package com.c2kernel.process;
/**
* @version $Revision: 1.17 $ $Date: 2005/10/12 12:51:54 $
* @author $Author: abranson $
*/
import java.net.MalformedURLException;
import java.util.Enumeration;
import java.util.Properties;
import com.c2kernel.common.InvalidDataException;
import com.c2kernel.common.ObjectNotFoundException;
import com.c2kernel.entity.CorbaServer;
import com.c2kernel.entity.proxy.AgentProxy;
import com.c2kernel.entity.proxy.EntityProxyManager;
import com.c2kernel.lookup.AgentPath;
import com.c2kernel.lookup.LDAPLookup;
import com.c2kernel.lookup.LDAPProperties;
import com.c2kernel.persistency.ClusterStorageException;
import com.c2kernel.persistency.TransactionManager;
import com.c2kernel.process.module.ModuleManager;
import com.c2kernel.utils.CastorXMLUtility;
import com.c2kernel.utils.FileStringUtility;
import com.c2kernel.utils.Language;
import com.c2kernel.utils.Logger;
import com.c2kernel.utils.Resource;
/**************************************************************************
* The Gateway is the central object of a CRISTAL process. It initializes,
* maintains and shuts down every other subsystem in both the client and the
* server.
*
* Child objects:
*
* - LDAPLookup - Provides access to the CRISTAL directory. Find or
* search for Items or Agents.
*
- EntityProxyManager - Gives a local proxy object for Entities found
* in LDAP. Execute activities in Items, query or subscribe to Entity data.
*
- TransactionManager - Access to the configured CRISTAL databases
*
- CorbaServer - Manages the memory pool of active Entities
*
- mORB - the Orbacus CORBA ORB
*
*
* @author $Author: abranson $ $Date: 2005/10/12 12:51:54 $
* @version $Revision: 1.17 $
**************************************************************************/
public class Gateway
{
static private Properties mC2KProps;
static private ModuleManager mModules;
static private org.omg.CORBA.ORB mORB;
static private LDAPLookup mLDAPLookup;
static private TransactionManager mStorage;
static private EntityProxyManager mProxyManager;
static private CorbaServer mCorbaServer;
static private CastorXMLUtility mMarshaller;
//static private SimpleTCPIPServer mHTTPServer;
private Gateway() { }
/**
* Initialises the Gateway and all of the client objects it holds, with
* the exception of the LDAPLookup, which is initialised during connect()
*
* @param props - java.util.Properties containing all application properties.
* If null, the java system properties are used
* @throws InvalidDataException - invalid properties caused a failure in initialisation
*/
static public void init(Properties props, boolean isServer) throws InvalidDataException {
// Init properties
mC2KProps = new Properties();
// report version info
Logger.msg("Kernel version: "+Resource.getKernelVersion());
// load kernel mapfiles
try {
mMarshaller = new CastorXMLUtility(Resource.getKernelResourceURL("mapFiles/"));
} catch (MalformedURLException e1) {
throw new InvalidDataException("Invalid Resource Location", "");
}
// init module manager
try {
mModules = new ModuleManager(ClassLoader.getSystemResources("META-INF/cristal/module.xml"), isServer);
} catch (Exception e) {
Logger.error(e);
throw new InvalidDataException("Could not load module definitions.", "");
}
// merge in module props
Properties moduleProperties = mModules.getAllModuleProperties();
for (Enumeration> e = moduleProperties.propertyNames(); e.hasMoreElements();) {
String propName = (String)e.nextElement();
mC2KProps.put(propName, moduleProperties.get(propName));
}
// Overwrite with argument props
if (props != null) mC2KProps.putAll(props);
// dump properties
dumpC2KProps(7);
//Initialise language file
String languageFile = getProperty("language.file");
if (languageFile != null && languageFile.length() > 0) {
Language.isTranlated=true;
Language.mTableOfTranslation = FileStringUtility.loadLanguageFile(languageFile);
}
// run module startup scripts
mModules.runScripts("startup");
}
/**
* Makes this process capable of creating and managing server entities. Runs the
* bootstrap to create the root LDAP contexts, initialises the CORBA server and
* time-out manager.
*
* @throws InvalidDataException - error initialising
*/
static public void startServer() throws InvalidDataException {
try {
// check top level LDAP contexts
mLDAPLookup.install();
// start entity proxy server
EntityProxyManager.initServer();
// Init ORB - set various config to sys properties
java.util.Properties sysProps = System.getProperties();
String serverName = getProperty("ItemServer.name");
if (serverName != null)
sysProps.put("com.sun.CORBA.ORBServerHost", serverName);
String serverPort = getProperty("ItemServer.iiop", "1500");
sysProps.put("com.sun.CORBA.ORBServerPort", serverPort);
//TODO: externalize this (or replace corba completely)
sysProps.put("com.sun.CORBA.POA.ORBServerId", "1");
sysProps.put("com.sun.CORBA.POA.ORBPersistentServerPort", serverPort);
//Standard initialisation of the ORB
mORB = org.omg.CORBA.ORB.init(new String[0], sysProps);
Logger.msg("Gateway.init() - ORB initialised. ORB is " + mORB.getClass().getName() );
// start corba server components
mCorbaServer = new CorbaServer();
// start checking bootstrap & module items
Bootstrap.run();
} catch (Exception ex) {
Logger.error(ex);
Logger.die("Exception starting server components. Shutting down.");
}
// start the http server
// try {
// int httpPort = Integer.parseInt(Gateway.getProperty("ItemServer.HTTP.port"));
// Logger.msg(2, "Starting HTTP Server on port "+httpPort);
// mHTTPServer = new SimpleTCPIPServer(httpPort, ItemHTTPBridge.class, 5);
// mHTTPServer.startListening();
// } catch (NumberFormatException ex) {
// Logger.msg(3, "Invalid or no HTTP port defined. HTTP server not available.");
// }
System.out.println("Server '"+Gateway.getCentreId()+"' initialised.");
}
public static ModuleManager getModuleManager() {
return mModules;
}
/**
* Connects to the LDAP server in an administrative context - using the admin username and
* password given in the LDAP.user and LDAP.password props of the kernel properties.
*
* @throws InvalidDataException - bad params
* @throws ClusterStorageException - error starting storages
*/
static public void connect()
throws InvalidDataException,
ClusterStorageException
{
LDAPProperties ldapProps = new LDAPProperties();
if( ldapProps.mHost != null && ldapProps.mPort != null &&
ldapProps.mUser != null && ldapProps.mPassword != null )
{
try
{
mLDAPLookup = new LDAPLookup(ldapProps);
}
catch (Exception ex)
{
Logger.error(ex);
throw new InvalidDataException("Cannot authenticate. Name and/or password invalid.", "");
}
}
else
{
Logger.error("LDAP not configured properly.");
throw new InvalidDataException("Cannot authenticate. Name and/or password invalid.", "");
}
setup();
}
/**
* Authenticates a user and returns and AgentProxy on them without overriding the system LDAP context.
* Useful for handling multiple users in one context e.g. on a web server
*
* @param agentName - username
* @param agentPassword - password
* @return AgentProxy on that user
* @throws InvalidDataException
* @throws ObjectNotFoundException
*/
static public AgentProxy login(String agentName, String agentPassword) throws InvalidDataException, ObjectNotFoundException {
LDAPProperties ldapProps = new LDAPProperties();
AgentPath agentPath;
try {
agentPath = mLDAPLookup.getRoleManager().getAgentPath(agentName);
} catch (Exception ex) {
Logger.error(ex);
throw new ObjectNotFoundException("Could not resolve agent", "");
}
String agentDN = agentPath.getFullDN();
ldapProps.mUser = agentDN;
ldapProps.mPassword = agentPassword;
try {
LDAPLookup.createConnection(ldapProps);
return (AgentProxy)getProxyManager().getProxy(mLDAPLookup.getRoleManager().getAgentPath(agentName));
} catch (Exception ex) {
Logger.error(ex);
throw new InvalidDataException("Could not log in", "");
}
}
/**
* Logs into the LDAP server with the given username and password, and initialises the lookup.
*
* @param agentName - username
* @param agentPassword - password
* @return an AgentProxy on the requested user
* @throws InvalidDataException
*/
static public AgentProxy connect(String agentName, String agentPassword)
throws InvalidDataException
{
LDAPProperties ldapProps = new LDAPProperties();
if (ldapProps.mHost!=null && ldapProps.mPort!= null && ldapProps.mLocalPath!=null )
{
try {
ldapProps.mUser = "";
ldapProps.mPassword = "";
mLDAPLookup = new LDAPLookup(ldapProps);
String agentDN = mLDAPLookup.getRoleManager().getAgentPath(agentName).getFullDN();
//found agentDN, try to log in with it
ldapProps.mUser = agentDN;
ldapProps.mPassword = agentPassword;
mLDAPLookup = new LDAPLookup(ldapProps);
// find agent proxy
AgentPath agentPath = mLDAPLookup.getRoleManager().getAgentPath(agentName);
if (agentPath!=null)
{
setup();
return (AgentProxy) mProxyManager.getProxy(agentPath);
}
else
{
throw new InvalidDataException("The agentDN " +agentDN+ " is invalid.", "");
}
} catch (ClusterStorageException e) {
throw new InvalidDataException(Language.translate("Error initialising storage")+Language.translate(". See log."), "");
} catch (ObjectNotFoundException e) {
throw new InvalidDataException(Language.translate("Invalid username/password"), "");
} catch (Exception e) {
throw new InvalidDataException(Language.translate("Could not log in")+": "+Language.translate(e.getMessage()), "");
}
}
else
{
throw new InvalidDataException("Cannot log in. Some connection properties are not set.", "");
}
}
/**
* Initializes the storage and proxy manager, called during connect.
*
* @throws InvalidDataException
* @throws ClusterStorageException
*/
static private void setup()
throws InvalidDataException,
ClusterStorageException
{
// Init storages
mStorage = new TransactionManager();
mProxyManager = new EntityProxyManager();
}
/**
* Shuts down all kernel api objects
*/
public static void close()
{
// run shutdown module scripts
mModules.runScripts("shutdown");
// shut down servers if running
if (mCorbaServer != null)
mCorbaServer.close();
mCorbaServer = null;
// if (mHTTPServer != null)
// mHTTPServer.stopListening();
// mHTTPServer = null;
// disconnect from storages
if (mStorage != null)
mStorage.close();
mStorage = null;
// disconnect from ldap
if (mLDAPLookup != null)
mLDAPLookup.disconnect();
mLDAPLookup = null;
// shut down proxy manager
if (mProxyManager != null)
mProxyManager.shutdown();
mProxyManager = null;
EntityProxyManager.shutdownServer();
// close log consoles
Logger.closeConsole();
// finally, destroy the ORB
getORB().destroy();
}
static public org.omg.CORBA.ORB getORB()
{
if (mORB == null)
mORB = org.omg.CORBA.ORB.init(new String[0], null);
return mORB;
}
static public LDAPLookup getLDAPLookup()
{
return mLDAPLookup;
}
static public CorbaServer getCorbaServer()
{
return mCorbaServer;
}
static public TransactionManager getStorage()
{
return mStorage;
}
static public CastorXMLUtility getMarshaller()
{
return mMarshaller;
}
static public EntityProxyManager getProxyManager()
{
return mProxyManager;
}
static public String getCentreId() {
return getProperty("LocalCentre");
}
static public String getProperty(String propName) {
return getProperty(propName, null);
}
static public String getProperty(String propName, String defaultValue) {
if (mC2KProps == null) return defaultValue;
return mC2KProps.getProperty(propName, defaultValue);
}
static public void setProperty(String propName, String propValue) {
if (mC2KProps == null) return;
mC2KProps.put(propName, propValue);
}
static public Enumeration> propertyNames() {
return mC2KProps.propertyNames();
}
static public void dumpC2KProps(int logLevel) {
if (!Logger.doLog(logLevel)) return;
Logger.msg(logLevel, "C2K Properties:");
for (Enumeration> e = propertyNames(); e.hasMoreElements();) {
String name = (String) e.nextElement();
Logger.msg(" "+name+": "+getProperty(name));
}
}
}