Add fallback default hazelcast.xml

- This enables running mvn test without running ./onos.sh setup.
- Specify HC_CONF value as JVM option to datagrid and datastore.
- Renamed method name to loadHazelcastConfig(), which better explain actual behavior.

Change-Id: Ib7d3d6a461dc60395b1f93e876f72428701c2347
diff --git a/conf/hazelcast.default.xml b/conf/hazelcast.default.xml
new file mode 100644
index 0000000..c6bb74d
--- /dev/null
+++ b/conf/hazelcast.default.xml
@@ -0,0 +1,107 @@
+<hazelcast xsi:schemaLocation="http://www.hazelcast.com/schema/config
+	http://www.hazelcast.com/schema/config/hazelcast-config-3.0.xsd"
+	xmlns="http://www.hazelcast.com/schema/config"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+
+  <properties>
+    <property name="hazelcast.logging.type">slf4j</property>
+    <property name="hazelcast.version.check.enabled">false</property>
+  </properties>
+
+  <network>
+    <port auto-increment="true">5701</port>
+    <join>
+<multicast enabled="false" />
+<tcp-ip enabled="true">
+  <member>127.0.0.1:5701</member>
+</tcp-ip>
+      <aws enabled="false">
+      </aws>
+    </join>
+  </network>
+
+  <!-- Configuration of maps used as a data store. -->
+  <map name="datastore://*">
+    <!-- must use 'sync' backup to imitate other data store -->
+    <backup-count>3</backup-count>
+    <async-backup-count>0</async-backup-count>
+    <!-- must be false for strong consistency -->
+    <read-backup-data>false</read-backup-data>
+    <!-- near cache must not be used -->
+  </map>
+
+  <map name="*">
+
+    <!--
+    Number of sync-backups. If 1 is set as the backup-count for example,
+    then all entries of the map will be copied to another JVM for
+    ail-safety. Valid numbers are 0 (no backup), 1, 2, 3.
+    -->
+    <backup-count>0</backup-count>
+
+    <!--
+    Number of async-backups. If 1 is set as the backup-count for example,
+    then all entries of the map will be copied to another JVM for
+    fail-safety. Valid numbers are 0 (no backup), 1, 2, 3.
+    -->
+    <async-backup-count>3</async-backup-count>
+
+    <!--
+    Can we read the local backup entries? Default value is false for
+    strong consistency. Being able to read backup data will give you
+    greater performance.
+    -->
+    <read-backup-data>true</read-backup-data>
+
+    <near-cache>
+      <!--
+	  Maximum size of the near cache. When max size is reached,
+	  cache is evicted based on the policy defined.
+	  Any integer between 0 and Integer.MAX_VALUE. 0 means
+	  Integer.MAX_VALUE. Default is 0.
+      -->
+      <max-size>0</max-size>
+      <!--
+	  Maximum number of seconds for each entry to stay in the near cache.
+	  Entries that are older than <time-to-live-seconds> will get
+	  automatically evicted from the near cache.
+	  Any integer between 0 and Integer.MAX_VALUE. 0 means infinite.
+	  Default is 0.
+      -->
+      <time-to-live-seconds>0</time-to-live-seconds>
+
+      <!--
+	  Maximum number of seconds each entry can stay in the near cache as
+	  untouched (not-read).
+	  Entries that are not read (touched) more than <max-idle-seconds>
+	  value will get removed from the near cache.
+	  Any integer between 0 and Integer.MAX_VALUE. 0 means
+	  Integer.MAX_VALUE. Default is 0.
+      -->
+      <max-idle-seconds>0</max-idle-seconds>
+
+      <!--
+	  Valid values are:
+	  NONE (no extra eviction, <time-to-live-seconds> may still apply),
+	  LRU (Least Recently Used),
+	  LFU (Least Frequently Used).
+	  LRU is the default.
+	  Regardless of the eviction policy used, <time-to-live-seconds> will
+	  still apply.
+      -->
+      <eviction-policy>NONE</eviction-policy>
+
+      <!--
+	  Should the cached entries get evicted if the entries are changed
+	  (updated or removed).
+	  true of false. Default is true.
+      -->
+      <invalidate-on-change>true</invalidate-on-change>
+
+    </near-cache>
+  </map>
+
+  <topic name="*">
+    <global-ordering-enabled>false</global-ordering-enabled>
+  </topic>
+</hazelcast>
diff --git a/onos.sh b/onos.sh
index e6d7d68..c4965ef 100755
--- a/onos.sh
+++ b/onos.sh
@@ -125,8 +125,6 @@
 
 JVM_OPTS="$JVM_OPTS -Dhazelcast.logging.type=slf4j"
 
-JVM_OPTS="${JVM_OPTS} -Dnet.onrc.onos.core.datagrid.HazelcastDatagrid.datagridConfig=${HC_CONF}"
-
 # Uncomment to dump final JVM flags to stdout
 #JVM_OPTS="$JVM_OPTS -XX:+PrintFlagsFinal"
 
@@ -779,9 +777,21 @@
     exit 1
   fi
 
