package org.atricore.idbus.bundles.apache.derby;
import org.apache.derby.drda.NetworkServerControl;
import java.util.*;
import java.net.InetAddress;
import java.io.PrintWriter;
import org.apache.commons.logging.*;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.DisposableBean;
/**
* @author <a href="mailto:sgonzalez@atricore.org">Sebastian Gonzalez Oyuela</a>
* @version $Id$
*/
public class OsgiNetworkServerControl implements InitializingBean, DisposableBean {
private static Log logger = LogFactory.getLog(OsgiNetworkServerControl.class);
private Map<String, NetworkServer> servers = new HashMap<String, NetworkServer>();
private Set<NetworkServerDescriptor> serverDescriptors = new HashSet<NetworkServerDescriptor>();
private boolean running;
public OsgiNetworkServerControl() {
logger.debug("Creating Osgi based Derby Server Control component");
}
// Spring friendly methods
public Set<NetworkServerDescriptor> getServerDescriptors() {
return serverDescriptors;
}
// Spring friendly methods
public void setServerDescriptors(Set<NetworkServerDescriptor> serverDescriptors) {
this.serverDescriptors = serverDescriptors;
}
public synchronized void afterPropertiesSet() throws Exception {
logger.info("Starting Apache Derby OSGi Network server control ... ");
running = true;
for (NetworkServerDescriptor sd : serverDescriptors) {
NetworkServer server = servers.get(sd.getPort() + "");
if (server == null) {
server = new NetworkServer(sd.getPort() + "", sd);
this.servers.put(server.id, server);
}
}
for (NetworkServer server : servers.values()) {
if (!server.isStarted()) {
if (logger.isDebugEnabled())
logger.debug("Starting server " + server.getId());
server.start();
}
}
}
public synchronized void destroy() throws Exception {
logger.info("Stopping Apache Derby OSGi Network server control");
running = false;
for (NetworkServer server : servers.values()) {
if (server.isStarted()) {
if (logger.isDebugEnabled())
logger.debug("Stopping server " + server.getId());
server.stop();
}
}
}
public boolean isRunning() {
return running;
}
public void register(final NetworkServerDescriptor serverDescriptor, Map<String, ?> properties) throws Exception {
if (logger.isDebugEnabled())
logger.debug("Registering Network Server Descriptor " + serverDescriptor);
serverDescriptors.add(serverDescriptor);
if (isRunning()) {
NetworkServer server = new NetworkServer(serverDescriptor.getPort() + "", serverDescriptor);
this.servers.put(server.id, server);
if (logger.isDebugEnabled())
logger.debug("Starting server " + server.getId());
server.start();
}
}
public void unregister(final NetworkServerDescriptor serverDescriptor, Map<String, ?> properties) throws Exception {
if (logger.isDebugEnabled())
logger.debug("Unregistering Network Server Descriptor " + serverDescriptor);
NetworkServerDescriptor toRemove = null;
for (NetworkServerDescriptor sd : serverDescriptors) {
if (sd.getPort() == serverDescriptor.getPort()) {
toRemove = sd;
break;
}
}
if (toRemove != null)
serverDescriptors.remove(toRemove);
NetworkServer server = servers.remove(serverDescriptor.getPort() + "");
if (logger.isDebugEnabled())
logger.debug("Stoping server " + server.getId());
server.stop();
}
class NetworkServer {
private String id;
private NetworkServerDescriptor descriptor;
private NetworkServerControl derbyServer;
private boolean started;
NetworkServer(String id, NetworkServerDescriptor descriptor) throws Exception {
this.id = id;
this.descriptor = descriptor;
InetAddress address = InetAddress.getByName("localhost");
if (descriptor.getHostname() != null) {
address = InetAddress.getByName(descriptor.getHostname());
}
derbyServer = new NetworkServerControl(address,
descriptor.getPort(),
descriptor.getUsername(),
descriptor.getPassword());
}
public void start() {
try {
started = true;
logger.debug("Startup Derby Network Server..." + descriptor.getHostname() + ":" + descriptor.getPort());
// TODO : Send a different OS ?
derbyServer.start(new PrintWriter(System.err));
logger.debug("Startup Derby Network Server...OK ");
long timeout = descriptor.getTimeout() * 1000L;
long now = System.currentTimeMillis();
long expiration = now + timeout;
{
// Try to check if connection is OK.
while (now < expiration) {
try {
try { synchronized (this) { wait(300); } } catch (InterruptedException ierr) {/**/}
// This will trigger a connection to the server ...
Properties p = derbyServer.getCurrentProperties();
if (logger.isDebugEnabled()) {
for (Object key : p.keySet()) {
Object v = p.get(key);
logger.debug(getId() + ":" + key + "=" + v);
}
}
return;
} catch (Exception e) {
logger.debug(e.getMessage());
if (now > expiration) {
logger.debug(e.getMessage(), e);
throw e;
}
// wait for a second and try again
try { synchronized (this) { wait(1000); } } catch (InterruptedException ierr) {/**/}
}
// Update time
now = System.currentTimeMillis();
}
}
// Give up trying ... server is dead!
} catch (Exception e) {
logger.error("Cannot connect to DB Server " + e.getMessage(), e);
throw new RuntimeException(e);
}
}
public void stop() throws Exception {
logger.debug("Stop Derby Network Server..." + descriptor.getHostname() + ":" + descriptor.getPort());
started = false;
derbyServer.shutdown();
}
public boolean isStarted() {
return started;
}
public String getId() {
return id;
}
}
}