-/*******************************************************************************\r
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.project.management;\r
-\r
-import java.io.File;\r
-import java.io.FileOutputStream;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.net.BindException;\r
-import java.net.Socket;\r
-import java.util.Collections;\r
-import java.util.HashMap;\r
-import java.util.Map;\r
-import java.util.Properties;\r
-\r
-import org.apache.log4j.Logger;\r
-import org.simantics.databoard.util.StreamUtil;\r
-import org.simantics.db.Driver;\r
-import org.simantics.db.Driver.Management;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.ServerEx;\r
-import org.simantics.db.ServerI;\r
-import org.simantics.db.ServiceLocator;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.WriteOnlyGraph;\r
-import org.simantics.db.common.request.ReadRequest;\r
-import org.simantics.db.common.request.WriteOnlyRequest;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.service.ClusterUID;\r
-import org.simantics.db.service.XSupport;\r
-import org.simantics.graph.db.CoreInitialization;\r
-import org.simantics.layer0.DatabaseManagementResource;\r
-import org.simantics.layer0.Layer0;\r
-\r
-/**\r
- * Server Manager handles starting and pooling of ProCore server instances.\r
- *\r
- * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
- */\r
-public class ServerManager {\r
-\r
- /** Default properties with default user and password */\r
- public static final Properties DEFAULT;\r
-\r
- /** Driver for database." */\r
- final Driver driver;\r
-\r
- /** Actual Server Instances. This object is synchronized by itself as lock. */\r
- Map<File, ServerHost> servers = Collections.synchronizedMap( new HashMap<File, ServerHost>() );\r
-\r
- /**\r
- * Create a new server manager.\r
- *\r
- * @param applicationDirectory location of org.simantics.db.build\r
- * @throws IOException\r
- */\r
- public ServerManager(Driver driver) throws IOException {\r
- this.driver = driver;\r
- }\r
- public Management getManagement(File dbFolder) throws DatabaseException {\r
- // We are using ProCoreDriver and know it's address format and security model. Not good!\r
- return driver.getManagement(dbFolder.getAbsolutePath(), null);\r
- }\r
- /**\r
- * Create a new database that is initialized with given graphs.\r
- * One of them must be layer0.\r
- * Database directory is created if it did not exist.\r
- *\r
- * @param databaseDirectory place where database is installed\r
- * @param initialGraphs initialGraphs to install\r
- * @throws DatabaseException\r
- */\r
- public Session createDatabase(File databaseDirectory) throws DatabaseException {\r
- try {\r
- Logger myLogger = Logger.getLogger(ServerManager.class);\r
- myLogger.debug("Creating database to "+ databaseDirectory);\r
-\r
- Session session = null;\r
- ServerEx server1 = getServer(databaseDirectory);\r
- server1.start();\r
- try {\r
- // This will initialize the fixed URIs and corresponding resources.\r
- // These are needed by the query system to parse URIs.\r
- // The server will generate the clusters for the generated resources.\r
- // The layer0 statements will be generated in phase two.\r
- // This will close the connection to server because the only thing\r
- // you can do with this connection is to initialize the fixed URIs.\r
- Properties info = new Properties();\r
- info.setProperty("user", "Default User");\r
- info.setProperty("password", "");\r
- session = server1.createSession(info);\r
- XSupport xs = session.getService(XSupport.class);\r
- ClusterUID[] clusters = xs.listClusters();\r
- if (clusters.length > 1) {// Database contain clusters, assuming initialization is done.");\r
- ReadRequest req = new ReadRequest() {\r
- @Override\r
- public void run(ReadGraph g) {\r
- // Registers Layer0 with the session ServiceLocator.\r
- Layer0.getInstance(g);\r
- }\r
- };\r
- session.syncRequest(req);\r
- return session;\r
- }\r
- CoreInitialization.initializeBuiltins(session);\r
- // This will try to initialize Builtins.class but because there is no statements\r
- // in the server only the previously added fixed URIs are found.\r
- // If we'd want to get rid of the missing layer0 URI warnings then\r
- // a non initialized session should be used to add graph statements\r
- // without using Builtins.class at all or by initializing Builtins.class\r
- // only with the fixed URIs.\r
- session.getService(XSupport.class).setServiceMode(true, true);\r
-\r
- // This will add layer0 statements. The query mechanism is not\r
- // yet totally functional because there is no statements in the\r
- // server. Mainly WriteOnly request is available here.\r
- GraphBundle l0 = PlatformUtil.getGraph("org.simantics.layer0");\r
- final GraphBundleEx l0ex = GraphBundleEx.extend(l0);\r
- l0ex.build();\r
- long[] resourceArray = CoreInitialization.initializeGraph(session, l0ex.getGraph());\r
- l0ex.setResourceArray(resourceArray);\r
- session.getService(XSupport.class).setServiceMode(true, true);\r
-\r
- DatabaseManagementResource.getInstance(session);\r
- Layer0.getInstance(session);\r
- session.syncRequest(new WriteOnlyRequest() {\r
- @Override\r
- public void perform(WriteOnlyGraph graph) throws DatabaseException {\r
- // Root Library is a cluster set\r
- graph.newClusterSet(graph.getRootLibrary());\r
- DatabaseManagement mgt = new DatabaseManagement();\r
- mgt.createGraphBundle(graph, l0ex);\r
- graph.flushCluster();\r
- }});\r
- return session;\r
- } finally {\r
- if (null == session)\r
- server1.stop();\r
- }\r
- } catch (Exception e) {\r
- throw new DatabaseException("Failed to create Simantics database.", e);\r
- }\r
- }\r
-\r
- /**\r
- * Get a server that can be started and stopped.\r
- *\r
- * The result is actually a proxy server. Each successful start() increases\r
- * reference count and stop() decreases. The actual server is closed\r
- * once all proxies are closed.\r
- *\r
- * @param databaseDirectory\r
- * @return server\r
- * @throws DatabaseException\r
- */\r
- private ServerEx getServer(File databaseDirectory) throws DatabaseException {\r
- File file = databaseDirectory.getAbsoluteFile();\r
-\r
- ServerHost host = null;\r
- synchronized(servers) {\r
- host = servers.get(file);\r
- if (host==null) {\r
- // Instantiate actual server. We are using ProCoreDriver and know it's address format and security model. Not good!\r
- ServerI server = driver.getServer(file.getAbsolutePath(), null);\r
-\r
- try {\r
- host = new ServerHost(server, databaseDirectory);\r
- } catch (IOException e) {\r
- throw new DatabaseException("Failed to load " + databaseDirectory, e);\r
- }\r
-\r
- servers.put(file, host);\r
- }\r
- }\r
-\r
- ServerEx proxy = new ProxyServer(host);\r
- return proxy;\r
- }\r
-\r
- /**\r
- * @param parseUnresolved\r
- * @return\r
- */\r
-// public ServerEx getServer(ServerAddress endpoint) {\r
-// return new ConnectedServer(endpoint);\r
-// }\r
-\r
- /**\r
- * Close the server manager, close all servers.\r
- * Deletes temporary files.\r
- */\r
- public void close() {\r
- synchronized(servers) {\r
- for (ServerHost host : servers.values()) {\r
- ServerI server = host.actual;\r
- try {\r
- if (server.isActive())\r
- server.stop();\r
- } catch (DatabaseException e) {\r
- Logger myLogger = Logger.getLogger(ServerManager.class);\r
- myLogger.error(e);\r
- }\r
- }\r
- servers.clear();\r
- }\r
- }\r
-\r
- public static int getFreeEphemeralPort() {\r
- while(true) {\r
- try {\r
- Socket s = null;\r
- try {\r
- s = new Socket();\r
- s.bind(null);\r
- return s.getLocalPort();\r
- } finally {\r
- if (s != null)\r
- s.close();\r
- }\r
- } catch(BindException e) {\r
- // Nothing to do, try next port\r
- } catch (Throwable e) {\r
- throw new Error(e);\r
- }\r
- }\r
- }\r
-\r
- public static void createServerConfig(File file) throws IOException {\r
- InputStream is = ServerManager.class.getResourceAsStream("server_template.cnfg");\r
- byte[] data = StreamUtil.readFully(is);\r
- is.close();\r
-\r
- FileOutputStream os = new FileOutputStream(file, false);\r
- os.write(data);\r
- Properties properties = new Properties();\r
- properties.store(os, "# automatically generated properties");\r
- os.close();\r
- }\r
-\r
- /**\r
- * ServerHost hosts a ServerI instance. For each successful start() a\r
- * reference count is increased and each stop() & kill() it is decreased.\r
- */\r
- class ServerHost implements ServerEx {\r
-\r
- File database;\r
- ServerI actual;\r
- int refCount = 0;\r
- Properties properties;\r
-\r
- public ServerHost(ServerI actual, File database)\r
- throws IOException {\r
- this.actual = actual;\r
- this.database = database;\r
- this.properties = new Properties();\r
- }\r
-\r
- public File getDatabase() {\r
- return database;\r
- }\r
-\r
- /**\r
- * Get properties\r
- * @return properties\r
- */\r
- public Properties getProperties() {\r
- return properties;\r
- }\r
-\r
- @Override\r
- public String getAddress()\r
- throws DatabaseException {\r
- return actual.getAddress();\r
- }\r
-\r
-// @Override\r
-// public synchronized ServerAddress getServerAddress()\r
-// throws DatabaseException {\r
-// throw new DatabaseException("ServerHost.getServerAddress is not supported. Use getAddress instead.");\r
-// }\r
-\r
- @Override\r
- public boolean isActive() {\r
- try {\r
- return actual.isActive();\r
- } catch (DatabaseException e) {\r
- return false;\r
- }\r
- }\r
-\r
- /**\r
- * Start server if refCount = 0. If running or start was successful\r
- * the refcount is increased.\r
- *\r
- * For each succesful start(), a stop() or kill() is expected.\r
- */\r
- @Override\r
- public void start() throws DatabaseException {\r
- boolean isRunning = actual.isActive();\r
-\r
- if (!isRunning) {\r
- actual.start();\r
- }\r
-\r
- refCount++;\r
- }\r
-\r
- @Override\r
- public void stop() throws DatabaseException {\r
- if (refCount <= 0)\r
- throw new DatabaseException("Trying to stop a standing process.");\r
- refCount--;\r
- if (refCount > 1)\r
- return;\r
- actual.stop();\r
- }\r
-\r
- @Override\r
- public Session createSession(Properties properties) throws DatabaseException {\r
- return driver.getSession(actual.getAddress(), properties);\r
- }\r
-\r
- @Override\r
- public ServiceLocator getServiceLocator(Properties info) throws DatabaseException {\r
- return createSession(info);\r
- }\r
-\r
- @Override\r
- public String execute(String command) throws DatabaseException {\r
- return actual.execute(command);\r
- }\r
-\r
- @Override\r
- public String executeAndDisconnect(String command) throws DatabaseException {\r
- return actual.executeAndDisconnect(command);\r
- }\r
- }\r
-\r
- /**\r
- * Proxy Server starts actual server (ServerHost) when first start():ed,\r
- * and closes the actual server once all proxy servers are closed.\r
- *\r
- * @author Toni Kalajainen <toni.kalajainen@vtt.fi>\r
- */\r
- public class ProxyServer implements ServerEx {\r
-\r
- boolean running;\r
- ServerHost actual;\r
-\r
- public ProxyServer(ServerHost actual) {\r
- this.actual = actual;\r
- }\r
-\r
- public File getDatabase() {\r
- return actual.getDatabase();\r
- }\r
-\r
- /**\r
- * Get server properties\r
- *\r
- * @return properties\r
- * @throws IOException\r
- */\r
- public Properties getProperties() {\r
- return actual.getProperties();\r
- }\r
-\r
- @Override\r
- public String getAddress()\r
- throws DatabaseException {\r
- return actual.getAddress();\r
- }\r
-\r
-// @Override\r
-// public synchronized ServerAddress getServerAddress()\r
-// throws DatabaseException {\r
-// return actual.getServerAddress();\r
-// }\r
-\r
- @Override\r
- public boolean isActive() {\r
- return running && actual.isActive();\r
- }\r
-\r
- @Override\r
- public void start() throws DatabaseException {\r
- if (running) return;\r
- actual.start();\r
- running = true;\r
- }\r
-\r
- @Override\r
- public void stop() throws DatabaseException {\r
- if (!running) return;\r
- actual.stop();\r
- running = false;\r
- }\r
-\r
- @Override\r
- public Session createSession(Properties properties) throws DatabaseException {\r
- return driver.getSession(actual.getAddress(), properties);\r
- }\r
-\r
- @Override\r
- public ServiceLocator getServiceLocator(Properties info) throws DatabaseException {\r
- return createSession(info);\r
- }\r
-\r
- @Override\r
- public String execute(String command) throws DatabaseException {\r
- return actual.execute(command);\r
- }\r
-\r
- @Override\r
- public String executeAndDisconnect(String command) throws DatabaseException {\r
- return actual.executeAndDisconnect(command);\r
- }\r
- }\r
-\r
-// public class ConnectedServer implements ServerEx {\r
-//\r
-// ServerAddress endpoint;\r
-//\r
-// public ConnectedServer(ServerAddress endpoint) {\r
-// this.endpoint = endpoint;\r
-// }\r
-//\r
-// @Override\r
-// public void start() throws DatabaseException {\r
-// // Intentional NOP. Cannot control through socket.\r
-// }\r
-//\r
-// @Override\r
-// public void stop() throws DatabaseException {\r
-// // Intentional NOP. Cannot control through socket.\r
-// }\r
-//\r
-// @Override\r
-// public boolean isActive() {\r
-// // Without better knowledge\r
-// return true;\r
-// }\r
-//\r
-// @Override\r
-// public String getAddress()\r
-// throws DatabaseException {\r
-// return endpoint.getDbid();\r
-// }\r
-//\r
-// @Override\r
-// public synchronized ServerAddress getServerAddress()\r
-// throws DatabaseException {\r
-// return new ServerAddress(endpoint.getAddress());\r
-// }\r
-//\r
-// @Override\r
-// public Session createSession(Properties properties)\r
-// throws DatabaseException {\r
-// return driver.getSession(getServerAddress().toString(), properties);\r
-// }\r
-//\r
-// @Override\r
-// public ServiceLocator getServiceLocator(Properties info) throws DatabaseException {\r
-// return createSession(info);\r
-// }\r
-//\r
-// @Override\r
-// public String execute(String command) throws DatabaseException {\r
-// // Intentional NOP. Cannot control through socket.\r
-// return null;\r
-// }\r
-//\r
-// @Override\r
-// public String executeAndDisconnect(String command) throws DatabaseException {\r
-// // Intentional NOP. Cannot control through socket.\r
-// return null;\r
-// }\r
-// }\r
-\r
- static {\r
- DEFAULT = new Properties();\r
- DEFAULT.setProperty("user", "Default User");\r
- DEFAULT.setProperty("password", "");\r
- }\r
-\r
-}\r
-\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.project.management;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.BindException;
+import java.net.Socket;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.simantics.databoard.util.StreamUtil;
+import org.simantics.db.Driver;
+import org.simantics.db.Driver.Management;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.ServerEx;
+import org.simantics.db.ServerI;
+import org.simantics.db.ServiceLocator;
+import org.simantics.db.Session;
+import org.simantics.db.WriteOnlyGraph;
+import org.simantics.db.common.request.ReadRequest;
+import org.simantics.db.common.request.WriteOnlyRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.service.ClusterUID;
+import org.simantics.db.service.XSupport;
+import org.simantics.graph.db.CoreInitialization;
+import org.simantics.layer0.DatabaseManagementResource;
+import org.simantics.layer0.Layer0;
+import org.simantics.project.SessionDescriptor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Server Manager handles starting and pooling of ProCore server instances.
+ *
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
+ */
+public class ServerManager {
+ private static final Logger LOGGER = LoggerFactory.getLogger(ServerManager.class);
+
+ /** Default properties with default user and password */
+ public static final Properties DEFAULT;
+
+ /** Driver for database." */
+ final Driver driver;
+
+ /** Actual Server Instances. This object is synchronized by itself as lock. */
+ Map<File, ServerHost> servers = Collections.synchronizedMap( new HashMap<File, ServerHost>() );
+
+ /**
+ * Create a new server manager.
+ *
+ * @param applicationDirectory location of org.simantics.db.build
+ * @throws IOException
+ */
+ public ServerManager(Driver driver) throws IOException {
+ this.driver = driver;
+ }
+ public Management getManagement(File dbFolder) throws DatabaseException {
+ // We are using ProCoreDriver and know it's address format and security model. Not good!
+ return driver.getManagement(dbFolder.getAbsolutePath(), null);
+ }
+ /**
+ * Create a new database that is initialized with given graphs.
+ * One of them must be layer0.
+ * Database directory is created if it did not exist.
+ *
+ * @param databaseDirectory place where database is installed
+ * @param initialGraphs initialGraphs to install
+ * @throws DatabaseException
+ */
+ public SessionDescriptor createDatabase(File databaseDirectory) throws DatabaseException {
+ try {
+ LOGGER.debug("Creating database to "+ databaseDirectory);
+
+ Session session = null;
+ ServerEx server1 = getServer(databaseDirectory);
+ server1.start();
+ try {
+ // This will initialize the fixed URIs and corresponding resources.
+ // These are needed by the query system to parse URIs.
+ // The server will generate the clusters for the generated resources.
+ // The layer0 statements will be generated in phase two.
+ // This will close the connection to server because the only thing
+ // you can do with this connection is to initialize the fixed URIs.
+ Properties info = new Properties();
+ info.setProperty("user", "Default User");
+ info.setProperty("password", "");
+ session = server1.createSession(info);
+ XSupport xs = session.getService(XSupport.class);
+ ClusterUID[] clusters = xs.listClusters();
+ if (clusters.length > 1) {// Database contain clusters, assuming initialization is done.");
+ ReadRequest req = new ReadRequest() {
+ @Override
+ public void run(ReadGraph g) {
+ // Registers Layer0 with the session ServiceLocator.
+ Layer0.getInstance(g);
+ }
+ };
+ session.syncRequest(req);
+ return new SessionDescriptor(session, false);
+ }
+ CoreInitialization.initializeBuiltins(session);
+ // This will try to initialize Builtins.class but because there is no statements
+ // in the server only the previously added fixed URIs are found.
+ // If we'd want to get rid of the missing layer0 URI warnings then
+ // a non initialized session should be used to add graph statements
+ // without using Builtins.class at all or by initializing Builtins.class
+ // only with the fixed URIs.
+ session.getService(XSupport.class).setServiceMode(true, true);
+
+ // This will add layer0 statements. The query mechanism is not
+ // yet totally functional because there is no statements in the
+ // server. Mainly WriteOnly request is available here.
+ GraphBundle l0 = PlatformUtil.getGraph("org.simantics.layer0");
+ final GraphBundleEx l0ex = GraphBundleEx.extend(l0);
+ l0ex.build();
+ long[] resourceArray = CoreInitialization.initializeGraph(session, l0ex.getGraph());
+ l0ex.setResourceArray(resourceArray);
+ session.getService(XSupport.class).setServiceMode(true, true);
+
+ DatabaseManagementResource.getInstance(session);
+ Layer0.getInstance(session);
+ session.syncRequest(new WriteOnlyRequest() {
+ @Override
+ public void perform(WriteOnlyGraph graph) throws DatabaseException {
+ // Root Library is a cluster set
+ graph.newClusterSet(graph.getRootLibrary());
+ DatabaseManagement mgt = new DatabaseManagement();
+ mgt.createGraphBundle(graph, l0ex);
+ graph.flushCluster();
+ }});
+ return new SessionDescriptor(session, true);
+ } finally {
+ if (null == session)
+ server1.stop();
+ }
+ } catch (Exception e) {
+ throw new DatabaseException("Failed to create Simantics database.", e);
+ }
+ }
+
+ /**
+ * Get a server that can be started and stopped.
+ *
+ * The result is actually a proxy server. Each successful start() increases
+ * reference count and stop() decreases. The actual server is closed
+ * once all proxies are closed.
+ *
+ * @param databaseDirectory
+ * @return server
+ * @throws DatabaseException
+ */
+ private ServerEx getServer(File databaseDirectory) throws DatabaseException {
+ File file = databaseDirectory.getAbsoluteFile();
+
+ ServerHost host = null;
+ synchronized(servers) {
+ host = servers.get(file);
+ if (host==null) {
+ // Instantiate actual server. We are using ProCoreDriver and know it's address format and security model. Not good!
+ ServerI server = driver.getServer(file.getAbsolutePath(), null);
+
+ try {
+ host = new ServerHost(server, databaseDirectory);
+ } catch (IOException e) {
+ throw new DatabaseException("Failed to load " + databaseDirectory, e);
+ }
+
+ servers.put(file, host);
+ }
+ }
+
+ ServerEx proxy = new ProxyServer(host);
+ return proxy;
+ }
+
+ /**
+ * @param parseUnresolved
+ * @return
+ */
+// public ServerEx getServer(ServerAddress endpoint) {
+// return new ConnectedServer(endpoint);
+// }
+
+ /**
+ * Close the server manager, close all servers.
+ * Deletes temporary files.
+ */
+ public void close() {
+ synchronized(servers) {
+ for (ServerHost host : servers.values()) {
+ ServerI server = host.actual;
+ try {
+ if (server.isActive())
+ server.stop();
+ } catch (DatabaseException e) {
+ LOGGER.error("Failed to stop database server.", e);
+ }
+ }
+ servers.clear();
+ }
+ }
+
+ public static int getFreeEphemeralPort() {
+ while(true) {
+ try {
+ Socket s = null;
+ try {
+ s = new Socket();
+ s.bind(null);
+ return s.getLocalPort();
+ } finally {
+ if (s != null)
+ s.close();
+ }
+ } catch(BindException e) {
+ // Nothing to do, try next port
+ } catch (Throwable e) {
+ throw new Error(e);
+ }
+ }
+ }
+
+ public static void createServerConfig(File file) throws IOException {
+ InputStream is = ServerManager.class.getResourceAsStream("server_template.cnfg");
+ byte[] data = StreamUtil.readFully(is);
+ is.close();
+
+ FileOutputStream os = new FileOutputStream(file, false);
+ os.write(data);
+ Properties properties = new Properties();
+ properties.store(os, "# automatically generated properties");
+ os.close();
+ }
+
+ /**
+ * ServerHost hosts a ServerI instance. For each successful start() a
+ * reference count is increased and each stop() & kill() it is decreased.
+ */
+ class ServerHost implements ServerEx {
+
+ File database;
+ ServerI actual;
+ int refCount = 0;
+ Properties properties;
+
+ public ServerHost(ServerI actual, File database)
+ throws IOException {
+ this.actual = actual;
+ this.database = database;
+ this.properties = new Properties();
+ }
+
+ public File getDatabase() {
+ return database;
+ }
+
+ /**
+ * Get properties
+ * @return properties
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ @Override
+ public String getAddress()
+ throws DatabaseException {
+ return actual.getAddress();
+ }
+
+// @Override
+// public synchronized ServerAddress getServerAddress()
+// throws DatabaseException {
+// throw new DatabaseException("ServerHost.getServerAddress is not supported. Use getAddress instead.");
+// }
+
+ @Override
+ public boolean isActive() {
+ try {
+ return actual.isActive();
+ } catch (DatabaseException e) {
+ return false;
+ }
+ }
+
+ /**
+ * Start server if refCount = 0. If running or start was successful
+ * the refcount is increased.
+ *
+ * For each succesful start(), a stop() or kill() is expected.
+ */
+ @Override
+ public void start() throws DatabaseException {
+ boolean isRunning = actual.isActive();
+
+ if (!isRunning) {
+ actual.start();
+ }
+
+ refCount++;
+ }
+
+ @Override
+ public void stop() throws DatabaseException {
+ if (refCount <= 0)
+ throw new DatabaseException("Trying to stop a standing process.");
+ refCount--;
+ if (refCount > 1)
+ return;
+ actual.stop();
+ }
+
+ @Override
+ public Session createSession(Properties properties) throws DatabaseException {
+ return driver.getSession(actual.getAddress(), properties);
+ }
+
+ @Override
+ public ServiceLocator getServiceLocator(Properties info) throws DatabaseException {
+ return createSession(info);
+ }
+
+ @Override
+ public String execute(String command) throws DatabaseException {
+ return actual.execute(command);
+ }
+
+ @Override
+ public String executeAndDisconnect(String command) throws DatabaseException {
+ return actual.executeAndDisconnect(command);
+ }
+ }
+
+ /**
+ * Proxy Server starts actual server (ServerHost) when first start():ed,
+ * and closes the actual server once all proxy servers are closed.
+ *
+ * @author Toni Kalajainen <toni.kalajainen@vtt.fi>
+ */
+ public class ProxyServer implements ServerEx {
+
+ boolean running;
+ ServerHost actual;
+
+ public ProxyServer(ServerHost actual) {
+ this.actual = actual;
+ }
+
+ public File getDatabase() {
+ return actual.getDatabase();
+ }
+
+ /**
+ * Get server properties
+ *
+ * @return properties
+ * @throws IOException
+ */
+ public Properties getProperties() {
+ return actual.getProperties();
+ }
+
+ @Override
+ public String getAddress()
+ throws DatabaseException {
+ return actual.getAddress();
+ }
+
+// @Override
+// public synchronized ServerAddress getServerAddress()
+// throws DatabaseException {
+// return actual.getServerAddress();
+// }
+
+ @Override
+ public boolean isActive() {
+ return running && actual.isActive();
+ }
+
+ @Override
+ public void start() throws DatabaseException {
+ if (running) return;
+ actual.start();
+ running = true;
+ }
+
+ @Override
+ public void stop() throws DatabaseException {
+ if (!running) return;
+ actual.stop();
+ running = false;
+ }
+
+ @Override
+ public Session createSession(Properties properties) throws DatabaseException {
+ return driver.getSession(actual.getAddress(), properties);
+ }
+
+ @Override
+ public ServiceLocator getServiceLocator(Properties info) throws DatabaseException {
+ return createSession(info);
+ }
+
+ @Override
+ public String execute(String command) throws DatabaseException {
+ return actual.execute(command);
+ }
+
+ @Override
+ public String executeAndDisconnect(String command) throws DatabaseException {
+ return actual.executeAndDisconnect(command);
+ }
+ }
+
+// public class ConnectedServer implements ServerEx {
+//
+// ServerAddress endpoint;
+//
+// public ConnectedServer(ServerAddress endpoint) {
+// this.endpoint = endpoint;
+// }
+//
+// @Override
+// public void start() throws DatabaseException {
+// // Intentional NOP. Cannot control through socket.
+// }
+//
+// @Override
+// public void stop() throws DatabaseException {
+// // Intentional NOP. Cannot control through socket.
+// }
+//
+// @Override
+// public boolean isActive() {
+// // Without better knowledge
+// return true;
+// }
+//
+// @Override
+// public String getAddress()
+// throws DatabaseException {
+// return endpoint.getDbid();
+// }
+//
+// @Override
+// public synchronized ServerAddress getServerAddress()
+// throws DatabaseException {
+// return new ServerAddress(endpoint.getAddress());
+// }
+//
+// @Override
+// public Session createSession(Properties properties)
+// throws DatabaseException {
+// return driver.getSession(getServerAddress().toString(), properties);
+// }
+//
+// @Override
+// public ServiceLocator getServiceLocator(Properties info) throws DatabaseException {
+// return createSession(info);
+// }
+//
+// @Override
+// public String execute(String command) throws DatabaseException {
+// // Intentional NOP. Cannot control through socket.
+// return null;
+// }
+//
+// @Override
+// public String executeAndDisconnect(String command) throws DatabaseException {
+// // Intentional NOP. Cannot control through socket.
+// return null;
+// }
+// }
+
+ static {
+ DEFAULT = new Properties();
+ DEFAULT.setProperty("user", "Default User");
+ DEFAULT.setProperty("password", "");
+ }
+
+}
+