/*
* Copyright 2008 Glencoe Software, Inc. All rights reserved.
* Use is subject to license terms supplied in LICENSE.txt
*/
package ome.services.blitz.util;
import java.net.URL;
import ome.security.SecuritySystem;
import ome.services.blitz.fire.PermissionsVerifierI;
import ome.services.blitz.fire.Registry;
import ome.services.blitz.fire.Ring;
import ome.services.blitz.fire.SessionManagerI;
import ome.services.blitz.fire.TopicManager;
import ome.services.util.Executor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.FatalBeanException;
import org.springframework.util.ResourceUtils;
import Glacier2.PermissionsVerifier;
import Glacier2.SessionManager;
import Ice.Util;
/**
* Factory bean which creates an {@link Ice.Communicator} instance as well as the
* proper {@link Ice.ObjectAdapter} and adds initial, well-known servants.
*
* @author Josh Moore
* @since 3.0-Beta3.1
*/
public class BlitzConfiguration {
private final static String CONFIG_KEY = "--Ice.Config=";
private final Logger logger = LoggerFactory.getLogger(getClass());
private final Ring blitzRing;
private final Ice.Communicator communicator;
private final Ice.ObjectAdapter blitzAdapter;
private final SessionManagerI blitzManager;
private final PermissionsVerifier blitzVerifier;
private final Registry registry;
private final TopicManager topicManager;
private final Ice.InitializationData id;
private final Ice.ObjectPrx managerDirectProxy;
private final int servantsPerSession;
/**
* Single constructor which builds all Ice instances needed for the server
* runtime based on arguments provided. Once the constructor is finished,
* none of the default create* methods can safely be called, since
* {@link #throwIfInitialized(Object)} is called first.
*
* If any of the methods other than {@link #createCommunicator()} throws an
* exception, then {@link #destroy()} will be called to properly shut down
* the {@link Ice.Communicator} instance. Therefore {@link #destroy()}
* should be careful to check for nulls.
*/
public BlitzConfiguration(Ring ring,
ome.services.sessions.SessionManager sessionManager,
SecuritySystem securitySystem, Executor executor,
int servantsPerSession)
throws RuntimeException {
this(createId(), ring, sessionManager, securitySystem, executor,
servantsPerSession);
}
/**
* Like
* {@link #BlitzConfiguration(Ring, ome.services.sessions.SessionManager, SecuritySystem, Executor, int)}
* but allows properties to be specified via an
* {@link Ice.InitializationData} instance.
*
* @param id
* @param ring
* @param sessionManager
* @param securitySystem
* @param executor
* @param servantsPerSession
* @throws RuntimeException
*/
public BlitzConfiguration(Ice.InitializationData id, Ring ring,
ome.services.sessions.SessionManager sessionManager,
SecuritySystem securitySystem, Executor executor,
int servantsPerSession)
throws RuntimeException {
logger.info("Initializing Ice.Communicator");
this.id = id;
this.blitzRing = ring;
this.communicator = createCommunicator();
this.servantsPerSession = servantsPerSession;
if (communicator == null) {
throw new RuntimeException("No communicator cannot continue.");
}
try {
// This component is inert, and so can be created early.
registry = new Registry.Impl(this.communicator);
topicManager = new TopicManager.Impl(this.communicator);
blitzAdapter = createAdapter();
blitzManager = createAndRegisterManager(sessionManager,
securitySystem, executor);
blitzVerifier = createAndRegisterVerifier(sessionManager, executor);
managerDirectProxy = blitzAdapter.createDirectProxy(managerId());
blitzAdapter.activate();
// When using adapter methods from within the ring, it is necessary
// to start the adapter first.
blitzRing.setRegistry(registry);
blitzRing.init(blitzAdapter, communicator
.proxyToString(getDirectProxy()));
} catch (RuntimeException e) {
try {
destroy();
} catch (Exception e2) {
logger.error("Error destroying configuration after "
+ "initialization exception. "
+ "Throwing initialization exception", e2);
}
throw e;
}
}
/**
* If this configuration is finished and {@link #communicator} is not-null,
* throw a {@link IllegalStateException}
*/
protected final void throwIfInitialized(Object instance) {
if (instance != null) {
throw new IllegalStateException(
"Configuration has already taken place.");
}
}
protected Ice.Communicator createCommunicator() {
throwIfInitialized(communicator);
Ice.Communicator ic;
String ICE_CONFIG = System.getProperty("ICE_CONFIG");
if (ICE_CONFIG != null) {
// HORRIBLE HACK. Here we are short cutting the logic below
// since it is complicated and needs to be reduced. This works in
// tandem with the code in Main.main() which takes command line
// arguments.
id.properties.load(ICE_CONFIG);
}
ic = Ice.Util.initialize(id);
return ic;
}
protected Ice.Communicator createCommunicator(String configFile,
String[] arguments) {
throwIfInitialized(communicator);
if (configFile == null) {
throw new IllegalArgumentException("No config file given.");
}
configFile = resolveConfigFile(configFile);
if (logger.isInfoEnabled()) {
logger.info("Reading config file:" + configFile);
}
Ice.Communicator ic = null;
Ice.InitializationData id = new Ice.InitializationData();
if (arguments == null) {
id.properties = Util.createProperties(new String[] {});
} else {
for (int i = 0; i < arguments.length; i++) {
String s = arguments[i];
if (s != null && s.startsWith(CONFIG_KEY)) {
if (logger.isDebugEnabled()) {
logger.debug(String.format(
"Overriding args setting %s with %s", s,
configFile));
}
arguments[i] = CONFIG_KEY + configFile;
}
}
id.properties = Util.createProperties(arguments);
}
ic = Util.initialize(id);
return ic;
}
/**
* Resolve the given config file to a concrete location, possibly throwing
* an exception if stored in a jar. Null will not be returned, but an
* exception may be thrown if the path is invalid.
*/
protected String resolveConfigFile(String configFile) {
try {
URL file = ResourceUtils.getURL(configFile);
if (ResourceUtils.isJarURL(file)) {
throw new RuntimeException(configFile + " is in a jar: " + file);
} else {
configFile = file.getPath();
}
} catch (Exception e) {
throw new RuntimeException("Error resolving config file: "
+ configFile, e);
}
return configFile;
}
/**
* Creates an adapter with the name "BlitzAdapter", which must be properly
* configured via --Ice.Config or ICE_CONFIG or similar.
*/
protected Ice.ObjectAdapter createAdapter() {
throwIfInitialized(blitzAdapter);
Ice.ObjectAdapter adapter;
try {
adapter = communicator.createObjectAdapter("BlitzAdapter");
} catch (Exception e) {
// Possible Ice.IPv6 error
logger.error("Fatal error creating adapter. " +
"See the troubleshooting page", e);
throw new FatalBeanException(
"Could not find Ice config for object adapter [ BlitzAdapter ]");
}
return adapter;
}
protected SessionManagerI createAndRegisterManager(
ome.services.sessions.SessionManager sessionManager,
SecuritySystem securitySystem, Executor executor) {
throwIfInitialized(blitzManager);
SessionManagerI manager = new SessionManagerI(blitzRing, blitzAdapter,
securitySystem, sessionManager, executor, topicManager, registry,
servantsPerSession);
Ice.Identity id = managerId();
Ice.ObjectPrx prx = this.blitzAdapter.add(manager, id);
return manager;
}
protected PermissionsVerifier createAndRegisterVerifier(
ome.services.sessions.SessionManager sessionManager,
Executor executor) {
throwIfInitialized(blitzVerifier);
PermissionsVerifierI verifier = new PermissionsVerifierI(blitzRing,
sessionManager, executor, blitzRing.uuid);
this.blitzAdapter.add(verifier, Ice.Util
.stringToIdentity("BlitzVerifier"));
return verifier;
}
public void destroy() {
if (blitzRing != null) {
blitzRing.destroy();
}
logger.debug(String.format("Destroying Ice.Communicator (%s)",
communicator));
logger.info("Shutting down Ice.Communicator");
if (blitzAdapter != null) {
logger.debug(String.format("Deactivating BlitzAdapter (%s)",
blitzAdapter));
blitzAdapter.deactivate();
}
communicator.destroy();
}
// Getters
// =========================================================================
public Ring getRing() {
if (blitzRing == null) {
throw new IllegalStateException("Ring is null");
}
return blitzRing;
}
public Ice.Communicator getCommunicator() {
if (communicator == null) {
throw new IllegalStateException("Communicator is null");
}
return communicator;
}
public Ice.ObjectAdapter getBlitzAdapter() {
if (blitzAdapter == null) {
throw new IllegalStateException("Adapter is null");
}
return blitzAdapter;
}
public SessionManager getBlitzManager() {
if (blitzManager == null) {
throw new IllegalStateException("Manager is null");
}
return blitzManager;
}
public PermissionsVerifier getBlitzVerifier() {
if (blitzVerifier == null) {
throw new IllegalStateException("Verifier is null");
}
return blitzVerifier;
}
public Registry getRegistry() {
if (registry == null) {
throw new IllegalStateException("Registry is null");
}
return registry;
}
public TopicManager getTopicManager() {
if (topicManager == null) {
throw new IllegalStateException("TopicManager is null");
}
return topicManager;
}
/**
* Return a direct proxy to the session manager in this object adapter.
*/
public Ice.ObjectPrx getDirectProxy() {
if (managerDirectProxy == null) {
throw new IllegalStateException("Direct proxy is null");
}
return managerDirectProxy;
}
// Helpers
private static Ice.InitializationData createId() {
Ice.InitializationData iData = new Ice.InitializationData();
iData.properties = Ice.Util.createProperties();
return iData;
}
private Ice.Identity managerId() {
Ice.Identity id = Ice.Util.stringToIdentity("BlitzManager");
return id;
}
}