From 0ed2c1124cf1b9e49a2ec1fa0126a8df09f9e758 Mon Sep 17 00:00:00 2001 From: Andrew Branson Date: Tue, 7 Oct 2014 09:18:11 +0200 Subject: Repackage to org.cristalise --- .../cristalise/kernel/process/AbstractMain.java | 178 +++++++++ .../org/cristalise/kernel/process/Bootstrap.java | 394 +++++++++++++++++++ .../org/cristalise/kernel/process/ClientShell.java | 71 ++++ .../org/cristalise/kernel/process/Gateway.java | 426 +++++++++++++++++++++ .../cristalise/kernel/process/ShutdownHandler.java | 26 ++ .../cristalise/kernel/process/StandardClient.java | 31 ++ .../cristalise/kernel/process/StandardServer.java | 67 ++++ .../cristalise/kernel/process/UserCodeProcess.java | 276 +++++++++++++ .../kernel/process/auth/Authenticator.java | 93 +++++ .../kernel/process/auth/ConsoleAuth.java | 65 ++++ .../cristalise/kernel/process/auth/ProxyLogin.java | 42 ++ .../cristalise/kernel/process/module/Module.java | 224 +++++++++++ .../kernel/process/module/ModuleConfig.java | 42 ++ .../kernel/process/module/ModuleException.java | 29 ++ .../kernel/process/module/ModuleImport.java | 87 +++++ .../kernel/process/module/ModuleImports.java | 78 ++++ .../kernel/process/module/ModuleInfo.java | 34 ++ .../kernel/process/module/ModuleManager.java | 211 ++++++++++ .../kernel/process/module/ModuleResource.java | 80 ++++ .../kernel/process/module/ModuleScript.java | 53 +++ .../process/resource/BadArgumentsException.java | 37 ++ .../resource/DefaultResourceImportHandler.java | 106 +++++ .../kernel/process/resource/Resource.java | 196 ++++++++++ .../process/resource/ResourceImportHandler.java | 68 ++++ .../kernel/process/resource/ResourceLoader.java | 67 ++++ 25 files changed, 2981 insertions(+) create mode 100644 src/main/java/org/cristalise/kernel/process/AbstractMain.java create mode 100644 src/main/java/org/cristalise/kernel/process/Bootstrap.java create mode 100644 src/main/java/org/cristalise/kernel/process/ClientShell.java create mode 100644 src/main/java/org/cristalise/kernel/process/Gateway.java create mode 100644 src/main/java/org/cristalise/kernel/process/ShutdownHandler.java create mode 100644 src/main/java/org/cristalise/kernel/process/StandardClient.java create mode 100644 src/main/java/org/cristalise/kernel/process/StandardServer.java create mode 100644 src/main/java/org/cristalise/kernel/process/UserCodeProcess.java create mode 100644 src/main/java/org/cristalise/kernel/process/auth/Authenticator.java create mode 100644 src/main/java/org/cristalise/kernel/process/auth/ConsoleAuth.java create mode 100644 src/main/java/org/cristalise/kernel/process/auth/ProxyLogin.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/Module.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleConfig.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleException.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleImport.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleImports.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleInfo.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleManager.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleResource.java create mode 100644 src/main/java/org/cristalise/kernel/process/module/ModuleScript.java create mode 100644 src/main/java/org/cristalise/kernel/process/resource/BadArgumentsException.java create mode 100644 src/main/java/org/cristalise/kernel/process/resource/DefaultResourceImportHandler.java create mode 100644 src/main/java/org/cristalise/kernel/process/resource/Resource.java create mode 100644 src/main/java/org/cristalise/kernel/process/resource/ResourceImportHandler.java create mode 100644 src/main/java/org/cristalise/kernel/process/resource/ResourceLoader.java (limited to 'src/main/java/org/cristalise/kernel/process') diff --git a/src/main/java/org/cristalise/kernel/process/AbstractMain.java b/src/main/java/org/cristalise/kernel/process/AbstractMain.java new file mode 100644 index 0000000..5acfbef --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/AbstractMain.java @@ -0,0 +1,178 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.util.Enumeration; +import java.util.Properties; + +import org.cristalise.kernel.process.resource.BadArgumentsException; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2004/10/25 15:27:35 $ + * @version $Revision: 1.67 $ + **************************************************************************/ +abstract public class AbstractMain +{ + public static boolean isServer = false; + private static ShutdownHandler shutdownHandler; + + public static String MAIN_ARG_NONEWLOGSTREAM = "noNewLogStream"; + public static String MAIN_ARG_CONFIG = "config"; + public static String MAIN_ARG_LOGLEVEL = "logLevel"; + public static String MAIN_ARG_LOGFILE = "logFile"; + public static String MAIN_ARG_CONNECT = "connect"; + + + + /************************************************************************** + * reading and setting input paramaters + ************************************************************************** + * + * Known arguments : + * + * + * + * @param args + * @return + * @throws BadArgumentsException + */ + public static Properties readC2KArgs( String[] args ) throws BadArgumentsException { + Properties c2kProps; + Properties argProps = new Properties(); + int logLevel = 0; + PrintStream logStream = System.out; + + int i = 0; + while( i < args.length ) { + if (args[i].startsWith("-") && args[i].length()>1) { + String key = args[i].substring(1); + if (argProps.containsKey(key)) + throw new BadArgumentsException("Argument "+args[i]+" given twice"); + String value = ""; + if (!args[i+1].startsWith("-")) + value = args[++i]; + argProps.put(key, value); + i++; + } + else + throw new BadArgumentsException("Bad argument: "+args[i]); + + } + + if (argProps.containsKey("logFile")) + try { + logStream = new PrintStream(new FileOutputStream(argProps.getProperty("logFile"), true)); + } catch (FileNotFoundException e) { + e.printStackTrace(); + throw new BadArgumentsException("Logfile "+argProps.getProperty("logFile")+" cannot be created"); + } + + + // if the optional arg "noNewLogStream" isn't present => add a + // new LogStream + boolean wMustAddNewLogStream = !argProps.contains(MAIN_ARG_NONEWLOGSTREAM); + if (wMustAddNewLogStream) { + + // Set up log stream + if (argProps.containsKey("logLevel")) + logLevel = Integer.parseInt(argProps.getProperty("logLevel")); + + Logger.addLogStream(logStream, logLevel); + } + if (wMustAddNewLogStream) Logger.msg( + String.format("New logStream added at logLevel %d: %s", logLevel, logStream.getClass().getName())); + + + // Dump params if log high enough + + if (Logger.doLog(3)) for (Enumeration e = argProps.propertyNames(); e.hasMoreElements();) { + String next = (String)e.nextElement(); + System.out.println("AbstractMain: Param "+next+": "+argProps.getProperty(next)); + } + + String configPath = argProps.getProperty("config"); + if (configPath == null) + throw new BadArgumentsException("Config file not specified"); + + if (!new File(configPath).exists()) + throw new BadArgumentsException("Config file "+configPath+" not found"); + else + Logger.msg(0, "Config file: "+configPath); + + // Load config & connect files into c2kprops + c2kProps = FileStringUtility.loadConfigFile(argProps.getProperty("config") ); + c2kProps.putAll(argProps); // args overlap config + + String connectFile = c2kProps.getProperty("connect"); + if (connectFile == null) + throw new BadArgumentsException("Connect file not specified"); + + if (!new File(connectFile).exists()) + throw new BadArgumentsException("Connect file "+connectFile+" not found"); + else + Logger.msg(0, "Connect file: "+connectFile); + + FileStringUtility.appendConfigFile( c2kProps, connectFile); + + if (!c2kProps.containsKey("LocalCentre")) { + String connectFileName = new File(connectFile).getName(); + String centreId = connectFileName.substring(0, connectFileName.lastIndexOf(".clc")); + c2kProps.setProperty("LocalCentre", centreId); + } + + c2kProps.putAll(argProps); // args override connect file too + Logger.msg(7, "AbstractMain::standardSetUp() - readC2KArgs() DONE."); + + return c2kProps; + } + + public static void setShutdownHandler(ShutdownHandler handler) { + shutdownHandler = handler; + } + + public static void shutdown(int errCode) { + if (shutdownHandler!= null) + shutdownHandler.shutdown(errCode, isServer); + else + try { + Gateway.close(); + } catch (Exception ex) { + Logger.error(ex); + } + } +} diff --git a/src/main/java/org/cristalise/kernel/process/Bootstrap.java b/src/main/java/org/cristalise/kernel/process/Bootstrap.java new file mode 100644 index 0000000..8934cd8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/Bootstrap.java @@ -0,0 +1,394 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +import java.net.InetAddress; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Set; +import java.util.StringTokenizer; +import java.util.UUID; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.events.Event; +import org.cristalise.kernel.events.History; +import org.cristalise.kernel.lifecycle.CompositeActivityDef; +import org.cristalise.kernel.lifecycle.instance.CompositeActivity; +import org.cristalise.kernel.lifecycle.instance.Workflow; +import org.cristalise.kernel.lifecycle.instance.predefined.server.ServerPredefinedStepContainer; +import org.cristalise.kernel.lifecycle.instance.stateMachine.Transition; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.LookupManager; +import org.cristalise.kernel.lookup.Path; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.OutcomeValidator; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.resource.DefaultResourceImportHandler; +import org.cristalise.kernel.process.resource.ResourceImportHandler; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.property.PropertyDescription; +import org.cristalise.kernel.property.PropertyDescriptionList; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.LocalObjectLoader; +import org.cristalise.kernel.utils.Logger; +import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.XMLUnit; + + +/** + * @version $Revision: 1.25 $ $Date: 2006/01/10 09:48:32 $ + * @author $Author: abranson $ + */ + +public class Bootstrap +{ + static DomainPath thisServerPath; + static HashMap resHandlerCache = new HashMap(); + static HashMap systemAgents = new HashMap(); + + /** + * Run everything without timing-out the service wrapper + */ + public static void run() throws Exception { + // check for system agents + checkAdminAgents(); + + // create the server's mother item + createServerItem(); + new Thread(new Runnable() { + @Override + public void run() { + try { + Thread.currentThread().setName("Bootstrapper"); + + ClassLoader wClassLoader = Bootstrap.class.getClassLoader(); + Logger.msg(String.format("Bootstrap.run() setContextClassLoader=[%s]",wClassLoader)); + Thread.currentThread().setContextClassLoader(wClassLoader); + + // make sure all of the boot items are up-to-date + Logger.msg("Bootstrap.run() - Verifying kernel boot data items"); + verifyBootDataItems(); + + // verify the server item's wf + Logger.msg("Bootstrap.run() - Initialising Server Item Workflow"); + initServerItemWf(); + + Gateway.getModuleManager().setUser(systemAgents.get("system")); + Gateway.getModuleManager().registerModules(); + + Logger.msg("Bootstrap.run() - Bootstrapping complete"); + } catch (Throwable e) { + Logger.error(e); + Logger.die("Exception performing bootstrap. Check that everything is OK."); + } + } + }).start(); + } + + /************************************************************************** + * Checks all kernel descriptions, stored in resources + **************************************************************************/ + public static void verifyBootDataItems() throws Exception { + String bootItems; + Logger.msg(1, "Verifying kernel boot items"); + bootItems = FileStringUtility.url2String(Gateway.getResource().getKernelResourceURL("boot/allbootitems.txt")); + verifyBootDataItems(bootItems, null, true); + Logger.msg(1, "Boot data items complete"); + } + + private static void verifyBootDataItems(String bootList, String ns, boolean reset) throws InvalidItemPathException { + StringTokenizer str = new StringTokenizer(bootList, "\n\r"); + while (str.hasMoreTokens()) { + String thisItem = str.nextToken(); + ItemPath itemPath = null; + String[] itemParts = thisItem.split("/"); + if (itemParts.length == 3) { // includes UUID + itemPath = new ItemPath(itemParts[2]); + } + String itemType = itemParts[0]; + String itemName = itemParts[1]; + try { + String location = "boot/"+thisItem+(itemType.equals("OD")?".xsd":".xml"); + verifyResource(ns, itemName, 0, itemType, itemPath, location, reset); + } catch (Exception e) { + Logger.error(e); + Logger.die("Error importing bootstrap items. Unsafe to continue."); + } + } + } + + public static DomainPath verifyResource(String ns, String itemName, int version, String itemType, ItemPath itemPath, String dataLocation, boolean reset) throws Exception { + LookupManager lookupManager = Gateway.getLookupManager(); + ResourceImportHandler typeImpHandler = getHandler(itemType); + Logger.msg(1, "Bootstrap.verifyResource() - Verifying version "+version+" of "+typeImpHandler.getName()+" "+itemName); + + // Find or create Item for Resource + DomainPath modDomPath = typeImpHandler.getPath(itemName, ns); + ItemProxy thisProxy; + Iterator en = Gateway.getLookup().search(typeImpHandler.getTypeRoot(), itemName); + if (!en.hasNext()) { + if (itemPath == null) itemPath = new ItemPath(); + Logger.msg("Bootstrap.verifyResource() - "+typeImpHandler.getName()+" "+itemName+" not found. Creating new."); + thisProxy = createResourceItem(typeImpHandler, itemName, ns, itemPath); + } + else { + DomainPath path = (DomainPath)en.next(); + thisProxy = Gateway.getProxyManager().getProxy(path); + if (itemPath != null && !path.getItemPath().equals(itemPath)) { + Logger.warning("Resource "+itemType+"/"+itemName+" should have path "+itemPath+" but was found with path "+path.getItemPath()); + itemPath = path.getItemPath(); + } + if (itemPath == null) itemPath = path.getItemPath(); + // Verify module property and location + + String moduleName = (ns==null?"kernel":ns); + String itemModule; + try{ + itemModule = thisProxy.getProperty("Module"); + if (!itemModule.equals("") && !itemModule.equals("null") && !moduleName.equals(itemModule)) { + Logger.error("Bootstrap.verifyResource() - Module clash! Resource '"+itemName+"' included in module "+moduleName+" but is assigned to '"+itemModule+"'. Not overwriting."); + return path; + } + } catch (ObjectNotFoundException ex) { + itemModule = ""; + } + + if (!moduleName.equals(itemModule)) { // write module property + Gateway.getStorage().put(itemPath, new Property("Module", moduleName, false), thisProxy); + } + + if (!modDomPath.equals(path)) { // move item to module subtree + Logger.msg("Module item "+itemName+" found with path "+path.toString()+". Moving to "+modDomPath.toString()); + modDomPath.setItemPath(itemPath); + if (!modDomPath.exists()) + lookupManager.add(modDomPath); + lookupManager.delete(path); + } + } + + // Verify/Import Outcomes, creating events and views as necessary + Set impList = typeImpHandler.getResourceOutcomes(itemName, ns, dataLocation, version); + for (Outcome newOutcome : impList) { + try { + Viewpoint currentData = (Viewpoint)thisProxy.getObject(ClusterStorage.VIEWPOINT+"/"+newOutcome.getSchemaType()+"/"+version); + Outcome oldData = currentData.getOutcome(); + XMLUnit.setIgnoreWhitespace(true); + XMLUnit.setIgnoreComments(true); + Diff xmlDiff = new Diff(newOutcome.getDOM(), oldData.getDOM()); + if (xmlDiff.identical()) { + Logger.msg(5, "Bootstrap.verifyResource() - Data identical, no update required"); + continue; + } + else { + Logger.msg("Difference found in "+itemName+": "+xmlDiff.toString()); + if (!reset && !currentData.getEvent().getStepPath().equals("Bootstrap")) { + Logger.msg("Version "+version+" was not set by Bootstrap, and reset not requested. Not overwriting."); + continue; + } + } + + } catch (ObjectNotFoundException ex) { + Logger.msg("Bootstrap.verifyResource() - Item "+itemName+" exists but version "+version+" not found! Attempting to insert new."); + } + + // data was missing or doesn't match + // validate it (but not for kernel objects because we need those to validate the rest) + if (ns!= null) { + OutcomeValidator validator = OutcomeValidator.getValidator(LocalObjectLoader.getSchema(newOutcome.getSchemaType(), newOutcome.getSchemaVersion())); + String error = validator.validate(newOutcome.getData()); + if (error.length() > 0) { + Logger.error("Outcome not valid: \n " + error); + throw new InvalidDataException(error); + } + } + + // store + Logger.msg("Bootstrap.verifyResource() - Writing new "+newOutcome.getSchemaType()+" v"+version+" to "+typeImpHandler.getName()+" "+itemName); + History hist = new History(itemPath, thisProxy); + Transition predefDone = new Transition(0, "Done", 0, 0); + Event newEvent = hist.addEvent(systemAgents.get("system").getPath(), "Admin", "Bootstrap", "Bootstrap", "Bootstrap", newOutcome.getSchemaType(), 0, "PredefinedStep", 0, predefDone, String.valueOf(version)); + newOutcome.setID(newEvent.getID()); + Viewpoint newLastView = new Viewpoint(itemPath, newOutcome.getSchemaType(), "last", 0, newEvent.getID()); + Viewpoint newNumberView = new Viewpoint(itemPath, newOutcome.getSchemaType(), String.valueOf(version), 0, newEvent.getID()); + Gateway.getStorage().put(itemPath, newOutcome, thisProxy); + Gateway.getStorage().put(itemPath, newLastView, thisProxy); + Gateway.getStorage().put(itemPath, newNumberView, thisProxy); + } + Gateway.getStorage().commit(thisProxy); + return modDomPath; + } + + private static ResourceImportHandler getHandler(String resType) throws Exception { + if (resHandlerCache.containsKey(resType)) + return resHandlerCache.get(resType); + ResourceImportHandler handler = null; + if (Gateway.getProperties().containsKey("ResourceImportHandler."+resType)) { + try { + handler = (ResourceImportHandler) Gateway.getProperties().getInstance("ResourceImportHandler."+resType); + } catch (Exception ex) { + Logger.error(ex); + Logger.error("Exception loading ResourceHandler for "+resType+". Using default."); + } + } + + if (handler == null) + handler = new DefaultResourceImportHandler(resType); + + resHandlerCache.put(resType, handler); + return handler; + } + + /** + * @param itemType + * @param itemName + * @param data + */ + private static ItemProxy createResourceItem(ResourceImportHandler impHandler, String itemName, String ns, ItemPath itemPath) throws Exception { + // create props + PropertyDescriptionList pdList = impHandler.getPropDesc(); + PropertyArrayList props = new PropertyArrayList(); + LookupManager lookupManager = Gateway.getLookupManager(); + + for (int i = 0; i < pdList.list.size(); i++) { + PropertyDescription pd = pdList.list.get(i); + String propName = pd.getName(); + String propVal = propName.equals("Name")?itemName:pd.getDefaultValue(); + props.list.add(new Property(propName, propVal, pd.getIsMutable())); + } + + CompositeActivity ca = new CompositeActivity(); + if (ns!=null && Gateway.getProperties().getBoolean("Module.debug", false)) + try { + ca = (CompositeActivity) ((CompositeActivityDef)LocalObjectLoader.getActDef(impHandler.getWorkflowName(), 0)).instantiate(); + } catch (ObjectNotFoundException ex) { + Logger.error("Module resource workflow "+impHandler.getWorkflowName()+" not found. Using empty."); + } + + + Gateway.getCorbaServer().createItem(itemPath); + lookupManager.add(itemPath); + DomainPath newDomPath = impHandler.getPath(itemName, ns); + newDomPath.setItemPath(itemPath); + lookupManager.add(newDomPath); + ItemProxy newItemProxy = Gateway.getProxyManager().getProxy(itemPath); + newItemProxy.initialise( systemAgents.get("system").getPath(), props, ca, null); + return newItemProxy; + } + + /************************************************************************** + * Checks for the existence of the admin users so you can use Cristal + **************************************************************************/ + private static void checkAgent(String name, String pass, RolePath rolePath, String uuid) throws Exception { + Logger.msg(1, "Bootstrap.checkAgent() - Checking for existence of '"+name+"' user."); + LookupManager lookup = Gateway.getLookupManager(); + + try { + systemAgents.put(name, Gateway.getProxyManager().getAgentProxy(lookup.getAgentPath(name))); + Logger.msg(3, "Bootstrap.checkAgent() - User '"+name+"' found."); + return; + } catch (ObjectNotFoundException ex) { } + + Logger.msg("Bootstrap.checkAgent() - User '"+name+"' not found. Creating."); + + try { + AgentPath agentPath = new AgentPath(new ItemPath(uuid), name); + agentPath.setPassword(pass); + Gateway.getCorbaServer().createAgent(agentPath); + lookup.add(agentPath); + + // assign admin role + Logger.msg("Bootstrap.checkAgent() - Assigning role '"+rolePath.getName()+"'"); + Gateway.getLookupManager().addRole(agentPath, rolePath); + Gateway.getStorage().put(agentPath, new Property("Name", name, true), null); + Gateway.getStorage().put(agentPath, new Property("Type", "Agent", false), null); + systemAgents.put(name, Gateway.getProxyManager().getAgentProxy(agentPath)); + } catch (Exception ex) { + Logger.error("Unable to create "+name+" user."); + throw ex; + } + } + + /** + * + */ + public static void checkAdminAgents() throws Exception { + + // check for administrative user & admin role + String adminPassword = Gateway.getProperties().getString("AdminPassword", "admin12345"); + RolePath rootRole = new RolePath(); + if (!rootRole.exists()) Gateway.getLookupManager().createRole(rootRole); + RolePath adminRole = new RolePath(rootRole, "Admin", false); + if (!adminRole.exists()) Gateway.getLookupManager().createRole(adminRole); + + // check for import user + checkAgent("system", adminPassword, adminRole, new UUID(0, 0).toString()); + + checkAgent("admin", adminPassword, adminRole, new UUID(0, 1).toString()); + + // check for local usercode user & role + RolePath usercodeRole = new RolePath(rootRole, "UserCode", true); + if (!usercodeRole.exists()) Gateway.getLookupManager().createRole(usercodeRole); + checkAgent(InetAddress.getLocalHost().getHostName(), "uc", usercodeRole, UUID.randomUUID().toString()); + } + + public static void createServerItem() throws Exception { + LookupManager lookupManager = Gateway.getLookupManager(); + String serverName = Gateway.getProperties().getString("ItemServer.name", InetAddress.getLocalHost().getHostName()); + thisServerPath = new DomainPath("/servers/"+serverName); + ItemPath serverEntity; + try { + serverEntity = thisServerPath.getItemPath(); + } catch (ObjectNotFoundException ex) { + Logger.msg("Creating server item "+thisServerPath); + serverEntity = new ItemPath(); + Gateway.getCorbaServer().createItem(serverEntity); + lookupManager.add(serverEntity); + thisServerPath.setItemPath(serverEntity); + lookupManager.add(thisServerPath); + } + Gateway.getStorage().put(serverEntity, new Property("Name", serverName, false), null); + Gateway.getStorage().put(serverEntity, new Property("Type", "Server", false), null); + Gateway.getStorage().put(serverEntity, new Property("KernelVersion", Gateway.getKernelVersion(), true), null); + int proxyPort = Gateway.getProperties().getInt("ItemServer.Proxy.port", 1553); + Gateway.getStorage().put(serverEntity, + new Property("ProxyPort", String.valueOf(proxyPort), false), null); + Gateway.getStorage().put(serverEntity, + new Property("ConsolePort", String.valueOf(Logger.getConsolePort()), true), null); + Gateway.getProxyManager().connectToProxyServer(serverName, proxyPort); + + } + + public static void initServerItemWf() throws Exception { + CompositeActivityDef serverWfCa = (CompositeActivityDef)LocalObjectLoader.getActDef("ServerItemWorkflow", 0); + Workflow wf = new Workflow((CompositeActivity)serverWfCa.instantiate(), new ServerPredefinedStepContainer()); + wf.initialise(thisServerPath.getItemPath(), systemAgents.get("system").getPath()); + Gateway.getStorage().put(thisServerPath.getItemPath(), wf, null); + } +} diff --git a/src/main/java/org/cristalise/kernel/process/ClientShell.java b/src/main/java/org/cristalise/kernel/process/ClientShell.java new file mode 100644 index 0000000..0a9ad83 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/ClientShell.java @@ -0,0 +1,71 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +import java.util.Scanner; + +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.process.auth.ProxyLogin; +import org.cristalise.kernel.scripting.Script; +import org.cristalise.kernel.scripting.ScriptParsingException; + + +public class ClientShell extends StandardClient { + + AgentProxy user; + Script console; + + public ClientShell(AgentProxy user) throws Exception { + this.user = user; + console = new Script("javascript", user, System.out); + } + + public void run() { + Scanner scan = new Scanner(System.in); + System.out.print("> "); + while (scan.hasNextLine()) { + String command = scan.nextLine(); + try { + console.setScript(command); + Object response = console.execute(); + if (response == null) + System.out.println("Ok"); + else + System.out.println(response); + } catch (ScriptParsingException e) { + System.err.println("Syntax error: "+e.getMessage()); + } catch (Throwable ex) { + ex.printStackTrace(); + } + System.out.print("> "); + } + shutdown(0); + } + + public static void main(String[] args) throws Exception { + Gateway.init(readC2KArgs(args)); + ProxyLogin auth = (ProxyLogin)Gateway.getProperties().getInstance("cli.auth"); + AgentProxy user = auth.authenticate(Gateway.getProperties().getProperty("Name")); + ClientShell shell = new ClientShell(user); + shell.run(); + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/Gateway.java b/src/main/java/org/cristalise/kernel/process/Gateway.java new file mode 100644 index 0000000..c7936c3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/Gateway.java @@ -0,0 +1,426 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.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 org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.CorbaServer; +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.entity.proxy.ProxyManager; +import org.cristalise.kernel.entity.proxy.ProxyServer; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.Lookup; +import org.cristalise.kernel.lookup.LookupManager; +import org.cristalise.kernel.persistency.TransactionManager; +import org.cristalise.kernel.process.auth.Authenticator; +import org.cristalise.kernel.process.module.ModuleManager; +import org.cristalise.kernel.process.resource.Resource; +import org.cristalise.kernel.process.resource.ResourceLoader; +import org.cristalise.kernel.utils.CastorXMLUtility; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.Language; +import org.cristalise.kernel.utils.Logger; +import org.cristalise.kernel.utils.ObjectProperties; + + + +/************************************************************************** + * 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: + *
    + *
  • Lookup - 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 ObjectProperties mC2KProps = new ObjectProperties(); + static private ModuleManager mModules; + static private org.omg.CORBA.ORB mORB; + static private boolean orbDestroyed = false; + static private Lookup mLookup; + static private LookupManager mLookupManager = null; + static private TransactionManager mStorage; + static private ProxyManager mProxyManager; + static private ProxyServer mProxyServer; + static private CorbaServer mCorbaServer; + static private CastorXMLUtility mMarshaller; + static private ResourceLoader mResource; + + + + private Gateway() { } + + /** + * Initialises the Gateway and all of the client objects it holds, with + * the exception of the Lookup, 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) throws InvalidDataException { + init(props, null); + } + + /** + * Initialises the Gateway and all of the client objects it holds, with + * the exception of the Lookup, which is initialised during connect() + * + * @param props - java.util.Properties containing all application properties. + * If null, the java system properties are used + * @param res - ResourceLoader for the kernel to use to resolve all class resource requests + * such as for bootstrap descriptions and version information + * @throws InvalidDataException - invalid properties caused a failure in initialisation + */ + static public void init(Properties props, ResourceLoader res) throws InvalidDataException { + + // Init properties & resources + mC2KProps.clear(); + + orbDestroyed = false; + mResource = res; + if (mResource == null) mResource = new Resource(); + + // report version info + Logger.msg("Kernel version: "+getKernelVersion()); + + // load kernel mapfiles giving the resourse loader and the properties of + // the application to be able to configure castor + try { + mMarshaller = new CastorXMLUtility(mResource, props, mResource.getKernelResourceURL("mapFiles/")); + } catch (MalformedURLException e1) { + throw new InvalidDataException("Invalid Resource Location"); + } + + + // init module manager + try { + mModules = new ModuleManager(mResource.getModuleDefURLs(), AbstractMain.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 = getProperties().getString("language.file"); + if (languageFile != null && languageFile.length() > 0) { + Language.isTranlated=true; + Language.mTableOfTranslation = FileStringUtility.loadLanguageFile(languageFile); + } + } + + /** + * 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(Authenticator auth) throws InvalidDataException, CannotManageException { + try { + // check top level directory contexts + if (mLookup instanceof LookupManager) { + mLookupManager = (LookupManager)mLookup; + mLookupManager.initializeDirectory(); + } + else { + throw new CannotManageException("Lookup implementation is not a LookupManager. Cannot write to directory"); + } + + // start entity proxy server + mProxyServer = new ProxyServer(mC2KProps.getProperty("ItemServer.name")); + + // Init ORB - set various config + String serverName = mC2KProps.getProperty("ItemServer.name"); + if (serverName != null) + mC2KProps.put("com.sun.CORBA.ORBServerHost", serverName); + String serverPort = mC2KProps.getProperty("ItemServer.iiop", "1500"); + mC2KProps.put("com.sun.CORBA.ORBServerPort", serverPort); + //TODO: externalize this (or replace corba completely) + mC2KProps.put("com.sun.CORBA.POA.ORBServerId", "1"); + mC2KProps.put("com.sun.CORBA.POA.ORBPersistentServerPort", serverPort); + mC2KProps.put("com.sun.CORBA.codeset.charsets", "0x05010001, 0x00010109"); // need to force UTF-8 in the Sun ORB + mC2KProps.put("com.sun.CORBA.codeset.wcharsets", "0x00010109, 0x05010001"); + //Standard initialisation of the ORB + orbDestroyed = false; + mORB = org.omg.CORBA.ORB.init(new String[0], mC2KProps); + + 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(); + System.out.println("Server '"+serverName+"' initialised."); + } catch (Exception ex) { + Logger.error(ex); + Logger.die("Exception starting server components. Shutting down."); + } + + } + + 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 PersistencyException - error starting storages + */ + static public Authenticator connect() + throws InvalidDataException, + PersistencyException + { + try { + Authenticator auth = (Authenticator)mC2KProps.getInstance("Authenticator"); + auth.authenticate("System"); + + mLookup = (Lookup)mC2KProps.getInstance("Lookup"); + mLookup.open(auth); + + mStorage = new TransactionManager(auth); + mProxyManager = new ProxyManager(); + + return auth; + } catch (Exception ex) { + Logger.error(ex); + throw new InvalidDataException("Cannot connect server process. Please check config."); + } + + + } + + /** + * Logs in with the given username and password, and initialises the lookup, storage and proxy manager. + * + * @param agentName - username + * @param agentPassword - password + * @return an AgentProxy on the requested user + * @throws InvalidDataException + * @throws PersistencyException + * @throws ClassNotFoundException + * @throws IllegalAccessException + * @throws InstantiationException + */ + static public AgentProxy connect(String agentName, String agentPassword, String resource) + throws InvalidDataException, ObjectNotFoundException, PersistencyException, InstantiationException, IllegalAccessException, ClassNotFoundException + { + Authenticator auth = (Authenticator)mC2KProps.getInstance("Authenticator"); + if (!auth.authenticate(agentName, agentPassword, resource)) + throw new InvalidDataException("Login failed"); + + mLookup = (Lookup)mC2KProps.getInstance("Lookup"); + mLookup.open(auth); + + mStorage = new TransactionManager(auth); + mProxyManager = new ProxyManager(); + + // find agent proxy + AgentPath agentPath = mLookup.getAgentPath(agentName); + AgentProxy userProxy = (AgentProxy) mProxyManager.getProxy(agentPath); + userProxy.setAuthObj(auth); + + // Run module startup scripts. Server does this during bootstrap + mModules.setUser(userProxy); + mModules.runScripts("startup"); + + return userProxy; + } + + static public AgentProxy connect(String agentName, String agentPassword) + throws InvalidDataException, ObjectNotFoundException, PersistencyException, InstantiationException, IllegalAccessException, ClassNotFoundException + { + return connect(agentName, agentPassword, null); + } + + /** + * Shuts down all kernel api objects + */ + public static void close() + { + // run shutdown module scripts + if (mModules != null) + mModules.runScripts("shutdown"); + + // shut down servers if running + if (mCorbaServer != null) + mCorbaServer.close(); + mCorbaServer = null; + + // disconnect from storages + if (mStorage != null) + mStorage.close(); + mStorage = null; + + // disconnect from ldap + if (mLookup != null) + mLookup.close(); + mLookup = null; + mLookupManager = null; + + // shut down proxy manager & server + if (mProxyManager != null) + mProxyManager.shutdown(); + if (mProxyServer != null) + mProxyServer.shutdownServer(); + mProxyManager = null; + mProxyServer = null; + + // close log consoles + Logger.closeConsole(); + + // finally, destroy the ORB + if (!orbDestroyed) { + getORB().destroy(); + orbDestroyed = true; + mORB = null; + } + + // clean up remaining objects + mModules = null; + mResource = null; + mMarshaller = null; + mC2KProps.clear(); + } + + static public org.omg.CORBA.ORB getORB() + { + if (orbDestroyed) throw new RuntimeException("Gateway has been closed. ORB is destroyed. "); + + if (mORB == null) { + mC2KProps.put("com.sun.CORBA.codeset.charsets", "0x05010001, 0x00010109"); // need to force UTF-8 in the Sun ORB + mC2KProps.put("com.sun.CORBA.codeset.wcharsets", "0x00010109, 0x05010001"); + mORB = org.omg.CORBA.ORB.init(new String[0], mC2KProps); + } + return mORB; + } + + static public Lookup getLookup() + { + return mLookup; + } + + static public LookupManager getLookupManager() throws CannotManageException + { + if (mLookupManager == null) + throw new CannotManageException("No Lookup Manager created. Not a server process."); + else + return mLookupManager; + } + + static public CorbaServer getCorbaServer() + { + return mCorbaServer; + } + + static public TransactionManager getStorage() + { + return mStorage; + } + + static public CastorXMLUtility getMarshaller() + { + return mMarshaller; + } + + static public ResourceLoader getResource() + { + return mResource; + } + + static public ProxyManager getProxyManager() + { + return mProxyManager; + } + + + public static ProxyServer getProxyServer() { + return mProxyServer; + } + + static public String getCentreId() { + return getProperties().getString("LocalCentre"); + } + + static public Enumeration propertyNames() { + return mC2KProps.propertyNames(); + } + + static public void dumpC2KProps(int logLevel) { + if (!Logger.doLog(logLevel)) return; + mC2KProps.dumpProps(logLevel); + } + + static public ObjectProperties getProperties() { + return mC2KProps; + } + + static public String getKernelVersion() { + try { + return mResource.getTextResource(null, "textFiles/version.txt"); + } catch (Exception ex) { + return "No version info found"; + } + + } +} + diff --git a/src/main/java/org/cristalise/kernel/process/ShutdownHandler.java b/src/main/java/org/cristalise/kernel/process/ShutdownHandler.java new file mode 100644 index 0000000..f34800d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/ShutdownHandler.java @@ -0,0 +1,26 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +public interface ShutdownHandler { + + public void shutdown(int errCode, boolean isServer); +} diff --git a/src/main/java/org/cristalise/kernel/process/StandardClient.java b/src/main/java/org/cristalise/kernel/process/StandardClient.java new file mode 100644 index 0000000..c97fed0 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/StandardClient.java @@ -0,0 +1,31 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + + +abstract public class StandardClient extends AbstractMain +{ + + static public void main(String[] args) throws Exception { + Gateway.init(readC2KArgs(args)); + //AgentProxy user = Gateway.connect("username", "password"); + } +} diff --git a/src/main/java/org/cristalise/kernel/process/StandardServer.java b/src/main/java/org/cristalise/kernel/process/StandardServer.java new file mode 100644 index 0000000..9d31b8e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/StandardServer.java @@ -0,0 +1,67 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +import org.cristalise.kernel.process.auth.Authenticator; +import org.cristalise.kernel.utils.Logger; + +/************************************************************************** + * Base class for all servers i.e. c2k processes that serve Entities + * + * @author $Author: abranson $ $Date: 2005/04/28 13:49:43 $ + * @version $Revision: 1.47 $ + **************************************************************************/ +public class StandardServer extends AbstractMain +{ + protected static StandardServer server; + + /************************************************************************** + * void StandardInitalisation( String[] ) + * + * Set-up calls to ORB, POA and Factorys, both optional and required. + **************************************************************************/ + protected static void standardInitialisation( String[] args ) + throws Exception + { + isServer = true; + + // read args and init Gateway + Gateway.init(readC2KArgs(args)); + + // connect to LDAP as root + Authenticator auth = Gateway.connect(); + + //start console + Logger.initConsole("ItemServer"); + + //initialize the server objects + Gateway.startServer(auth); + + Logger.msg(5, "StandardServer::standardInitialisation - complete."); + + } + + public static void main(String[] args) throws Exception + { + //initialise everything + standardInitialisation( args ); + } +} diff --git a/src/main/java/org/cristalise/kernel/process/UserCodeProcess.java b/src/main/java/org/cristalise/kernel/process/UserCodeProcess.java new file mode 100644 index 0000000..ff63baf --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/UserCodeProcess.java @@ -0,0 +1,276 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process; + +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.HashMap; + +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.agent.Job; +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.entity.proxy.MemberSubscription; +import org.cristalise.kernel.entity.proxy.ProxyObserver; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.scripting.ErrorInfo; +import org.cristalise.kernel.scripting.ScriptErrorException; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * $Revision: 1.31 $ + * $Date: 2004/10/21 08:02:19 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ +public class UserCodeProcess extends StandardClient implements ProxyObserver, Runnable { + + // Default state machine transitions + private static final int START = 1; + private static final int COMPLETE = 2; + private static final int SUSPEND = 3; + private static final int RESUME = 4; + + protected AgentProxy agent; + static boolean active = true; + ArrayList ignoredPaths = new ArrayList(); + HashMap errors = new HashMap(); + final HashMap jobs = new HashMap(); + + public UserCodeProcess(String agentName, String agentPass, String resource) { + // login - try for a while in case server hasn't imported our user yet + for (int i=1;i<6;i++) { + try { + Logger.msg("Login attempt "+i+" of 5"); + agent = Gateway.connect(agentName, agentPass, resource); + break; + } catch (Exception ex) { + Logger.error("Could not log in."); + Logger.error(ex); + try { + Thread.sleep(5000); + } catch (InterruptedException ex2) { } + } + } + System.out.println(getDesc()+" initialised for " + agentName); + } + + @Override + public void run() { + Thread.currentThread().setName("Usercode Process"); + // subscribe to job list + agent.subscribe(new MemberSubscription(this, ClusterStorage.JOB, true)); + while (active) { + Job thisJob = null; + synchronized (jobs) { + if (jobs.size() > 0) { + thisJob = getJob(jobs, COMPLETE); + if (thisJob == null) + thisJob = getJob(jobs, START); + if (thisJob == null) + thisJob = getJob(jobs, SUSPEND); + if (thisJob == null) + thisJob = getJob(jobs, RESUME); + + if (thisJob == null) { + Logger.error("No supported jobs, but joblist is not empty! Discarding remaining jobs"); + jobs.clear(); + } + else + jobs.remove(ClusterStorage.getPath(thisJob)); + } + } + + if (thisJob != null) { + String jobKey = thisJob.getItemPath()+":"+thisJob.getStepPath(); + int transitionId = thisJob.getTransition().getId(); + try { + if (transitionId==START) { + Logger.msg(5, "Testing start conditions"); + boolean start = assessStartConditions(thisJob); + if (start) { + Logger.msg(5, "Attempting to start"); + agent.execute(thisJob); + } + else { + Logger.msg(5, "Start conditions failed "+thisJob.getStepName()+" in "+thisJob.getItemPath()); + } + } + else if (transitionId==COMPLETE) { + Logger.msg(5, "Executing logic"); + runUCLogic(thisJob); + if (ignoredPaths.contains(jobKey)) + ignoredPaths.remove(jobKey); + } + else if (transitionId==SUSPEND) { + if (ignoredPaths.contains(jobKey)) { + if (errors.containsKey(jobKey)) { + thisJob.setOutcome(Gateway.getMarshaller().marshall(errors.get(jobKey))); + errors.remove(jobKey); + } + agent.execute(thisJob); + } + } + else if (transitionId==RESUME) { + if (!ignoredPaths.contains(jobKey)) + agent.execute(thisJob); + } + } catch (ScriptErrorException ex) { + errors.put(jobKey, ex.getErrors()); + ignoredPaths.add(jobKey); + } catch (InvalidTransitionException ex) { + // must have already been done by someone else - ignore + } catch (Throwable ex) { + Logger.error("Error executing "+thisJob.getTransition().getName()+" job:"); + Logger.error(ex); + ErrorInfo ei = new ErrorInfo(); + ei.setFatal(); + ei.addError(ex.getClass().getSimpleName()); + ei.addError(ex.getMessage()); + errors.put(jobKey, ei); + ignoredPaths.add(jobKey); + } + } + try { + synchronized (jobs) { + if (jobs.size() == 0) { + Logger.msg("Sleeping"); + while (active && jobs.size() == 0) + jobs.wait(2000); + } + } + } catch (InterruptedException ex) { } + } + + // shut down + try + { + Gateway.close(); + } + catch( Exception ex ) + { + Logger.error(ex); + } + } + + private static Job getJob(HashMap jobs, int transition) { + for (C2KLocalObject c2kLocalObject : jobs.values()) { + Job thisJob = (Job)c2kLocalObject; + if (thisJob.getTransition().getId() == transition) { + Logger.msg(1,"================================================================="); + Logger.msg(1, "Got "+thisJob.getTransition().getName()+" job for "+thisJob.getStepName()+" in "+thisJob.getItemPath()); + return thisJob; + } + } + return null; + } + + public boolean assessStartConditions(Job job) { + // default implementation - has no start conditions. + return true; + } + + public void runUCLogic(Job job) throws Exception { + // default implementation - the agent will execute any scripts defined when we execute + agent.execute(job); + } + + + /** + * Receives job from the AgentProxy. Reactivates thread if sleeping. + */ + @Override + public void add(Job contents) { + synchronized(jobs) { + Logger.msg(7, "Adding "+ClusterStorage.getPath(contents)); + jobs.put(ClusterStorage.getPath(contents), contents); + jobs.notify(); + } + + } + + @Override + public void control(String control, String msg) { + if (MemberSubscription.ERROR.equals(control)) + Logger.error("Error in job subscription: "+msg); + } + + /** + * Removes job removal notification from the AgentProxy. + */ + @Override + public void remove(String id) { + synchronized(jobs) { + Logger.msg(7, "Deleting "+id); + jobs.remove(id); + } + } + + public static UserCodeProcess getInstance() throws UnknownHostException { + return new UserCodeProcess(InetAddress.getLocalHost().getHostName(), "uc", Gateway.getProperties().getString("AuthResource", "Cristal")); + } + + static public void main(String[] args) + { + int status = 0; + + try + { + Gateway.init(readC2KArgs(args)); + UserCodeProcess proc = getInstance(); + new Thread(proc).start(); + Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() { + @Override + public void run() { + shutdown(); + } + })); + } + catch( Exception ex ) + { + Logger.error(ex); + + try + { + Gateway.close(); + } + catch(Exception ex1) + { + Logger.error(ex1); + } + status = 1; + System.exit(status); + } + } + + public String getDesc() { + return("Usercode Process"); + } + + public static void shutdown() { + active = false; + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/auth/Authenticator.java b/src/main/java/org/cristalise/kernel/process/auth/Authenticator.java new file mode 100644 index 0000000..2d92d4d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/auth/Authenticator.java @@ -0,0 +1,93 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.auth; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; + +/** + * This interface is used by the kernel to store an authenticated connection + * and/or token that will be used by kernel components. The CRISTAL property + * 'Authenticator' is used to specify the implementation used. It is + * instantiated by the connect() methods of the Gateway, and will be found in + * the AgentProxy returned by connect(). Lookup and ClusterStorage instances are + * initialized with this Authenticator, which is expected to maintain the same + * user's connection through the process lifetime, reconnecting if the + * connection is lost. + * + * @since 3.0 + * + */ +public interface Authenticator { + + /** + * Authenticates a CRISTAL agent. If this method returns true, then the + * connect method will create and return an AgentProxy for the given + * username using the Lookup and ProxyManager. + * + * @param agentName + * The username of the Agent to be authenticated. This must be + * already present as an Agent in the CRISTAL directory. + * @param password + * The Agent's password + * @param resource + * The authentication resource/domain/realm of the agent. + * Included so that domains may include CRISTAL users from + * different realms. This parameter is passed into the connect() + * method if required. May be null. + * @return a boolean indicating if the authentication was successful. If so, + * then the Gateway will generate an AgentProxy for the given user. + * @throws ObjectNotFoundException + * When the Agent doesn't exist + * @throws InvalidDataException + * When authentication fails for another reason + */ + public boolean authenticate(String agentName, String password, + String resource) throws InvalidDataException, + ObjectNotFoundException; + + /** + * Authenticates a superuser connection for the server. It must be able to + * act on behalf of any other Agent, as the server needs to do this. + * Credentials may be in the CRISTAL properties, or some other mechanism. + * + * @param resource + * @return + * @throws InvalidDataException + * @throws ObjectNotFoundException + */ + public boolean authenticate(String resource) throws InvalidDataException, + ObjectNotFoundException; + + /** + * Lookup and storage implementations that need to use user or superuser + * authentication can retrieve it using this method. This will be highly + * implementation specific. + * + * @return the connection/token created during authentication + */ + public Object getAuthObject(); + + /** + * Close or expire the connection as the CRISTAL process shuts down. + */ + public void disconnect(); +} diff --git a/src/main/java/org/cristalise/kernel/process/auth/ConsoleAuth.java b/src/main/java/org/cristalise/kernel/process/auth/ConsoleAuth.java new file mode 100644 index 0000000..319c792 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/auth/ConsoleAuth.java @@ -0,0 +1,65 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.auth; + +import java.util.Properties; +import java.util.Scanner; + +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.process.Gateway; + + +public class ConsoleAuth implements ProxyLogin { + + public ConsoleAuth() { + } + + @Override + public void initialize(Properties props) throws Exception { + + } + @Override + public AgentProxy authenticate(String resource) throws Exception { + AgentProxy user = null; + if (resource!=null) System.out.println("Please log in"+(resource.length()>0?"to "+resource:"")); + Scanner scan = new Scanner(System.in); + int loginAttempts = 0; + while (user == null && loginAttempts++ < 3) { + System.out.print("User:"); + String username = scan.nextLine(); + System.out.print("Password:"); + String pass = scan.nextLine(); + try { + user = Gateway.connect(username, pass, resource); + } catch (Exception ex) { + System.err.println(ex.getMessage()); + } + } + + if (user == null) { + System.err.println("Bye"); + System.exit(0); + } + return user; + + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/auth/ProxyLogin.java b/src/main/java/org/cristalise/kernel/process/auth/ProxyLogin.java new file mode 100644 index 0000000..9305d50 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/auth/ProxyLogin.java @@ -0,0 +1,42 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.auth; + +import java.util.Properties; + +import org.cristalise.kernel.entity.proxy.AgentProxy; + + +/** + * This interface is used by client processes to implement alternative login + * mechanisms aside from the standard username and password. Implementations may + * synchronize Agents with an external user library, such as Active Directory. + * Implementations are expected to set up the Gateway process and its + * authenticated components itself. + * + */ +public interface ProxyLogin { + + public void initialize(Properties props) throws Exception; + + public AgentProxy authenticate(String resource) throws Exception; + +} diff --git a/src/main/java/org/cristalise/kernel/process/module/Module.java b/src/main/java/org/cristalise/kernel/process/module/Module.java new file mode 100644 index 0000000..840614b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/Module.java @@ -0,0 +1,224 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import java.util.ArrayList; +import java.util.Properties; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.imports.ImportAgent; +import org.cristalise.kernel.entity.imports.ImportDependency; +import org.cristalise.kernel.entity.imports.ImportDependencyMember; +import org.cristalise.kernel.entity.imports.ImportItem; +import org.cristalise.kernel.entity.imports.ImportOutcome; +import org.cristalise.kernel.entity.imports.ImportRole; +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.scripting.ErrorInfo; +import org.cristalise.kernel.scripting.ScriptingEngineException; +import org.cristalise.kernel.utils.Logger; + + +public class Module extends ImportItem { + + private ModuleInfo info; + private String resURL; + private ModuleImports imports = new ModuleImports(); + private ArrayList config = new ArrayList(); + private ArrayList scripts = new ArrayList(); + + public Module() { + super(); + // Module properties + properties.add(new Property("Type", "Module", false)); + setInitialPath("/desc/modules/"); + setWorkflow("NoWorkflow"); + setWorkflowVer(0); + imports.list.add(this); + } + + public void runScript(String event, AgentProxy user, boolean isServer) throws ScriptingEngineException { + for (ModuleScript script : scripts) { + if (script.shouldRun(event, isServer)) { + Logger.msg("Running "+script.event+" "+script.target+" script from "+name); + Object result = script.getScript(ns, user).execute(); + if (result instanceof ErrorInfo) { + ErrorInfo error = (ErrorInfo) result; + Logger.error(error.toString()); + if (error.getFatal()) + throw new ScriptingEngineException("Fatal Script Error"); + } + else if (result != null) + Logger.msg(result.toString()); + } + } + } + + public void setModuleXML(String moduleXML) { + ImportOutcome moduleOutcome = new ImportOutcome("Module", 0, "last", null); + moduleOutcome.data = moduleXML; + outcomes.add(moduleOutcome); + } + + @Override + public void setNamespace(String ns) { + super.setNamespace(ns); + replaceProp(new Property("Namespace", ns, false)); + } + + @Override + public void setName(String name) { + super.setName(name); + replaceProp(new Property("Name", name, false)); + } + + private void replaceProp(Property newProp) { + for (Property prop : properties) { + if (prop.getName().equals("Namespace")) { + prop.setMutable(newProp.isMutable()); + prop.setValue(newProp.getValue()); + return; + } + } + properties.add(newProp); + } + public void importAll(ItemProxy serverEntity, AgentProxy systemAgent, String moduleXML, boolean reset) throws Exception { + setModuleXML(moduleXML); + + for (ModuleResource thisRes : imports.getResources()) { + try { + thisRes.setNamespace(ns); + thisRes.create(systemAgent.getPath(), reset); + } catch (Exception ex) { + Logger.error(ex); + Logger.die("Error importing module resources. Unsafe to continue."); + } + } + + for (ImportRole thisRole : imports.getRoles()) { + RolePath rolePath; + try { + String roleName = thisRole.name; + if (roleName.indexOf('/') > -1) roleName = roleName.substring(roleName.indexOf('/')+1); + rolePath = Gateway.getLookup().getRolePath(roleName); + if (rolePath.hasJobList() != thisRole.hasJobList()) { + Logger.msg("Module.importAll() - Role '"+thisRole.name+"' has incorrect joblist settings. Correcting."); + rolePath.setHasJobList(thisRole.hasJobList()); + Gateway.getLookupManager().createRole(rolePath); + } + } catch (ObjectNotFoundException ex) { + Logger.msg("Module.importAll() - Role '"+thisRole.name+"' not found. Creating."); + thisRole.create(systemAgent.getPath(), reset); + } + } + + for (ImportAgent thisAgent : imports.getAgents()) { + try { + Gateway.getLookup().getAgentPath(thisAgent.name); + Logger.msg(3, "Module.importAll() - User '"+thisAgent.name+"' found."); + continue; + } catch (ObjectNotFoundException ex) { } + Logger.msg("Module.importAll() - User '"+thisAgent.name+"' not found. Creating."); + thisAgent.create(systemAgent.getPath(), reset); + } + + for (ImportItem thisItem : imports.getItems()) { + thisItem.setNamespace(ns); + thisItem.create(systemAgent.getPath(), reset); + } + + } + + public Properties getProperties(boolean isServer) { + Properties props = new Properties(); + for (ModuleConfig thisProp : config) { + if (thisProp.include(isServer)) + props.put(thisProp.name, thisProp.value); + } + return props; + } + + public ArrayList getScripts() { + return scripts; + } + + public void setResURL(String resURL) { + this.resURL = resURL; + } + public String getDesc() { + return info.desc; + } + public String getVersion() { + return info.version; + } + public String getResURL() { + return resURL; + } + public ArrayList getDependencies() { + return info.dependency; + } + public boolean hasDependency(String dep) { + return info.dependency.contains(dep); + } + + public ModuleInfo getInfo() { + return info; + } + + public void setInfo(ModuleInfo info) { + this.info = info; + replaceProp(new Property("Version", info.version, true)); + } + + public ModuleImports getImports() { + return imports; + } + + public void setImports(ModuleImports imp) { + // Add dependency for all children + imports = imp; + ImportDependency children = new ImportDependency("Contents"); + for (ModuleImport thisImport : imports.list) { + DomainPath path = thisImport.domainPath; + if (path != null) + children.dependencyMemberList.add(new ImportDependencyMember(path.toString())); + } + dependencyList.add(children); + } + + public void setConfig(ArrayList config) { + this.config = config; + } + + public void setScripts(ArrayList scripts) { + this.scripts = scripts; + } + + public ArrayList getConfig() { + return config; + } + + +} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleConfig.java b/src/main/java/org/cristalise/kernel/process/module/ModuleConfig.java new file mode 100644 index 0000000..1165e31 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleConfig.java @@ -0,0 +1,42 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +public class ModuleConfig { + + public String name; + public String value; + public String target; + + public ModuleConfig() { + } + + public ModuleConfig(String name, String value, String target) { + super(); + this.name = name; + this.value = value; + this.target = target; + } + + public boolean include(boolean isServer) { + return (target == null || target.length() == 0 || isServer == target.equals("server")); + } +} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleException.java b/src/main/java/org/cristalise/kernel/process/module/ModuleException.java new file mode 100644 index 0000000..e09107e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleException.java @@ -0,0 +1,29 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +public class ModuleException extends Exception { + + public ModuleException(String msg) { + super(msg); + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleImport.java b/src/main/java/org/cristalise/kernel/process/module/ModuleImport.java new file mode 100644 index 0000000..22faa5a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleImport.java @@ -0,0 +1,87 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; + + +public abstract class ModuleImport { + + protected String ns; + protected String name; + protected DomainPath domainPath; + protected ItemPath itemPath; + + public ModuleImport() { + } + + public abstract void create(AgentPath agentPath, boolean reset) throws ObjectNotFoundException, + ObjectCannotBeUpdated, CannotManageException, ObjectAlreadyExistsException, InvalidCollectionModification; + + public void setID( String uuid ) throws InvalidItemPathException + { + if (uuid != null && uuid.length() > 0) itemPath = new ItemPath(uuid); + } + + public String getID() { + return itemPath==null?null:itemPath.getUUID().toString(); + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public void setNamespace(String ns) { + this.ns = ns; + } + + public String getNamespace() { + return ns; + } + + public DomainPath getDomainPath() { + return domainPath; + } + + public void setDomainPath(DomainPath domainPath) { + this.domainPath = domainPath; + } + + public ItemPath getItemPath() { + return itemPath; + } + + public void setItemPath(ItemPath itemPath) { + this.itemPath = itemPath; + } +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleImports.java b/src/main/java/org/cristalise/kernel/process/module/ModuleImports.java new file mode 100644 index 0000000..53c7e9d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleImports.java @@ -0,0 +1,78 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import java.util.ArrayList; + +import org.cristalise.kernel.entity.imports.ImportAgent; +import org.cristalise.kernel.entity.imports.ImportItem; +import org.cristalise.kernel.entity.imports.ImportRole; +import org.cristalise.kernel.utils.CastorArrayList; + + +public class ModuleImports extends CastorArrayList { + + public ModuleImports() + { + super(); + } + + public ModuleImports(ArrayList aList) + { + super(aList); + } + + public ArrayList getResources() { + ArrayList subset = new ArrayList(); + for (ModuleImport imp : list) { + if (imp instanceof ModuleResource) + subset.add((ModuleResource)imp); + } + return subset; + } + + public ArrayList getItems() { + ArrayList subset = new ArrayList(); + for (ModuleImport imp : list) { + if (imp instanceof ImportItem) + subset.add((ImportItem)imp); + } + return subset; + } + + public ArrayList getAgents() { + ArrayList subset = new ArrayList(); + for (ModuleImport imp : list) { + if (imp instanceof ImportAgent) + subset.add((ImportAgent)imp); + } + return subset; + } + + public ArrayList getRoles() { + ArrayList subset = new ArrayList(); + for (ModuleImport imp : list) { + if (imp instanceof ImportRole) + subset.add((ImportRole)imp); + } + return subset; + } +} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleInfo.java b/src/main/java/org/cristalise/kernel/process/module/ModuleInfo.java new file mode 100644 index 0000000..8f482fc --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleInfo.java @@ -0,0 +1,34 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import java.util.ArrayList; + +public class ModuleInfo { + + public String desc; + public String version; + public ArrayList dependency = new ArrayList(); + + public ModuleInfo() { + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleManager.java b/src/main/java/org/cristalise/kernel/process/module/ModuleManager.java new file mode 100644 index 0000000..d95abe6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleManager.java @@ -0,0 +1,211 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import java.io.IOException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Properties; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.persistency.outcome.OutcomeValidator; +import org.cristalise.kernel.persistency.outcome.Schema; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.scripting.ScriptingEngineException; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.Logger; + + +public class ModuleManager { + ArrayList modules = new ArrayList(); + HashMap modulesXML = new HashMap(); + Properties props = new Properties(); + AgentProxy user; + boolean isServer; + OutcomeValidator moduleValidator; + + public ModuleManager(Enumeration moduleEnum, boolean isServer) throws ModuleException { + this.isServer = isServer; + try { + Schema moduleSchema = new Schema("Module", 0, + FileStringUtility.url2String(Gateway.getResource().getKernelResourceURL("boot/OD/Module.xsd"))); + moduleValidator = new OutcomeValidator(moduleSchema); + } catch (InvalidDataException ex) { + Logger.error(ex); + throw new ModuleException("Module Schema is not valid"); + } catch (IOException ex) { + throw new ModuleException("Could not load Module Schema from kernel resources"); + } + ArrayList loadedModules = new ArrayList(); + ArrayList moduleNs = new ArrayList(); + while(moduleEnum.hasMoreElements()) { + URL newModuleURL = moduleEnum.nextElement(); + try { + String moduleXML = FileStringUtility.url2String(newModuleURL); + String errors = moduleValidator.validate(moduleXML); + if (errors.length() > 0) + throw new ModuleException("Module XML found at "+newModuleURL+" was not valid: "+errors); + Module newModule = (Module)Gateway.getMarshaller().unmarshall(moduleXML); + if (newModule.getResURL() != null && newModule.getResURL().length()>0) Gateway.getResource().addModuleBaseURL(newModule.getNamespace(), newModule.getResURL()); + modules.add(newModule); + modulesXML.put(newModule.getNamespace(), moduleXML); + if (loadedModules.contains(newModule.getName())) throw new ModuleException("Module name clash: "+newModule.getName()); + if (moduleNs.contains(newModule.getNamespace())) throw new ModuleException("Module namespace clash: "+newModule.getNamespace()); + Logger.debug(4, "Module found: "+newModule.getNamespace()+" - "+newModule.getName()); + loadedModules.add(newModule.getName()); moduleNs.add(newModule.getNamespace()); + } catch (ModuleException e) { + Logger.error("Could not load module description from "+newModuleURL); + throw e; + } catch (Exception e) { + Logger.error(e); + throw new ModuleException("Could not load module.xml from "+newModuleURL); + } + } + + Logger.debug(5, "Checking dependencies"); + boolean allDepsPresent = true; + + ArrayList prevModules = new ArrayList(); + for (int i=0; i deps = thisMod.getDependencies(); + depClean = true; + for (String dep : deps) { + Logger.msg(6, thisMod.getName()+" depends on "+dep); + if (!loadedModules.contains(dep)) { + Logger.error("UNMET MODULE DEPENDENCY: "+thisMod.getName()+" requires "+dep); + allDepsPresent = false; + } + else if (!prevModules.contains(dep)) { + Logger.msg(1, "ModuleManager: Shuffling "+thisMod.getName()+" to the end to fulfil dependency on "+dep); + modules.remove(i); + modules.add(thisMod); + thisMod = modules.get(i); + skipped++; + depClean = false; + break; + } + } + if (skipped > modules.size()-i) { + StringBuffer badMod = new StringBuffer(); + for (Module mod : modules.subList(i, modules.size())) { + badMod.append(mod.getName()).append(" "); + } + Logger.die("Circular module dependencies involving: "+badMod); + } + } + // Current module is 'next', this is the correct order to load the properties + Properties modProp = thisMod.getProperties(isServer); + for (Enumeration e = modProp.propertyNames(); e.hasMoreElements();) { + String propName = (String)e.nextElement(); + props.put(propName, modProp.get(propName)); + } + prevModules.add(thisMod.getName()); + } + if (!allDepsPresent) Logger.die("Unmet module dependencies. Cannot continue"); + } + + public void setUser(AgentProxy user) { + this.user = user; + } + + public String getModuleVersions() { + StringBuffer ver = new StringBuffer(); + for (Module thisMod : modules) { + if (ver.length()>0) ver.append("; "); + ver.append(thisMod.getName()+" ("+thisMod.getVersion()+")"); + } + return ver.toString(); + } + + + public Properties getAllModuleProperties() { + return props; + } + + public void runScripts(String event) { + for (Module thisMod : modules) { + try { + thisMod.runScript(event, user, isServer); + } catch (ScriptingEngineException e) { + Logger.error(e); + Logger.die(e.getMessage()); + } + } + } + + public void registerModules() throws ModuleException { + ItemProxy serverEntity; + try { + serverEntity = Gateway.getProxyManager().getProxy(new DomainPath("/servers/"+Gateway.getProperties().getString("ItemServer.name"))); + } catch (ObjectNotFoundException e) { + throw new ModuleException("Cannot find local server name."); + } + Logger.debug(3, "Registering modules"); + + boolean reset = Gateway.getProperties().getBoolean("Module.reset", false); + + for (Module thisMod : modules) { + + Logger.msg("Registering module "+thisMod.getName()); + try { + String thisResetKey = "Module."+thisMod.getNamespace()+".reset"; + boolean thisReset = reset; + if (Gateway.getProperties().containsKey(thisResetKey)) + thisReset = Gateway.getProperties().getBoolean(thisResetKey); + thisMod.importAll(serverEntity, user, modulesXML.get(thisMod.getNamespace()), thisReset); + } catch (Exception e) { + Logger.error(e); + throw new ModuleException("Error importing items for module "+thisMod.getName()); + } + Logger.msg("Module "+thisMod.getName()+" registered"); + + try { + thisMod.runScript("startup", user, true); + } catch (ScriptingEngineException e) { + Logger.error(e); + throw new ModuleException("Error in startup script for module "+thisMod.getName()); + } + + } + } + + public void dumpModules() { + for (Module thisMod : modules) { + try { + FileStringUtility.string2File(thisMod.getName()+".xml", Gateway.getMarshaller().marshall(thisMod)); + } catch (Exception e) { + Logger.error(e); + } + } + + } +} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleResource.java b/src/main/java/org/cristalise/kernel/process/module/ModuleResource.java new file mode 100644 index 0000000..74b5673 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleResource.java @@ -0,0 +1,80 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.process.Bootstrap; +import org.cristalise.kernel.utils.Logger; + + +public class ModuleResource extends ModuleImport { + + public int version; + public String resourceType; + public String resourceLocation; + + public ModuleResource() { + // if not given, version defaults to 0 + version = 0; + } + + @Override + public void create(AgentPath agentPath, boolean reset) + throws ObjectNotFoundException, ObjectCannotBeUpdated, + CannotManageException, ObjectAlreadyExistsException { + try { + domainPath = Bootstrap.verifyResource(ns, name, version, resourceType, itemPath, resourceLocation, reset); + } catch (Exception e) { + Logger.error(e); + throw new CannotManageException("Exception verifying module resource "+ns+"/"+name); + } + } + + public int getVersion() { + return version; + } + + public void setVersion(int version) { + this.version = version; + } + + public String getResourceType() { + return resourceType; + } + + public void setResourceType(String resourceType) { + this.resourceType = resourceType; + } + + public String getResourceLocation() { + return resourceLocation; + } + + public void setResourceLocation(String resourceLocation) { + this.resourceLocation = resourceLocation; + } + + +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleScript.java b/src/main/java/org/cristalise/kernel/process/module/ModuleScript.java new file mode 100644 index 0000000..4e81864 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleScript.java @@ -0,0 +1,53 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.module; + +import org.cristalise.kernel.entity.proxy.AgentProxy; +import org.cristalise.kernel.scripting.Script; +import org.cristalise.kernel.scripting.ScriptingEngineException; + +public class ModuleScript { + + + public String target; + public String event; + public String lang; + public String script; + public ModuleScript() { + } + + public ModuleScript(String target, String event, String lang, String script) { + super(); + this.target = target; + this.event = event; + this.lang = lang; + this.script = script; + } + + public Script getScript(String ns, AgentProxy user) throws ScriptingEngineException { + return new Script(lang, ns+" "+target+" "+event, script, user); + } + + public boolean shouldRun(String event, boolean isServer) { + return ((this.target == null || this.target.length() == 0 || isServer == target.equals("server")) && + (this.event == null || this.event.length() == 0 || event.equals(this.event))); + } +} diff --git a/src/main/java/org/cristalise/kernel/process/resource/BadArgumentsException.java b/src/main/java/org/cristalise/kernel/process/resource/BadArgumentsException.java new file mode 100644 index 0000000..d8d7dc9 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/BadArgumentsException.java @@ -0,0 +1,37 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.resource; + +public class BadArgumentsException extends Exception { + + public BadArgumentsException() { + super(); + } + + public BadArgumentsException(String message) { + super(message); + } + + public BadArgumentsException(Throwable cause) { + super(cause); + } + +} diff --git a/src/main/java/org/cristalise/kernel/process/resource/DefaultResourceImportHandler.java b/src/main/java/org/cristalise/kernel/process/resource/DefaultResourceImportHandler.java new file mode 100644 index 0000000..dbd2d44 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/DefaultResourceImportHandler.java @@ -0,0 +1,106 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.resource; + +import java.util.HashSet; +import java.util.Set; + +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.PropertyDescriptionList; + + +public class DefaultResourceImportHandler implements ResourceImportHandler { + + String schemaName; + String typeRoot; + DomainPath typeRootPath; + String wfDef; + PropertyDescriptionList props; + + public DefaultResourceImportHandler(String resType) throws Exception { + if (resType.equals("CA")) { + wfDef = "ManageCompositeActDef"; + schemaName = "CompositeActivityDef"; + typeRoot = "/desc/ActivityDesc"; + } + else if (resType.equals("EA")) { + wfDef = "ManageElementaryActDef"; + schemaName = "ElementaryActivityDef"; + typeRoot = "/desc/ActivityDesc"; + } + else if (resType.equals("OD")) { + wfDef = "ManageSchema"; + schemaName = "Schema"; + typeRoot = "/desc/OutcomeDesc"; + } + else if (resType.equals("SC")) { + wfDef = "ManageScript"; + schemaName = "Script"; + typeRoot = "/desc/Script"; + } + else if (resType.equals("SM")) { + wfDef = "ManageStateMachine"; + schemaName = "StateMachine"; + typeRoot = "/desc/StateMachine"; + } + else throw new Exception("Unknown bootstrap item type: "+resType); + typeRootPath = new DomainPath(typeRoot); + props = (PropertyDescriptionList)Gateway.getMarshaller().unmarshall(Gateway.getResource().getTextResource(null, "boot/property/"+resType+"Prop.xml")); + } + + @Override + public DomainPath getTypeRoot() { + return typeRootPath; + } + + @Override + public String getName() { + return schemaName; + } + + @Override + public DomainPath getPath(String name, String ns) throws Exception { + return new DomainPath(typeRoot+"/system/"+(ns==null?"kernel":ns)+'/'+name); + } + + @Override + public Set getResourceOutcomes(String name, String ns, String location, int version) throws Exception { + HashSet retArr = new HashSet(); + String data = Gateway.getResource().getTextResource(ns, location); + if (data == null) + throw new Exception("No data found for "+schemaName+" "+name); + Outcome resOutcome = new Outcome(0, data, schemaName, 0); + retArr.add(resOutcome); + return retArr; + } + + @Override + public PropertyDescriptionList getPropDesc() throws Exception { + return props; + } + + @Override + public String getWorkflowName() throws Exception { + return wfDef; + } +} diff --git a/src/main/java/org/cristalise/kernel/process/resource/Resource.java b/src/main/java/org/cristalise/kernel/process/resource/Resource.java new file mode 100644 index 0000000..25b1ee8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/Resource.java @@ -0,0 +1,196 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.resource; + +//Java +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Hashtable; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2005/10/05 07:39:36 $ + * @version $Revision: 1.71 $ + **************************************************************************/ +public class Resource implements ResourceLoader { + + private final Hashtable txtCache = new Hashtable(); + private final URL baseURL; + private final HashMap moduleBaseURLs = new HashMap(); + private final HashMap allBaseURLs = new HashMap(); + + public Resource() throws InvalidDataException { + baseURL = getURLorResURL("org/cristalise/kernel/utils/resources/"); + allBaseURLs.put(null, baseURL); + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#getKernelBaseURL() + */ + @Override + public URL getKernelBaseURL() { + return baseURL; + } + + @Override + public ClassLoader getClassLoader(String className) { + return Resource.class.getClassLoader(); + } + + @Override + public Class getClassForName(String name) throws ClassNotFoundException { + return Class.forName(name); + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#getKernelResourceURL(java.lang.String) + */ + @Override + public URL getKernelResourceURL(String resName) throws MalformedURLException { + return new URL(baseURL, resName); + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#addModuleBaseURL(java.lang.String, java.net.URL) + */ + @Override + public void addModuleBaseURL(String ns, URL newBaseURL) { + moduleBaseURLs.put(ns, newBaseURL); + allBaseURLs.put(ns, newBaseURL); + Logger.msg("Adding resource URL for "+ns+": "+newBaseURL.toString()); + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#addModuleBaseURL(java.lang.String, java.lang.String) + */ + @Override + public void addModuleBaseURL(String ns, String newBaseURL) throws InvalidDataException { + addModuleBaseURL(ns, getURLorResURL(newBaseURL)); + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#getModuleBaseURLs() + */ + @Override + public HashMap getModuleBaseURLs() { + return moduleBaseURLs; + } + + private HashMap getAllBaseURLs() { + return allBaseURLs; + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#getModuleResourceURL(java.lang.String, java.lang.String) + */ + @Override + public URL getModuleResourceURL(String ns, String resName) throws MalformedURLException { + return new URL(moduleBaseURLs.get(ns), resName); + } + + static private URL getURLorResURL(String newURL) throws InvalidDataException { + URL result; + try { + result = new URL(newURL); + } catch (java.net.MalformedURLException ex) { + //it is assumed that a 'wrong' URL denotes a directory + //of files resolvable from the CLASSPATH + result = Resource.class.getClassLoader().getResource(newURL); + } + if (result == null) { + Logger.error("URL "+newURL+" could not be found"); + throw new InvalidDataException(); + } + return result; + } + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#findTextResource(java.lang.String) + */ + + @Override + public String findTextResource(String resName) { + for (String ns : getAllBaseURLs().keySet()) { + try { + return getTextResource(ns, resName); + } catch (ObjectNotFoundException ex) { } + } + Logger.warning("Text resource '"+resName+"' not found."); + return null; + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#getAllTextResources(java.lang.String) + */ + @Override + public HashMap getAllTextResources(String resName) { + HashMap results = new HashMap(); + for (String ns : getAllBaseURLs().keySet()) { + try { + results.put(ns, getTextResource(ns, resName)); + } catch (ObjectNotFoundException ex) { } + } + return results; + } + + /* (non-Javadoc) + * @see org.cristalise.kernel.utils.ResourceLoader#getTextResource(java.lang.String, java.lang.String) + */ + @Override + public String getTextResource(String ns, String resName) throws ObjectNotFoundException + // throws IOException + { + Logger.msg(8, "Resource::getTextResource() - Getting resource from "+ns+": " + resName); + + if (txtCache.containsKey(ns+'/'+resName)) { + return txtCache.get(ns+'/'+resName); + } + + try { + + String newRes = null; + URL loc; + + if (ns == null) // kernel + loc = getKernelResourceURL(resName); + else + loc = getModuleResourceURL(ns, resName); + Logger.msg(5, "Loading resource: "+loc.toString()); + newRes = FileStringUtility.url2String(loc); + txtCache.put(ns+'/'+resName, newRes); + return newRes; + } catch (Exception e) { + throw new ObjectNotFoundException(e.getMessage()); + } + } + + @Override + public Enumeration getModuleDefURLs() throws Exception { + return ClassLoader.getSystemResources("META-INF/cristal/module.xml"); + } +} diff --git a/src/main/java/org/cristalise/kernel/process/resource/ResourceImportHandler.java b/src/main/java/org/cristalise/kernel/process/resource/ResourceImportHandler.java new file mode 100644 index 0000000..9d37e31 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/ResourceImportHandler.java @@ -0,0 +1,68 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.resource; + +import java.util.Set; + +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.property.PropertyDescriptionList; + + +public interface ResourceImportHandler { + + + /** Returns the DomainPath for a specific resource + * @param ns - module namespace + * @param name - resource name + * @return + */ + public DomainPath getPath(String name, String ns) throws Exception; + + /** Generates the outcomes that the resource should contain. + * @param res - the module resource definition + * @return a set of outcomes to be synced with the resource item. + * @throws Exception - if the supplied resources are not valid + */ + public Set getResourceOutcomes(String name, String ns, String location, int version) throws Exception; + + /** Gives the CompActDef name to instantiate to provide the workflow for this type of resource. + * Should be found in the CA typeroot (/desc/ActivityDesc/) + * @return String workflow name + * @throws Exception + */ + public String getWorkflowName() throws Exception; + + /** Should return all of the Properties the resource Item + * will have on creation. The Property 'Name' will be created and populated automatically, even if not declared. + * @return a PropertyDescriptionList - an arraylist of PropertyDescriptions + * @throws Exception + */ + public PropertyDescriptionList getPropDesc() throws Exception; + + /** The directory context to search for existing resources. The name of the resource must be unique below this point. + * @return Root path + */ + public DomainPath getTypeRoot(); + + public String getName(); + +} diff --git a/src/main/java/org/cristalise/kernel/process/resource/ResourceLoader.java b/src/main/java/org/cristalise/kernel/process/resource/ResourceLoader.java new file mode 100644 index 0000000..4ef0e9d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/ResourceLoader.java @@ -0,0 +1,67 @@ +/** + * This file is part of the CRISTAL-iSE kernel. + * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved. + * + * This library is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published + * by the Free Software Foundation; either version 3 of the License, or (at + * your option) any later version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public + * License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * http://www.fsf.org/licensing/licenses/lgpl.html + */ +package org.cristalise.kernel.process.resource; + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import java.util.HashMap; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; + + +public interface ResourceLoader { + + public URL getKernelBaseURL(); + + public URL getKernelResourceURL(String resName) + throws MalformedURLException; + + public void addModuleBaseURL(String ns, URL newBaseURL); + + public void addModuleBaseURL(String ns, String newBaseURL) + throws InvalidDataException; + + public HashMap getModuleBaseURLs(); + + public URL getModuleResourceURL(String ns, String resName) + throws MalformedURLException; + + /************************************************************************** + * Gets any text resource files + **************************************************************************/ + + public String findTextResource(String resName); + + public HashMap getAllTextResources(String resName); + + public String getTextResource(String ns, String resName) + throws ObjectNotFoundException; + + public Class getClassForName(String name) + throws ClassNotFoundException; + + public ClassLoader getClassLoader(String className); + + public Enumeration getModuleDefURLs() throws Exception; + +} \ No newline at end of file -- cgit v1.2.3