+  if [ ! -f ${HC_CONF} ]; then
+    echo "[WARNING] ${HC_CONF} not found."
+    echo "          Run \"\$ $0 setup\" to create."
+    exit 1
+    fi
+
+  # specify hazelcast.xml to datagrid
+  JVM_OPTS="${JVM_OPTS} -Dnet.onrc.onos.core.datagrid.HazelcastDatagrid.datagridConfig=${HC_CONF}"
+
+  # specify backend config
   JVM_OPTS="${JVM_OPTS} -Dnet.onrc.onos.core.datastore.backend=${ONOS_HOST_BACKEND}"
   if [ "${ONOS_HOST_BACKEND}" = "ramcloud" ]; then
     JVM_OPTS="${JVM_OPTS} -Dramcloud.config.path=${RAMCLOUD_CONF}"
+  elif [ "${ONOS_HOST_BACKEND}" = "hazelcast" ]; then
+    JVM_OPTS="${JVM_OPTS} -Dnet.onrc.onos.core.datastore.hazelcast.baseConfig=${HC_CONF}"
   fi
 
   # Run ONOS
diff --git a/src/main/java/net/onrc/onos/core/datagrid/HazelcastDatagrid.java b/src/main/java/net/onrc/onos/core/datagrid/HazelcastDatagrid.java
index 7d2b7f3..5758b38 100644
--- a/src/main/java/net/onrc/onos/core/datagrid/HazelcastDatagrid.java
+++ b/src/main/java/net/onrc/onos/core/datagrid/HazelcastDatagrid.java
@@ -33,6 +33,7 @@
     private IRestApiService restApi;
 
     static final String HAZELCAST_CONFIG_FILE = "datagridConfig";
+    private static final String HAZELCAST_DEFAULT_XML = "conf/hazelcast.default.xml";
     private HazelcastInstance hazelcastInstance;
     private Config hazelcastConfig;
 
@@ -44,11 +45,11 @@
     private final Map<String, IEventChannel<?, ?>> eventChannels = new HashMap<>();
 
     /**
-     * Initialize the Hazelcast Datagrid operation.
+     * Load the Hazelcast Datagrid configuration file.
      *
      * @param configFilename the configuration filename.
      */
-    public void init(String configFilename) {
+    public void loadHazelcastConfig(String configFilename) {
         /*
         System.setProperty("hazelcast.socket.receive.buffer.size", "32");
         System.setProperty("hazelcast.socket.send.buffer.size", "32");
@@ -60,6 +61,16 @@
             hazelcastConfig = new FileSystemXmlConfig(configFilename);
         } catch (FileNotFoundException e) {
             log.error("Error opening Hazelcast XML configuration. File not found: " + configFilename, e);
+
+            // Fallback mechanism to support running unit test without setup.
+            log.error("Falling back to default Hazelcast XML {}", HAZELCAST_DEFAULT_XML);
+            try {
+                hazelcastConfig = new FileSystemXmlConfig(HAZELCAST_DEFAULT_XML);
+            } catch (FileNotFoundException e2) {
+                log.error("Error opening fall back Hazelcast XML configuration. "
+                        + "File not found: " + HAZELCAST_DEFAULT_XML, e2);
+                // XXX probably should throw some exception to kill ONOS instead.
+            }
         }
         /*
         hazelcastConfig.setProperty(GroupProperties.PROP_IO_THREAD_COUNT, "1");
@@ -145,7 +156,7 @@
         // Get the configuration file name and configure the Datagrid
         Map<String, String> configMap = context.getConfigParams(this);
         String configFilename = configMap.get(HAZELCAST_CONFIG_FILE);
-        this.init(configFilename);
+        this.loadHazelcastConfig(configFilename);
     }
 
     /**
diff --git a/src/main/java/net/onrc/onos/core/datastore/hazelcast/HZClient.java b/src/main/java/net/onrc/onos/core/datastore/hazelcast/HZClient.java
index 2b319a1..d3c303f 100644
--- a/src/main/java/net/onrc/onos/core/datastore/hazelcast/HZClient.java
+++ b/src/main/java/net/onrc/onos/core/datastore/hazelcast/HZClient.java
@@ -41,6 +41,7 @@
 
     // make this path configurable
     private static final String BASE_CONFIG_FILENAME = System.getProperty("net.onrc.onos.core.datastore.hazelcast.baseConfig", "conf/hazelcast.xml");
+    private static final String HAZELCAST_DEFAULT_XML = "conf/hazelcast.default.xml";
     private static boolean useClientMode = Boolean.parseBoolean(System.getProperty("net.onrc.onos.core.datastore.hazelcast.clientMode", "true"));
 
     // Note: xml configuration will overwrite this value if present
@@ -64,7 +65,18 @@
             baseHzConfig = new FileSystemXmlConfig(hazelcastConfigFileName);
         } catch (FileNotFoundException e) {
             log.error("Error opening Hazelcast XML configuration. File not found: " + hazelcastConfigFileName, e);
-            throw new Error("Cannot find Hazelcast configuration: " + hazelcastConfigFileName, e);
+            // Fallback mechanism to support running unit test without setup.
+            log.error("Falling back to default Hazelcast XML {}", HAZELCAST_DEFAULT_XML);
+            try {
+                baseHzConfig = new FileSystemXmlConfig(HAZELCAST_DEFAULT_XML);
+            } catch (FileNotFoundException e2) {
+                log.error("Error opening fall back Hazelcast XML configuration. "
+                        + "File not found: " + HAZELCAST_DEFAULT_XML, e2);
+
+                // intentionally throwing Exception "e" thrown from non-fallback
+                // Hazelcast configuration loading.
+                throw new Error("Cannot find Hazelcast configuration: " + hazelcastConfigFileName, e);
+            }
         }
 
         // use xml config if present, if not use System.property