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/entity/C2KLocalObject.java | 52 +++ .../org/cristalise/kernel/entity/CorbaServer.java | 204 +++++++++ .../kernel/entity/ItemImplementation.java | 333 ++++++++++++++ .../cristalise/kernel/entity/TraceableEntity.java | 154 +++++++ .../cristalise/kernel/entity/TraceableLocator.java | 90 ++++ .../kernel/entity/agent/ActiveEntity.java | 156 +++++++ .../kernel/entity/agent/ActiveLocator.java | 100 +++++ .../kernel/entity/agent/AgentImplementation.java | 137 ++++++ .../org/cristalise/kernel/entity/agent/Job.java | 484 +++++++++++++++++++++ .../kernel/entity/agent/JobArrayList.java | 42 ++ .../cristalise/kernel/entity/agent/JobList.java | 138 ++++++ .../kernel/entity/agent/package-info.java | 32 ++ .../cristalise/kernel/entity/imports/Geometry.java | 48 ++ .../kernel/entity/imports/ImportAgent.java | 118 +++++ .../kernel/entity/imports/ImportAggregation.java | 91 ++++ .../entity/imports/ImportAggregationMember.java | 55 +++ .../kernel/entity/imports/ImportDependency.java | 107 +++++ .../entity/imports/ImportDependencyMember.java | 48 ++ .../kernel/entity/imports/ImportItem.java | 280 ++++++++++++ .../kernel/entity/imports/ImportOutcome.java | 48 ++ .../kernel/entity/imports/ImportRole.java | 75 ++++ .../org/cristalise/kernel/entity/package-info.java | 39 ++ .../cristalise/kernel/entity/proxy/AgentProxy.java | 323 ++++++++++++++ .../kernel/entity/proxy/DomainPathSubscriber.java | 38 ++ .../cristalise/kernel/entity/proxy/ItemProxy.java | 390 +++++++++++++++++ .../kernel/entity/proxy/MemberSubscription.java | 141 ++++++ .../kernel/entity/proxy/ProxyClientConnection.java | 208 +++++++++ .../kernel/entity/proxy/ProxyManager.java | 277 ++++++++++++ .../kernel/entity/proxy/ProxyMessage.java | 129 ++++++ .../kernel/entity/proxy/ProxyObserver.java | 47 ++ .../kernel/entity/proxy/ProxyServer.java | 129 ++++++ .../kernel/entity/proxy/ProxyServerConnection.java | 145 ++++++ .../kernel/entity/proxy/package-info.java | 76 ++++ .../kernel/entity/transfer/TransferItem.java | 177 ++++++++ .../kernel/entity/transfer/TransferSet.java | 94 ++++ .../kernel/entity/transfer/package-info.java | 36 ++ 36 files changed, 5041 insertions(+) create mode 100644 src/main/java/org/cristalise/kernel/entity/C2KLocalObject.java create mode 100644 src/main/java/org/cristalise/kernel/entity/CorbaServer.java create mode 100644 src/main/java/org/cristalise/kernel/entity/ItemImplementation.java create mode 100644 src/main/java/org/cristalise/kernel/entity/TraceableEntity.java create mode 100644 src/main/java/org/cristalise/kernel/entity/TraceableLocator.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/ActiveEntity.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/ActiveLocator.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/AgentImplementation.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/Job.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/JobArrayList.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/JobList.java create mode 100644 src/main/java/org/cristalise/kernel/entity/agent/package-info.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/Geometry.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportAgent.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportAggregation.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportAggregationMember.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportDependency.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportDependencyMember.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportItem.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportOutcome.java create mode 100644 src/main/java/org/cristalise/kernel/entity/imports/ImportRole.java create mode 100644 src/main/java/org/cristalise/kernel/entity/package-info.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/AgentProxy.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/DomainPathSubscriber.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ItemProxy.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/MemberSubscription.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ProxyClientConnection.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ProxyManager.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ProxyMessage.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ProxyObserver.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ProxyServer.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/ProxyServerConnection.java create mode 100644 src/main/java/org/cristalise/kernel/entity/proxy/package-info.java create mode 100644 src/main/java/org/cristalise/kernel/entity/transfer/TransferItem.java create mode 100644 src/main/java/org/cristalise/kernel/entity/transfer/TransferSet.java create mode 100644 src/main/java/org/cristalise/kernel/entity/transfer/package-info.java (limited to 'src/main/java/org/cristalise/kernel/entity') diff --git a/src/main/java/org/cristalise/kernel/entity/C2KLocalObject.java b/src/main/java/org/cristalise/kernel/entity/C2KLocalObject.java new file mode 100644 index 0000000..18635ed --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/C2KLocalObject.java @@ -0,0 +1,52 @@ +/** + * 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.entity; + + +/** + * Objects that are to be stored by Cristal Entities must implement this interface and be (un)marshallable by Castor + * i.e. have a map file properly registered in the kernel. Domain implementors should not create new C2KLocalObjects + *

Each object will be stored as the path /clustertype/name in most cases. Exceptions are: + *

+ * + * @see org.cristalise.kernel.persistency.ClusterStorage + * @see org.cristalise.kernel.persistency.ClusterStorageManager + * + * @author Andrew Branson + * + * $Revision: 1.5 $ + * $Date: 2004/01/22 11:10:41 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + */ + +public interface C2KLocalObject { + + public void setName(String name); + public String getName(); + + public String getClusterType(); +} diff --git a/src/main/java/org/cristalise/kernel/entity/CorbaServer.java b/src/main/java/org/cristalise/kernel/entity/CorbaServer.java new file mode 100644 index 0000000..a16d3d1 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/CorbaServer.java @@ -0,0 +1,204 @@ +/** + * 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.entity; + +import java.util.Map; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.AgentHelper; +import org.cristalise.kernel.entity.ItemHelper; +import org.cristalise.kernel.entity.agent.ActiveEntity; +import org.cristalise.kernel.entity.agent.ActiveLocator; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.InvalidAgentPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; +import org.cristalise.kernel.utils.SoftCache; +import org.omg.PortableServer.POA; +import org.omg.PortableServer.POAManager; +import org.omg.PortableServer.Servant; +import org.omg.PortableServer.POAManagerPackage.AdapterInactive; + + +/************************************************************************** + * + * $Revision: 1.8 $ + * $Date: 2005/10/13 08:13:44 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + + +public class CorbaServer { + private final Map mItemCache; + private POA mRootPOA; + private POA mItemPOA; + private POA mAgentPOA; + private POAManager mPOAManager; + + public CorbaServer() throws InvalidDataException { + mItemCache = new SoftCache(50); + + // init POA + try { + setupPOA(); + mPOAManager.activate(); + } catch (Exception ex) { + Logger.error(ex); + throw new InvalidDataException("Error initialising POA"); + } + + new Thread(new Runnable() { + @Override + public void run() { + Thread.currentThread().setName("ORB Invoker"); + Gateway.getORB().run(); + } + }).start(); + } + + public void close() { + try { + mPOAManager.deactivate(true, true); + } catch (AdapterInactive ex) { + Logger.error(ex); + } + } + + /************************************************************************** + * Initialises the C2KRootPOA with policies which are suitable for Factory objects + **************************************************************************/ + public void setupPOA() throws Exception { + + //Initialise the RootPOA + mRootPOA = org.omg.PortableServer.POAHelper.narrow( + Gateway.getORB().resolve_initial_references("RootPOA")); + + //Initilaise the default POAManager + + mPOAManager = mRootPOA.the_POAManager(); + + // Create POA for use by the entities + org.omg.CORBA.Policy[] policies = new org.omg.CORBA.Policy[6]; + + policies[0] = mRootPOA.create_id_assignment_policy( + org.omg.PortableServer.IdAssignmentPolicyValue.USER_ID); + policies[1] = mRootPOA.create_lifespan_policy( + org.omg.PortableServer.LifespanPolicyValue.PERSISTENT); + policies[2] = mRootPOA.create_servant_retention_policy( + org.omg.PortableServer.ServantRetentionPolicyValue.NON_RETAIN); + policies[3] = mRootPOA.create_id_uniqueness_policy( + org.omg.PortableServer.IdUniquenessPolicyValue.UNIQUE_ID); + policies[4] = mRootPOA.create_request_processing_policy( + org.omg.PortableServer.RequestProcessingPolicyValue. + USE_SERVANT_MANAGER); + policies[5] = mRootPOA.create_implicit_activation_policy( + org.omg.PortableServer.ImplicitActivationPolicyValue. + NO_IMPLICIT_ACTIVATION); + + mItemPOA = mRootPOA.create_POA( "Item", + mRootPOA.the_POAManager(), + policies ); + mAgentPOA = mRootPOA.create_POA( "Agent", + mRootPOA.the_POAManager(), + policies ); + + //Create the locators + TraceableLocator itemLocator = new TraceableLocator(); + mItemPOA.set_servant_manager( itemLocator._this( Gateway.getORB() ) ); + + ActiveLocator agentLocator = new ActiveLocator(); + mAgentPOA.set_servant_manager( agentLocator._this( Gateway.getORB() ) ); + + } + + + /************************************************************************** + * Returns a CORBA servant for a pre-existing entity + * @throws ObjectNotFoundException + **************************************************************************/ + public TraceableEntity getItem(ItemPath itemPath) throws ObjectNotFoundException { + Servant item = null; + if (!itemPath.exists()) throw new ObjectNotFoundException(itemPath+" does not exist"); + synchronized (mItemCache) { + item = mItemCache.get(itemPath); + if (item == null) { + Logger.msg(7, "Creating new servant for "+itemPath); + item = new TraceableEntity(itemPath, mItemPOA); + mItemCache.put(itemPath, item); + } + } + return (TraceableEntity)item; + } + + /************************************************************************** + * Returns a CORBA servant for a pre-existing entity + **************************************************************************/ + public ActiveEntity getAgent(AgentPath agentPath) throws InvalidAgentPathException, ObjectNotFoundException { + Servant agent = null; + if (!agentPath.exists()) throw new ObjectNotFoundException(agentPath+" does not exist"); + synchronized (mItemCache) { + agent = mItemCache.get(agentPath); + if (agent == null) { + Logger.msg(7, "Creating new servant for "+agentPath); + agent = new ActiveEntity(agentPath, mAgentPOA); + mItemCache.put(agentPath, agent); + } + else if (!(agent instanceof ActiveEntity)) + throw new InvalidAgentPathException("Item "+agentPath+" was not an agent"); + } + return (ActiveEntity)agent; + } + + /** + * @param itemPath + * @return + */ + public TraceableEntity createItem(ItemPath itemPath) throws CannotManageException, ObjectAlreadyExistsException { + + if (itemPath.exists()) throw new ObjectAlreadyExistsException(); + org.omg.CORBA.Object obj = mItemPOA.create_reference_with_id(itemPath.getOID(), ItemHelper.id()); + itemPath.setIOR(obj); + TraceableEntity item = new TraceableEntity(itemPath, mItemPOA); + synchronized (mItemCache) { + mItemCache.put(itemPath, item); + } + return item; + } + + public ActiveEntity createAgent(AgentPath agentPath) throws CannotManageException, ObjectAlreadyExistsException { + if (agentPath.exists()) throw new ObjectAlreadyExistsException(); + org.omg.CORBA.Object obj = mAgentPOA.create_reference_with_id(agentPath.getOID(), AgentHelper.id()); + agentPath.setIOR(obj); + ActiveEntity agent; + agent = new ActiveEntity(agentPath, mAgentPOA); + synchronized (mItemCache) { + mItemCache.put(agentPath, agent); + } + return agent; + + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/ItemImplementation.java b/src/main/java/org/cristalise/kernel/entity/ItemImplementation.java new file mode 100644 index 0000000..ccc2706 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/ItemImplementation.java @@ -0,0 +1,333 @@ +/** + * 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.entity; + +import java.util.UUID; + +import org.cristalise.kernel.collection.Collection; +import org.cristalise.kernel.collection.CollectionArrayList; +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.entity.ItemOperations; +import org.cristalise.kernel.entity.agent.JobArrayList; +import org.cristalise.kernel.events.Event; +import org.cristalise.kernel.events.History; +import org.cristalise.kernel.lifecycle.instance.CompositeActivity; +import org.cristalise.kernel.lifecycle.instance.Workflow; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStepContainer; +import org.cristalise.kernel.lifecycle.instance.predefined.item.ItemPredefinedStepContainer; +import org.cristalise.kernel.lifecycle.instance.stateMachine.Transition; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.TransactionManager; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.utils.Logger; + + +public class ItemImplementation implements ItemOperations { + + protected final TransactionManager mStorage; + protected final ItemPath mItemPath; + + protected ItemImplementation(ItemPath key) { + this.mStorage = Gateway.getStorage(); + this.mItemPath = key; + } + + @Override + public SystemKey getSystemKey() { + return mItemPath.getSystemKey(); + } + + public UUID getUUID() { + return mItemPath.getUUID(); + } + + @Override + public void initialise(SystemKey agentId, String propString, String initWfString, + String initCollsString) throws AccessRightsException, + InvalidDataException, PersistencyException + { + Logger.msg(5, "Item::initialise("+mItemPath+") - agent:"+agentId); + Object locker = new Object(); + + AgentPath agentPath; + try { + agentPath = new AgentPath(agentId); + } catch (InvalidItemPathException e) { + throw new AccessRightsException("Invalid Agent Id:" + agentId); + } + + // must supply properties + if (propString == null || propString.length() == 0) { + throw new InvalidDataException("No properties supplied"); + } + + // store properties + try { + PropertyArrayList props = (PropertyArrayList) Gateway + .getMarshaller().unmarshall(propString); + for (Property thisProp : props.list) + mStorage.put(mItemPath, thisProp, locker); + } catch (Throwable ex) { + Logger.msg(8, "TraceableEntity::initialise(" + mItemPath + + ") - Properties were invalid: " + propString); + Logger.error(ex); + mStorage.abort(locker); + throw new InvalidDataException("Properties were invalid"); + } + + // Store an event and the initial properties + try { + Outcome initOutcome = new Outcome(0, propString, "ItemInitialization", 0); + History hist = new History(mItemPath, locker); + Transition predefDone = new Transition(0, "Done", 0, 0); + Event newEvent = hist.addEvent(new AgentPath(agentId), "", "Initialize", "", "", initOutcome.getSchemaType(), 0, "PredefinedStep", 0, predefDone, "last"); + initOutcome.setID(newEvent.getID()); + Viewpoint newLastView = new Viewpoint(mItemPath, initOutcome.getSchemaType(), "last", 0, newEvent.getID()); + Gateway.getStorage().put(mItemPath, initOutcome, locker); + Gateway.getStorage().put(mItemPath, newLastView, locker); + } catch (Throwable ex) { + Logger.msg(8, "TraceableEntity::initialise(" + mItemPath + + ") - Could not store event and outcome."); + Logger.error(ex); + mStorage.abort(locker); + throw new PersistencyException("Error storing event and outcome"); + } + + // create wf + try { + Workflow lc = null; + if (initWfString == null || initWfString.length() == 0) + lc = new Workflow(new CompositeActivity(), getNewPredefStepContainer()); + else + lc = new Workflow((CompositeActivity) Gateway + .getMarshaller().unmarshall(initWfString), getNewPredefStepContainer()); + lc.initialise(mItemPath, agentPath); + mStorage.put(mItemPath, lc, locker); + } catch (Throwable ex) { + Logger.msg(8, "TraceableEntity::initialise(" + mItemPath + + ") - Workflow was invalid: " + initWfString); + Logger.error(ex); + mStorage.abort(locker); + throw new InvalidDataException("Workflow was invalid"); + } + + // init collections + if (initCollsString != null && initCollsString.length() > 0) { + try { + CollectionArrayList colls = (CollectionArrayList) Gateway + .getMarshaller().unmarshall(initCollsString); + for (Collection thisColl : colls.list) { + mStorage.put(mItemPath, thisColl, locker); + } + } catch (Throwable ex) { + Logger.msg(8, "TraceableEntity::initialise(" + mItemPath + + ") - Collections were invalid: " + + initCollsString); + Logger.error(ex); + mStorage.abort(locker); + throw new InvalidDataException("Collections were invalid"); + } + } + + mStorage.commit(locker); + Logger.msg(3, "Initialisation of item " + mItemPath + + " was successful"); + } + + + protected PredefinedStepContainer getNewPredefStepContainer() { + + return new ItemPredefinedStepContainer(); + } + + @Override + public String requestAction(SystemKey agentId, String stepPath, int transitionID, + String requestData) throws AccessRightsException, + InvalidTransitionException, ObjectNotFoundException, + InvalidDataException, PersistencyException, + ObjectAlreadyExistsException, InvalidCollectionModification { + + try { + + AgentPath agent = new AgentPath(agentId); + Logger.msg(1, "TraceableEntity::request(" + mItemPath + ") - Transition " + + transitionID + " on " + stepPath + " by " + agent); + + + Workflow lifeCycle = (Workflow) mStorage.get(mItemPath, + ClusterStorage.LIFECYCLE + "/workflow", null); + + String finalOutcome = lifeCycle.requestAction(agent, stepPath, mItemPath, + transitionID, requestData); + + // store the workflow if we've changed the state of the domain + // wf + if (!(stepPath.startsWith("workflow/predefined"))) + mStorage.put(mItemPath, lifeCycle, null); + + return finalOutcome; + // Normal operation exceptions + } catch (AccessRightsException ex) { + Logger.msg("Propagating AccessRightsException back to the calling agent"); + throw ex; + } catch (InvalidTransitionException ex) { + Logger.msg("Propagating InvalidTransitionException back to the calling agent"); + throw ex; + } catch (ObjectNotFoundException ex) { + Logger.msg("Propagating ObjectNotFoundException back to the calling agent"); + throw ex; + // errors + } catch (InvalidItemPathException ex) { + Logger.error(ex); + throw new AccessRightsException("Invalid Agent Id: " + agentId); + } catch (InvalidDataException ex) { + Logger.error(ex); + Logger.msg("Propagating InvalidDataException back to the calling agent"); + throw ex; + } catch (ObjectAlreadyExistsException ex) { + Logger.error(ex); + Logger.msg("Propagating ObjectAlreadyExistsException back to the calling agent"); + throw ex; + } catch (InvalidCollectionModification ex) { + Logger.error(ex); + Logger.msg("Propagating InvalidCollectionModification back to the calling agent"); + throw ex; + } catch (Throwable ex) { // non-CORBA exception hasn't been caught! + Logger.error("Unknown Error: requestAction on " + mItemPath + + " by " + agentId + " executing " + stepPath); + Logger.error(ex); + throw new InvalidDataException( + "Extraordinary Exception during execution:" + + ex.getClass().getName() + " - " + + ex.getMessage()); + } + } + + @Override + public String queryLifeCycle(SystemKey agentId, boolean filter) + throws AccessRightsException, ObjectNotFoundException, + PersistencyException { + Logger.msg(1, "TraceableEntity::queryLifeCycle(" + mItemPath + + ") - agent: " + agentId); + try { + AgentPath agent; + try { + agent = new AgentPath(agentId); + } catch (InvalidItemPathException e) { + throw new AccessRightsException("Agent " + agentId + + " doesn't exist"); + } + Workflow wf; + wf = (Workflow) mStorage.get(mItemPath, + ClusterStorage.LIFECYCLE + "/workflow", null); + JobArrayList jobBag = new JobArrayList(); + CompositeActivity domainWf = (CompositeActivity) wf + .search("workflow/domain"); + jobBag.list = filter ? + domainWf.calculateJobs(agent, mItemPath, true) : + domainWf.calculateAllJobs(agent, mItemPath, true); + Logger.msg(1, "TraceableEntity::queryLifeCycle(" + mItemPath + + ") - Returning " + jobBag.list.size() + " jobs."); + try { + return Gateway.getMarshaller().marshall(jobBag); + } catch (Exception e) { + Logger.error(e); + throw new PersistencyException("Error marshalling job bag"); + } + } catch (Throwable ex) { + Logger.error("TraceableEntity::queryLifeCycle(" + mItemPath + + ") - Unknown error"); + Logger.error(ex); + throw new PersistencyException( + "Unknown error querying jobs. Please see server log."); + } + } + + @Override + public String queryData(String path) throws AccessRightsException, + ObjectNotFoundException, PersistencyException { + + String result = ""; + + Logger.msg(1, "TraceableEntity::queryData(" + mItemPath + ") - " + + path); + + try { // check for cluster contents query + + if (path.endsWith("/all")) { + int allPos = path.lastIndexOf("all"); + String query = path.substring(0, allPos); + String[] ids = mStorage.getClusterContents(mItemPath, query); + + for (int i = 0; i < ids.length; i++) { + result += ids[i]; + + if (i != ids.length - 1) + result += ","; + } + } + // **************************************************************** + else { // retrieve the object instead + C2KLocalObject obj = mStorage.get(mItemPath, path, null); + + // marshall it, or in the case of an outcome get the data. + result = Gateway.getMarshaller().marshall(obj); + } + } catch (ObjectNotFoundException ex) { + throw ex; + } catch (Throwable ex) { + Logger.warning("TraceableEntity::queryData(" + mItemPath + + ") - " + path + " Failed: " + ex.getClass().getName()); + throw new PersistencyException("Server exception: " + + ex.getClass().getName()); + } + + if (Logger.doLog(9)) + Logger.msg(9, "TraceableEntity::queryData(" + mItemPath + + ") - result:" + result); + + return result; + } + + /** + * + */ + @Override + protected void finalize() throws Throwable { + Logger.msg(7, "Item "+mItemPath+" reaped"); + Gateway.getStorage().clearCache(mItemPath, null); + super.finalize(); + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/TraceableEntity.java b/src/main/java/org/cristalise/kernel/entity/TraceableEntity.java new file mode 100644 index 0000000..7b43873 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/TraceableEntity.java @@ -0,0 +1,154 @@ +/** + * 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.entity; + + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.entity.ItemPOA; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** +* TraceableEntity is the implementation of the CORBA Item, although it +* delegates all non-CORBA functions to ItemImplementation. +* +* Traditional Pinky/Brain ASCII art: +* +*
+*                                ,.   '\'\    ,---.
+*                            .  | \\  l\\l_ //    |
+*        _              _       |  \\/ `/  `.|    |
+*      /~\\   \        //~\     | Y |   |   ||  Y |
+*      |  \\   \      //  |     |  \|   |   |\ /  |
+*      [   ||        ||   ]     \   |  o|o  | >  /
+*     ] Y  ||        ||  Y [     \___\_--_ /_/__/
+*     |  \_|l,------.l|_/  |     /.-\(____) /--.\
+*     |   >'          `<   |     `--(______)----'
+*     \  (/~`--____--'~\)  /         u// u / \
+*      `-_>-__________-<_-'          / \  / /|
+*          /(_#(__)#_)\             ( .) / / ]
+*          \___/__\___/              `.`' /   [
+*           /__`--'__\                |`-'    |
+*        /\(__,>-~~ __)               |       |_
+*     /\//\\(  `--~~ )               _l       |-:.
+*     '\/  <^\      /^>             |  `   (  <  \\
+*          _\ >-__-< /_           ,-\  ,-~~->. \  `:._,/
+*        (___\    /___)         (____/    (____)   `-'
+*             Kovax            and, paradoxically, Kovax
+* 
+***************************************************************************/ + +public class TraceableEntity extends ItemPOA +{ + + private final org.omg.PortableServer.POA mPoa; + private final ItemImplementation mItemImpl; + + public TraceableEntity( ItemPath key, + org.omg.PortableServer.POA poa ) + { + Logger.msg(5,"TraceableEntity::constructor() - SystemKey:" + key ); + mPoa = poa; + mItemImpl = new ItemImplementation(key); + } + + + @Override + public org.omg.PortableServer.POA _default_POA() + { + if(mPoa != null) + return mPoa; + else + return super._default_POA(); + } + + + @Override + public SystemKey getSystemKey() + { + return mItemImpl.getSystemKey(); + } + + @Override + public void initialise( SystemKey agentId, + String propString, + String initWfString, + String initCollsString + ) + throws AccessRightsException, + InvalidDataException, + PersistencyException + { + synchronized (this) { + mItemImpl.initialise(agentId, propString, initWfString, initCollsString); + } + } + + @Override + public String requestAction( SystemKey agentId, + String stepPath, + int transitionID, + String requestData + ) + throws AccessRightsException, + InvalidTransitionException, + ObjectNotFoundException, + InvalidDataException, + PersistencyException, + ObjectAlreadyExistsException, InvalidCollectionModification + { + synchronized (this) { + return mItemImpl.requestAction(agentId, stepPath, transitionID, requestData); + } + } + + @Override + public String queryLifeCycle( SystemKey agentId, + boolean filter + ) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException + { + synchronized (this) { + return mItemImpl.queryLifeCycle(agentId, filter); + } + } + + @Override + public String queryData(String path) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException + { + synchronized (this) { + return mItemImpl.queryData(path); + } + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/TraceableLocator.java b/src/main/java/org/cristalise/kernel/entity/TraceableLocator.java new file mode 100644 index 0000000..f61c433 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/TraceableLocator.java @@ -0,0 +1,90 @@ +/** + * 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.entity; + + +import java.nio.ByteBuffer; +import java.sql.Timestamp; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2005/10/05 07:39:37 $ + * @version $Revision: 1.15 $ + **************************************************************************/ +public class TraceableLocator extends org.omg.PortableServer.ServantLocatorPOA +{ + + /************************************************************************** + * + **************************************************************************/ + public TraceableLocator() + { + } + + + /************************************************************************** + * + **************************************************************************/ + @Override + public org.omg.PortableServer.Servant preinvoke( + byte[] oid, + org.omg.PortableServer.POA poa, + String operation, + org.omg.PortableServer.ServantLocatorPackage.CookieHolder cookie ) + { + ByteBuffer bb = ByteBuffer.wrap(oid); + long msb = bb.getLong(); + long lsb = bb.getLong(); + ItemPath syskey = new ItemPath(new SystemKey(msb, lsb)); + + Logger.msg(1,"==========================================================="); + Logger.msg(1,"Item called at "+new Timestamp( System.currentTimeMillis()) +": " + operation + + "(" + syskey + ")." ); + + try { + return Gateway.getCorbaServer().getItem(syskey); + } catch (ObjectNotFoundException ex) { + Logger.error("ObjectNotFoundException::TraceableLocator::preinvoke() " + ex.toString()); + throw new org.omg.CORBA.OBJECT_NOT_EXIST(); + } + } + + + /************************************************************************** + * + **************************************************************************/ + @Override + public void postinvoke( + byte[] oid, + org.omg.PortableServer.POA poa, + String operation, + java.lang.Object the_cookie, + org.omg.PortableServer.Servant the_servant ) + { } +} diff --git a/src/main/java/org/cristalise/kernel/entity/agent/ActiveEntity.java b/src/main/java/org/cristalise/kernel/entity/agent/ActiveEntity.java new file mode 100644 index 0000000..46d60ac --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/ActiveEntity.java @@ -0,0 +1,156 @@ +/** + * 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.entity.agent; + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.entity.AgentPOA; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * ActiveEntity - the CORBA object representing the Agent. All functionality + * is delegated to the AgentImplementation, which extends ItemImplementation, + * as this cannot extend its equivalent TraceableEntity + * + **************************************************************************/ +public class ActiveEntity extends AgentPOA +{ + + private final org.omg.PortableServer.POA mPoa; + private final AgentImplementation mAgentImpl; + + public ActiveEntity( AgentPath key, + org.omg.PortableServer.POA poa ) + { + Logger.msg(5, "ActiveEntity::constructor() - SystemKey:" + key ); + mPoa = poa; + mAgentImpl = new AgentImplementation(key); + } + + + /************************************************************************** + * + * + **************************************************************************/ + @Override + public org.omg.PortableServer.POA _default_POA() + { + if(mPoa != null) + return mPoa; + else + return super._default_POA(); + } + + + /************************************************************************** + * + * + **************************************************************************/ + @Override + public SystemKey getSystemKey() + { + return mAgentImpl.getSystemKey(); + } + + + /************************************************************************** + * + * + **************************************************************************/ + @Override + public String queryData(String path) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException + { + synchronized (this) { + return mAgentImpl.queryData(path); + } + } + + + + /** + * Called by an activity when it reckons we need to update our joblist for it + */ + + @Override + public void refreshJobList(SystemKey sysKey, String stepPath, String newJobs) { + synchronized (this) { + mAgentImpl.refreshJobList(sysKey, stepPath, newJobs); + } + } + + @Override + public void addRole(String roleName) throws CannotManageException, ObjectNotFoundException { + synchronized (this) { + mAgentImpl.addRole(roleName); + } + } + + @Override + public void removeRole(String roleName) throws CannotManageException, ObjectNotFoundException { + synchronized (this) { + mAgentImpl.removeRole(roleName); + } + } + + @Override + public void initialise(SystemKey agentId, String propString, String initWfString, + String initCollsString) throws AccessRightsException, + InvalidDataException, PersistencyException, ObjectNotFoundException { + synchronized (this) { + mAgentImpl.initialise(agentId, propString, initWfString, initCollsString); + } + + } + + @Override + public String requestAction(SystemKey agentID, String stepPath, int transitionID, + String requestData) throws AccessRightsException, + InvalidTransitionException, ObjectNotFoundException, + InvalidDataException, PersistencyException, + ObjectAlreadyExistsException, InvalidCollectionModification { + + synchronized (this) { + return mAgentImpl.requestAction(agentID, stepPath, transitionID, requestData); + } + + } + + @Override + public String queryLifeCycle(SystemKey agentId, boolean filter) + throws AccessRightsException, ObjectNotFoundException, + PersistencyException { + synchronized (this) { + return mAgentImpl.queryLifeCycle(agentId, filter); + } + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/agent/ActiveLocator.java b/src/main/java/org/cristalise/kernel/entity/agent/ActiveLocator.java new file mode 100644 index 0000000..1a55c99 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/ActiveLocator.java @@ -0,0 +1,100 @@ +/** + * 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.entity.agent; + + +import java.nio.ByteBuffer; +import java.sql.Timestamp; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + + +/************************************************************************** + * + * @author $Author: abranson $ $Date: 2005/10/05 07:39:36 $ + * @version $Revision: 1.9 $ + **************************************************************************/ +public class ActiveLocator extends org.omg.PortableServer.ServantLocatorPOA +{ + + /************************************************************************** + * + **************************************************************************/ + public ActiveLocator() + { + } + + + /************************************************************************** + * + **************************************************************************/ + @Override + public org.omg.PortableServer.Servant preinvoke( + byte[] oid, + org.omg.PortableServer.POA poa, + String operation, + org.omg.PortableServer.ServantLocatorPackage.CookieHolder cookie ) + { + + try + { + ByteBuffer bb = ByteBuffer.wrap(oid); + long msb = bb.getLong(); + long lsb = bb.getLong(); + AgentPath syskey = new AgentPath(new SystemKey(msb, lsb)); + + Logger.msg(1,"==========================================================="); + Logger.msg(1,"Agent called at "+new Timestamp( System.currentTimeMillis()) +": " + operation + + "(" + syskey + ")." ); + + return Gateway.getCorbaServer().getAgent(syskey); + + } + catch (ObjectNotFoundException ex) + { + Logger.error("ObjectNotFoundException::ActiveLocator::preinvoke() "+ex.toString()); + throw new org.omg.CORBA.OBJECT_NOT_EXIST(); + } catch (InvalidItemPathException ex) { + Logger.error("InvalidItemPathException::ActiveLocator::preinvoke() "+ex.toString()); + throw new org.omg.CORBA.INV_OBJREF(); + } + } + + + /************************************************************************** + * + **************************************************************************/ + @Override + public void postinvoke( + byte[] oid, + org.omg.PortableServer.POA poa, + String operation, + java.lang.Object the_cookie, + org.omg.PortableServer.Servant the_servant ) + { + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/agent/AgentImplementation.java b/src/main/java/org/cristalise/kernel/entity/agent/AgentImplementation.java new file mode 100644 index 0000000..26c2f2f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/AgentImplementation.java @@ -0,0 +1,137 @@ +/** + * 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.entity.agent; + +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.SystemKey; +import org.cristalise.kernel.entity.AgentOperations; +import org.cristalise.kernel.entity.ItemImplementation; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStepContainer; +import org.cristalise.kernel.lifecycle.instance.predefined.agent.AgentPredefinedStepContainer; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; + + +/** + * Implementation of Agent, though called from the CORBA implementation ActiveEntity. + * + *

The Agent is an extension of the Item that can execute Jobs, and in doing so + * change the state of Item workflows, submit data to them in the form of Outcomes + * and run any scripts associated with those activities. In this server object, + * none of this specific Agent work is performed - it all must be done using the + * client API. The server implementation only manages the Agent's data: its roles + * and persistent Jobs. + */ +public class AgentImplementation extends ItemImplementation implements + AgentOperations { + + private JobList currentJobs; + private final AgentPath mAgentPath; + + public AgentImplementation(AgentPath path) { + super(path); + mAgentPath = path; + } + + + /** + * Updates an Agent's list of Jobs relating to a particular activity. Only + * Activities that are assigned to a Role that is flagged to push Jobs do this. + * + */ + @Override + public synchronized void refreshJobList(SystemKey sysKey, String stepPath, String newJobs) { + try { + ItemPath itemPath = new ItemPath(sysKey); + JobArrayList newJobList = (JobArrayList)Gateway.getMarshaller().unmarshall(newJobs); + + // get our joblist + if (currentJobs == null) + currentJobs = new JobList( itemPath, null); + + // remove old jobs for this item + currentJobs.removeJobsForStep( itemPath, stepPath ); + + // merge new jobs in + for (Object name : newJobList.list) { + Job newJob = (Job)name; + Logger.msg(6, "Adding job for "+newJob.getItemPath()+"/"+newJob.getStepPath()+":"+newJob.getTransition().getId()); + currentJobs.addJob(newJob); + } + + } catch (Throwable ex) { + Logger.error("Could not refresh job list."); + Logger.error(ex); + } + + } + + /** Adds the given Role to this Agent. Called from the SetAgentRoles + * predefined step. + * + * @param roleName - the new Role to add + * @throws CannotManageException When the process has no lookup manager + * @throws ObjectNotFoundException + * + */ + @Override + public void addRole(String roleName) throws CannotManageException, ObjectNotFoundException { + RolePath newRole = Gateway.getLookup().getRolePath(roleName); + try { + Gateway.getLookupManager().addRole(mAgentPath, newRole); + } catch (ObjectCannotBeUpdated ex) { + throw new CannotManageException("Could not update role"); + } + } + + /** + * Removes the given Role from this Agent. Called by the SetAgentRoles + * predefined step. + * + * @param roleName + */ + @Override + public void removeRole(String roleName) throws CannotManageException, ObjectNotFoundException { + RolePath rolePath = Gateway.getLookup().getRolePath(roleName); + try { + Gateway.getLookupManager().removeRole(mAgentPath, rolePath); + } catch (ObjectCannotBeUpdated ex) { + throw new CannotManageException("Could not update role"); + } + } + + /** + * Agents have their own predefined step containers. They contain the standard + * predefined steps, plus special Agent ones related to Agent management and + * instantiation. + * + * @see org.cristalise.kernel.lifecycle.instance.predefined.agent.AgentPredefinedStepContainer + */ + @Override + protected PredefinedStepContainer getNewPredefStepContainer() { + return new AgentPredefinedStepContainer(); + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/agent/Job.java b/src/main/java/org/cristalise/kernel/entity/agent/Job.java new file mode 100644 index 0000000..bd74d51 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/Job.java @@ -0,0 +1,484 @@ +/** + * 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.entity.agent; + +import java.util.HashMap; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.proxy.ItemProxy; +import org.cristalise.kernel.lifecycle.instance.Activity; +import org.cristalise.kernel.lifecycle.instance.stateMachine.Transition; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.InvalidAgentPathException; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.OutcomeInitiator; +import org.cristalise.kernel.persistency.outcome.Schema; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.scripting.ErrorInfo; +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.KeyValuePair; +import org.cristalise.kernel.utils.Logger; + + +/******************************************************************************* + * @author $Author: abranson $ $Date: 2005/05/20 13:07:49 $ + * @version $Revision: 1.62 $ + ******************************************************************************/ + +public class Job implements C2KLocalObject +{ + // persistent + + private int id; + + private ItemPath itemPath; + + private String stepName; + + private String stepPath; + + private String stepType; + + private Transition transition; + + private String originStateName; + + private String targetStateName; + + private String agentRole; + + private CastorHashMap actProps = new CastorHashMap(); + + // non-persistent + + private String name; + + private AgentPath agentPath; + + private String agentName; + + private String outcomeData; + + private ErrorInfo error; + + private ItemProxy item = null; + + private boolean outcomeSet; + + // outcome initiator cache + + static private HashMap ocInitCache = new HashMap(); + + /*************************************************************************** + * Empty constructor for Castor + **************************************************************************/ + public Job() + { + } + + public Job(Activity act, ItemPath itemPath, Transition transition, AgentPath agent, String role) throws InvalidDataException, ObjectNotFoundException, InvalidAgentPathException { + + setItemPath(itemPath); + setStepPath(act.getPath()); + setTransition(transition); + setOriginStateName(act.getStateMachine().getState(transition.getOriginStateId()).getName()); + setTargetStateName(act.getStateMachine().getState(transition.getTargetStateId()).getName()); + setStepName(act.getName()); + setActProps(act.getProperties()); + setStepType(act.getType()); + if (agent != null) setAgentName(agent.getAgentName()); + setAgentRole(role); + } + + + // Castor persistent fields + + public String getOriginStateName() { + return originStateName; + } + + public void setOriginStateName(String originStateName) { + this.originStateName = originStateName; + } + + public String getTargetStateName() { + return targetStateName; + } + + public void setTargetStateName(String targetStateName) { + this.targetStateName = targetStateName; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + name = String.valueOf(id); + } + + public ItemPath getItemPath() { + return itemPath; + } + + public void setItemPath(ItemPath path) { + itemPath = path; + item = null; + } + + public void setItemUUID( String uuid ) throws InvalidItemPathException + { + setItemPath(new ItemPath(uuid)); + } + + public String getItemUUID() { + return getItemPath().getUUID().toString(); + } + + public String getStepName() { + return stepName; + } + + public void setStepName(String string) { + stepName = string; + } + + public String getStepPath() { + return stepPath; + } + + public void setStepPath(String string) { + stepPath = string; + } + + public String getStepType() { + return stepType; + } + + public void setStepType(String actType) { + stepType = actType; + } + + public Transition getTransition() { + return transition; + } + + public void setTransition(Transition transition) { + this.transition = transition; + } + + public AgentPath getAgentPath() throws ObjectNotFoundException { + if (agentPath == null && getAgentName() != null) { + agentPath = Gateway.getLookup().getAgentPath(getAgentName()); + } + return agentPath; + } + + public void setAgentPath(AgentPath agentPath) { + this.agentPath = agentPath; + agentName = agentPath.getAgentName(); + } + + public void setAgentUUID( String uuid ) + { + if (uuid != null) + try { + setAgentPath(AgentPath.fromUUIDString(uuid)); + } catch (InvalidAgentPathException e) { + Logger.error("Invalid agent path in Job: "+uuid); + } + } + + public String getAgentUUID() { + try { + if (getAgentPath() != null) + return getAgentPath().getUUID().toString(); + } catch (ObjectNotFoundException e) { } + return null; + } + + public String getAgentName() + { + if (agentName == null) + agentName = (String) actProps.get("Agent Name"); + return agentName; + } + + public void setAgentName(String agentName) throws ObjectNotFoundException + { + this.agentName = agentName; + agentPath = Gateway.getLookup().getAgentPath(agentName); + } + + public String getAgentRole() { + return agentRole; + } + + public void setAgentRole(String role) { + agentRole = role; + } + + public String getSchemaName() throws InvalidDataException, ObjectNotFoundException { + if (transition.hasOutcome(actProps)) { + Schema schema = transition.getSchema(actProps); + return schema.docType; + } + return null; + } + + public int getSchemaVersion() throws InvalidDataException, ObjectNotFoundException { + if (transition.hasOutcome(actProps)) { + Schema schema = transition.getSchema(actProps); + return schema.docVersion; + } + return -1; + } + + public boolean isOutcomeRequired() + { + return transition.hasOutcome(actProps) && transition.getOutcome().isRequired(); + } + + public String getScriptName() { + if (transition.hasScript(actProps)) { + return transition.getScript().getScriptName(); + } + return null; + } + + public int getScriptVersion() throws InvalidDataException { + if (transition.hasScript(actProps)) { + return transition.getScriptVersion(actProps); + } + return -1; + } + + public KeyValuePair[] getKeyValuePairs() { + return actProps.getKeyValuePairs(); + } + + public void setKeyValuePairs(KeyValuePair[] pairs) { + actProps.setKeyValuePairs(pairs); + } + + // Non-persistent fields + + @Override + public String getName() { + return name; + } + + @Override + public void setName(String name) { + this.name = name; + try { + id = Integer.parseInt(name); + } catch (NumberFormatException ex) { + id = -1; + } + } + + public ItemProxy getItemProxy() throws ObjectNotFoundException, InvalidItemPathException { + if (item == null) + item = Gateway.getProxyManager().getProxy(itemPath); + return item; + } + + public String getDescription() + { + String desc = (String) actProps.get("Description"); + if (desc == null) + desc = "No Description"; + return desc; + } + public void setOutcome(String outcome) + { + outcomeData = outcome; + outcomeSet = !(outcomeData == null); + } + + public void setError(ErrorInfo errors) + { + error = errors; + try { + outcomeData = Gateway.getMarshaller().marshall(error); + } catch (Exception e) { + Logger.error("Error marshalling ErrorInfo in job"); + Logger.error(e); + } + } + + public String getLastView() throws InvalidDataException { + String viewName = (String) getActProp("Viewpoint"); + if (viewName.length() > 0) { + // find schema + String schemaName; + try { + schemaName = getSchemaName(); + } catch (ObjectNotFoundException e1) { + throw new InvalidDataException("Schema "+getActProp("SchemaType")+" v"+getActProp("SchemaVersion")+" not found"); + } + + try { + Viewpoint view = (Viewpoint) Gateway.getStorage().get(itemPath, + ClusterStorage.VIEWPOINT + "/" + schemaName + "/" + viewName, null); + return view.getOutcome().getData(); + } catch (ObjectNotFoundException ex) { // viewpoint doesn't exist yet + return null; + } catch (PersistencyException e) { + Logger.error(e); + throw new InvalidDataException("ViewpointOutcomeInitiator: PersistencyException loading viewpoint " + + ClusterStorage.VIEWPOINT + "/" + schemaName + "/" + viewName+" in item "+itemPath.getUUID()); + } + } + else + return null; + } + + public OutcomeInitiator getOutcomeInitiator() throws InvalidDataException { + String ocInitName = (String) getActProp("OutcomeInit"); + OutcomeInitiator ocInit; + if (ocInitName.length() > 0) { + String ocPropName = "OutcomeInit."+ocInitName; + synchronized (ocInitCache) { + ocInit = ocInitCache.get(ocPropName); + if (ocInit == null) { + Object ocInitObj; + if (!Gateway.getProperties().containsKey(ocPropName)) { + throw new InvalidDataException("Outcome instantiator "+ocPropName+" isn't defined"); + } + try { + ocInitObj = Gateway.getProperties().getInstance(ocPropName); + } catch (Exception e) { + Logger.error(e); + throw new InvalidDataException("Outcome instantiator "+ocPropName+" couldn't be instantiated"); + } + ocInit = (OutcomeInitiator)ocInitObj; // throw runtime class cast if it isn't one + ocInitCache.put(ocPropName, ocInit); + } + } + return ocInit; + } + else + return null; + } + + public String getOutcomeString() throws InvalidDataException + { + if (outcomeData == null && transition.hasOutcome(actProps)) { + outcomeData = getLastView(); + if (outcomeData == null) { + OutcomeInitiator ocInit = getOutcomeInitiator(); + if (ocInit != null) + outcomeData = ocInit.initOutcome(this); + } + if (outcomeData != null) outcomeSet = true; + } + return outcomeData; + } + + public Outcome getOutcome() throws InvalidDataException, ObjectNotFoundException + { + return new Outcome(-1, getOutcomeString(), getSchemaName(), getSchemaVersion()); + } + + public boolean hasOutcome() { + return transition.hasOutcome(actProps); + } + + public boolean hasScript() { + return transition.hasScript(actProps); + } + + public boolean isOutcomeSet() { + return outcomeSet; + } + + @Override + public String getClusterType() + { + return ClusterStorage.JOB; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + + ((itemPath == null) ? 0 : itemPath.hashCode()); + result = prime * result + + ((stepPath == null) ? 0 : stepPath.hashCode()); + result = prime * result + + ((transition == null) ? 0 : transition.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + Job other = (Job) obj; + if (itemPath == null) { + if (other.itemPath != null) + return false; + } else if (!itemPath.equals(other.itemPath)) + return false; + if (stepPath == null) { + if (other.stepPath != null) + return false; + } else if (!stepPath.equals(other.stepPath)) + return false; + if (transition == null) { + if (other.transition != null) + return false; + } else if (!transition.equals(other.transition)) + return false; + return true; + } + + + private void setActProps(CastorHashMap actProps) { + this.actProps = actProps; + } + + public Object getActProp(String name) + { + return actProps.get(name); + } + + public String getActPropString(String name) + { + Object obj = getActProp(name); + return obj==null?null:String.valueOf(obj); + } +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/agent/JobArrayList.java b/src/main/java/org/cristalise/kernel/entity/agent/JobArrayList.java new file mode 100644 index 0000000..f4233fb --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/JobArrayList.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.entity.agent; + +import java.util.ArrayList; + +import org.cristalise.kernel.utils.CastorArrayList; + + +public class JobArrayList extends CastorArrayList +{ + + public JobArrayList() + { + super(); + } + + public JobArrayList(ArrayList aList) + { + super(aList); + } + + +} diff --git a/src/main/java/org/cristalise/kernel/entity/agent/JobList.java b/src/main/java/org/cristalise/kernel/entity/agent/JobList.java new file mode 100644 index 0000000..b4e2a27 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/JobList.java @@ -0,0 +1,138 @@ +/** + * 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.entity.agent; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.Vector; + +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.RemoteMap; +import org.cristalise.kernel.utils.Logger; + + + +/************************************************************************** +* +* @author $Author: abranson $ $Date: 2006/03/03 13:52:21 $ +* @version $Revision: 1.15 $ +***************************************************************************/ +public class JobList extends RemoteMap +{ + + /************************************************************************** + * Empty constructor for Castor + **************************************************************************/ + public JobList(ItemPath itemPath, Object locker) + { + super(itemPath, ClusterStorage.JOB, locker); + } + + + /************************************************************************** + * + **************************************************************************/ + public void addJob( Job job ) + { + synchronized(this) { + int jobId = getLastId()+1; + job.setId(jobId); + put(String.valueOf(jobId), job); + } + } + + /** + * Cannot be stored + */ + @Override + public String getClusterType() { + return null; + } + + + public Job getJob(int id) { + return get(String.valueOf(id)); + } + + + /** + * @param job + */ + public void removeJobsForItem( ItemPath itemPath ) + { + Iterator currentMembers = values().iterator(); + Job j = null; + + while( currentMembers.hasNext() ) + { + j = currentMembers.next(); + + if( j.getItemPath().equals(itemPath) ) + remove( String.valueOf(j.getId()) ); + } + + Logger.msg(5, "JobList::removeJobsWithSysKey() - " + itemPath + " DONE." ); + } + + public void removeJobsForStep( ItemPath itemPath, String stepPath ) + { + ArrayList staleJobs = new ArrayList(); + Iterator jobIter = keySet().iterator(); + while( jobIter.hasNext() ) + { + String jid = jobIter.next(); + Job j = get(jid); + if( j.getItemPath().equals(itemPath) && j.getStepPath().equals(stepPath)) + staleJobs.add(jid); + } + + Logger.msg(3, "JobList.removeJobsForStep() - removing "+staleJobs.size()); + + for (String jid : staleJobs) { + remove(jid); + } + Logger.msg(5, "JobList::removeJobsForStep() - " + itemPath + " DONE." ); + } + /** + * @param itemKey + * @param string + * @return + */ + public Vector getJobsOfItem( ItemPath itemPath ) + { + Iterator currentMembers = values().iterator(); + Job j = null; + Vector jobs = new Vector(); + + while( currentMembers.hasNext() ) + { + j = currentMembers.next(); + + if( j.getItemPath().equals(itemPath) ) + jobs.add(j); + } + + Logger.msg(5, "JobList::getJobsOfSysKey() - returning " + jobs.size() + " Jobs." ); + + return jobs; + } +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/agent/package-info.java b/src/main/java/org/cristalise/kernel/entity/agent/package-info.java new file mode 100644 index 0000000..f5e146b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/agent/package-info.java @@ -0,0 +1,32 @@ +/** + * 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 + */ +/** + * The implementation of Agents, and their Jobs. + * + *

This package contains the classes for the implementation of + * Agents on the CRISTAL server. They correspond to the Item implementations in + * the parent package. + *

This package also contains the {@link Job} object implementation, as well + * as the RemoteMap JobList, and the marshallable container JobArrayList. + * + */ + +package org.cristalise.kernel.entity.agent; \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/imports/Geometry.java b/src/main/java/org/cristalise/kernel/entity/imports/Geometry.java new file mode 100644 index 0000000..3680053 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/Geometry.java @@ -0,0 +1,48 @@ +/** + * 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.entity.imports; + + + +public class Geometry { + + + public int x; + + public int y; + + public int width; + + public int height; + + public Geometry() { + super(); + } + + public Geometry(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportAgent.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportAgent.java new file mode 100644 index 0000000..08c13d1 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportAgent.java @@ -0,0 +1,118 @@ +/** + * 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.entity.imports; + +import java.util.ArrayList; + +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.entity.agent.ActiveEntity; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.process.module.ModuleImport; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.utils.Logger; + + +public class ImportAgent extends ModuleImport { + + private String password; + private ArrayList properties = new ArrayList(); + private ArrayList roles = new ArrayList(); + + public ImportAgent() { + } + + public ImportAgent(String name, String password) { + this.name = name; + this.password = password; + } + + @Override + public void create(AgentPath agentPath, boolean reset) throws ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException, ObjectAlreadyExistsException { + AgentPath newAgent = new AgentPath(getItemPath(), name); + newAgent.setPassword(password); + ActiveEntity newAgentEnt = Gateway.getCorbaServer().createAgent(newAgent); + Gateway.getLookupManager().add(newAgent); + // assemble properties + properties.add(new Property("Name", name, true)); + properties.add(new Property("Type", "Agent", false)); + try { + newAgentEnt.initialise(agentPath.getSystemKey(), Gateway.getMarshaller().marshall(new PropertyArrayList(properties)), null, null); + } catch (Exception ex) { + Logger.error(ex); + throw new CannotManageException("Error initialising new agent"); + } + for (String role : roles) { + RolePath thisRole; + try { + thisRole = Gateway.getLookup().getRolePath(role); + } catch (ObjectNotFoundException ex) { + throw new ObjectNotFoundException("Role "+role+" does not exist."); + } + Gateway.getLookupManager().addRole(newAgent, thisRole); + } + + } + + @Override + public ItemPath getItemPath() { + if (itemPath == null) { // try to find agent if it already exists + try { + AgentPath existAgent = Gateway.getLookup().getAgentPath(name); + itemPath = existAgent; + } catch (ObjectNotFoundException ex) { + itemPath = new AgentPath(new ItemPath(), name); + } + } + return itemPath; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public ArrayList getRoles() { + return roles; + } + + public void setRoles(ArrayList roles) { + this.roles = roles; + } + + public ArrayList getProperties() { + return properties; + } + + public void setProperties(ArrayList properties) { + this.properties = properties; + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportAggregation.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportAggregation.java new file mode 100644 index 0000000..22a9b78 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportAggregation.java @@ -0,0 +1,91 @@ +/** + * 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.entity.imports; + +import java.util.ArrayList; + +import org.cristalise.kernel.collection.Aggregation; +import org.cristalise.kernel.collection.AggregationDescription; +import org.cristalise.kernel.collection.AggregationInstance; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.graph.model.GraphPoint; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.property.PropertyDescription; +import org.cristalise.kernel.property.PropertyDescriptionList; +import org.cristalise.kernel.property.PropertyUtility; + + +public class ImportAggregation { + + public boolean isDescription; + public Integer version; + public ArrayList aggregationMemberList = new ArrayList(); + public String name; + + public ImportAggregation() { + super(); + } + + public ImportAggregation(String name, boolean isDescription) { + this(); + this.name = name; + this.isDescription = isDescription; + } + + public org.cristalise.kernel.collection.Aggregation create() throws InvalidCollectionModification, ObjectNotFoundException, ObjectAlreadyExistsException { + Aggregation newAgg = isDescription?new AggregationDescription(name):new AggregationInstance(name); + if (version!= null) newAgg.setVersion(version); + for (ImportAggregationMember thisMem : aggregationMemberList) { + StringBuffer classProps = new StringBuffer(); + if (thisMem.itemDescriptionPath != null && thisMem.itemDescriptionPath.length()>0) { + ItemPath itemPath; + try { + itemPath = new ItemPath(thisMem.itemDescriptionPath); + } catch (InvalidItemPathException ex) { + itemPath = new DomainPath(thisMem.itemDescriptionPath).getItemPath(); + } + + String descVer = thisMem.itemDescriptionVersion==null?"last":thisMem.itemDescriptionVersion; + PropertyDescriptionList propList = PropertyUtility.getPropertyDescriptionOutcome(itemPath, descVer); + for (PropertyDescription pd : propList.list) { + thisMem.props.put(pd.getName(), pd.getDefaultValue()); + if (pd.getIsClassIdentifier()) + classProps.append((classProps.length()>0?",":"")).append(pd.getName()); + } + } + ItemPath itemPath = null; + if (thisMem.itemPath != null && thisMem.itemPath.length()>0) { + + try { + itemPath = new ItemPath(thisMem.itemPath); + } catch (InvalidItemPathException ex) { + itemPath = new DomainPath(thisMem.itemPath).getItemPath(); + } + } + newAgg.addMember(itemPath, thisMem.props, classProps.toString(), new GraphPoint(thisMem.geometry.x, thisMem.geometry.y), thisMem.geometry.width, thisMem.geometry.height); + } + return newAgg; + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportAggregationMember.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportAggregationMember.java new file mode 100644 index 0000000..53b74b8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportAggregationMember.java @@ -0,0 +1,55 @@ +/** + * 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.entity.imports; + +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.KeyValuePair; + +public class ImportAggregationMember { + + public int slotNo; + public String itemDescriptionPath; + public String itemDescriptionVersion = null; + public String itemPath; + public Geometry geometry; + public CastorHashMap props = new CastorHashMap(); + + + public ImportAggregationMember() { + super(); + } + + public ImportAggregationMember(int slotNo, String itemDescPath, String itemDescVersion, String itemPath, Geometry geometry) { + this.slotNo = slotNo; + this.itemDescriptionPath = itemDescPath; + this.itemDescriptionVersion = itemDescVersion; + this.itemPath = itemPath; + this.geometry = geometry; + } + + public KeyValuePair[] getKeyValuePairs() { + return props.getKeyValuePairs(); + } + + public void setKeyValuePairs(KeyValuePair[] pairs) { + props.setKeyValuePairs(pairs); + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportDependency.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportDependency.java new file mode 100644 index 0000000..f94cab0 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportDependency.java @@ -0,0 +1,107 @@ +/** + * 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.entity.imports; + +import java.util.ArrayList; + +import org.cristalise.kernel.collection.Dependency; +import org.cristalise.kernel.collection.DependencyDescription; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.property.PropertyDescription; +import org.cristalise.kernel.property.PropertyDescriptionList; +import org.cristalise.kernel.property.PropertyUtility; +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.KeyValuePair; + + +public class ImportDependency { + + public String name; + public Integer version; + public boolean isDescription; + public String itemDescriptionPath; + public String itemDescriptionVersion = null; + public ArrayList dependencyMemberList = new ArrayList(); + public CastorHashMap props = new CastorHashMap(); + + public ImportDependency() { + super(); + } + + public ImportDependency(String name) { + this(); + this.name = name; + } + + public KeyValuePair[] getKeyValuePairs() { + return props.getKeyValuePairs(); + } + + public void setKeyValuePairs(KeyValuePair[] pairs) { + props.setKeyValuePairs(pairs); + } + + /** + * @return + * @throws ObjectAlreadyExistsException + */ + public org.cristalise.kernel.collection.Dependency create() throws InvalidCollectionModification, ObjectNotFoundException, ObjectAlreadyExistsException { + Dependency newDep = isDescription?new DependencyDescription(name):new Dependency(name); + if (version!= null) newDep.setVersion(version); + if (itemDescriptionPath != null && itemDescriptionPath.length()>0) { + ItemPath itemPath; + try { + itemPath = new ItemPath(itemDescriptionPath); + } catch (InvalidItemPathException ex) { + itemPath = new DomainPath(itemDescriptionPath).getItemPath(); + } + String descVer = itemDescriptionVersion==null?"last":itemDescriptionVersion; + PropertyDescriptionList propList = PropertyUtility.getPropertyDescriptionOutcome(itemPath, descVer); + StringBuffer classProps = new StringBuffer(); + for (PropertyDescription pd : propList.list) { + props.put(pd.getName(), pd.getDefaultValue()); + if (pd.getIsClassIdentifier()) + classProps.append((classProps.length()>0?",":"")).append(pd.getName()); + } + newDep.setProperties(props); + newDep.setClassProps(classProps.toString()); + } + + for (ImportDependencyMember thisMem : dependencyMemberList) { + ItemPath itemPath; + try { + itemPath = new ItemPath(thisMem.itemPath); + } catch (InvalidItemPathException ex) { + itemPath = new DomainPath(thisMem.itemPath).getItemPath(); + } + + org.cristalise.kernel.collection.DependencyMember newDepMem = newDep.addMember(itemPath); + newDepMem.getProperties().putAll(thisMem.props); + } + return newDep; + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportDependencyMember.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportDependencyMember.java new file mode 100644 index 0000000..5a5d6cd --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportDependencyMember.java @@ -0,0 +1,48 @@ +/** + * 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.entity.imports; + +import org.cristalise.kernel.utils.CastorHashMap; +import org.cristalise.kernel.utils.KeyValuePair; + +public class ImportDependencyMember { + + + public String itemPath; + public CastorHashMap props = new CastorHashMap(); + + public ImportDependencyMember() { + super(); + } + + public ImportDependencyMember(String itemPath) { + this.itemPath = itemPath; + + } + + public KeyValuePair[] getKeyValuePairs() { + return props.getKeyValuePairs(); + } + + public void setKeyValuePairs(KeyValuePair[] pairs) { + props.setKeyValuePairs(pairs); + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportItem.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportItem.java new file mode 100644 index 0000000..2a259bd --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportItem.java @@ -0,0 +1,280 @@ +/** + * 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.entity.imports; + + +import java.util.ArrayList; + +import org.cristalise.kernel.collection.Aggregation; +import org.cristalise.kernel.collection.CollectionArrayList; +import org.cristalise.kernel.collection.Dependency; +import org.cristalise.kernel.common.CannotManageException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectCannotBeUpdated; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.TraceableEntity; +import org.cristalise.kernel.events.Event; +import org.cristalise.kernel.events.History; +import org.cristalise.kernel.lifecycle.CompositeActivityDef; +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.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.process.module.ModuleImport; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.utils.LocalObjectLoader; +import org.cristalise.kernel.utils.Logger; +import org.custommonkey.xmlunit.Diff; +import org.custommonkey.xmlunit.XMLUnit; + + +/** + * Complete Structure for new item + * + * @version $Revision: 1.8 $ $Date: 2006/03/03 13:52:21 $ + */ + +public class ImportItem extends ModuleImport { + + protected String initialPath; + protected String workflow; + protected Integer workflowVer; + protected ArrayList properties = new ArrayList(); + protected ArrayList aggregationList = new ArrayList(); + protected ArrayList dependencyList = new ArrayList(); + protected ArrayList outcomes = new ArrayList(); + + public ImportItem() { + } + + public ImportItem(String ns, String name, String initialPath, ItemPath itemPath, String wf, int wfVer) { + this(); + setNamespace(ns); + setName(name); + setItemPath(itemPath); + setInitialPath(initialPath); + setWorkflow(wf); + setWorkflowVer(wfVer); + } + + @Override + public ItemPath getItemPath() { + if (itemPath == null) { // try to find item if it already exists + DomainPath existingItem = new DomainPath(initialPath+"/"+name); + if (existingItem.exists()) { + try { + itemPath = existingItem.getItemPath(); + } catch (ObjectNotFoundException ex) { } + } + } + if (itemPath == null) itemPath = new ItemPath(); + return itemPath; + } + + @Override + public void setNamespace(String ns) { + super.setNamespace(ns); + if (initialPath == null) initialPath = "/desc/"+ns; + } + + @Override + public void setName(String name) { + super.setName(name); + } + + @Override + public void create(AgentPath agentPath, boolean reset) throws ObjectCannotBeUpdated, ObjectNotFoundException, CannotManageException, ObjectAlreadyExistsException, InvalidCollectionModification { + DomainPath domPath = new DomainPath(new DomainPath(initialPath), name); + if (domPath.exists()) { + ItemPath domItem = domPath.getItemPath(); + if (!getItemPath().equals(domItem)) + throw new CannotManageException("Item "+domPath+" was found with the wrong itemPath ("+domPath.getItemPath()+" vs "+getItemPath()+")"); + } + + TraceableEntity newItem; + if (getItemPath().exists()) { + Logger.msg(1, "ImportItem.create() - Verifying module item "+getItemPath()+" at "+domPath); + newItem = Gateway.getCorbaServer().getItem(getItemPath()); + } + else { + Logger.msg(1, "ImportItem.create() - Creating module item "+getItemPath()+" at "+domPath); + newItem = Gateway.getCorbaServer().createItem(getItemPath()); + Gateway.getLookupManager().add(getItemPath()); + } + + // set the name property + properties.add(new Property("Name", name, true)); + + // find workflow def + CompositeActivityDef compact; + // default workflow version is 0 if not given + int usedWfVer; + if (workflowVer == null) usedWfVer = 0; + else usedWfVer = workflowVer.intValue(); + try { + compact = (CompositeActivityDef)LocalObjectLoader.getActDef(workflow, usedWfVer); + } catch (ObjectNotFoundException ex) { + throw new CannotManageException("Could not find workflow "+workflow+"v"+usedWfVer+" for item "+domPath); + } catch (InvalidDataException e) { + throw new CannotManageException("Workflow def "+workflow+" v"+usedWfVer+" for item "+domPath+" was not valid"); + } + + // create collections + CollectionArrayList colls = new CollectionArrayList(); + for (ImportDependency element: dependencyList) { + Dependency newDep = element.create(); + colls.put(newDep); + } + + for (ImportAggregation element : aggregationList) { + Aggregation newAgg = element.create(); + colls.put(newAgg); + } + + // (re)initialise the new item with properties, workflow and collections + try { + newItem.initialise( + agentPath.getSystemKey(), + Gateway.getMarshaller().marshall(new PropertyArrayList(properties)), + Gateway.getMarshaller().marshall(compact.instantiate()), + Gateway.getMarshaller().marshall(colls)); + } catch (Exception ex) { + Logger.error("Error initialising new item "+name ); + Logger.error(ex); + throw new CannotManageException("Problem initialising new item. See server log."); + } + + // import outcomes + XMLUnit.setIgnoreWhitespace(true); + XMLUnit.setIgnoreComments(true); + History hist = new History(getItemPath(), null); + for (ImportOutcome thisOutcome : outcomes) { + Outcome newOutcome = new Outcome(-1, thisOutcome.getData(ns), thisOutcome.schema, thisOutcome.version); + Viewpoint impView; + try { + impView = (Viewpoint)Gateway.getStorage().get(getItemPath(), ClusterStorage.VIEWPOINT+"/"+thisOutcome.schema+"/"+thisOutcome.viewname, null); + + Diff xmlDiff = new Diff(newOutcome.getDOM(), impView.getOutcome().getDOM()); + if (xmlDiff.identical()) { + Logger.msg(5, "NewItem.create() - View "+thisOutcome.schema+"/"+thisOutcome.viewname+" in "+name+" identical, no update required"); + continue; + } + else { + Logger.msg("NewItem.create() - Difference found in view "+thisOutcome.schema+"/"+thisOutcome.viewname+" in "+name+": "+xmlDiff.toString()); + if (!reset && !impView.getEvent().getStepPath().equals("Import")) { + Logger.msg("Last edit was not done by import, and reset not requested. Not overwriting."); + continue; + } + } + } catch (ObjectNotFoundException ex) { + Logger.msg(3, "View "+thisOutcome.schema+"/"+thisOutcome.viewname+" not found in "+name+". Creating."); + impView = new Viewpoint(getItemPath(), thisOutcome.schema, thisOutcome.viewname, thisOutcome.version, -1); + } catch (PersistencyException e) { + throw new ObjectCannotBeUpdated("Could not check data for view "+thisOutcome.schema+"/"+thisOutcome.viewname+" in "+name); + } catch (InvalidDataException e) { + throw new ObjectCannotBeUpdated("Could not check previous event for view "+thisOutcome.schema+"/"+thisOutcome.viewname+" in "+name); + } + + // write new view/outcome/event + Transition predefDone = new Transition(0, "Done", 0, 0); + Event newEvent = hist.addEvent(agentPath, "Admin", "Import", "Import", "Import", thisOutcome.schema, thisOutcome.version, "PredefinedStep", 0, predefDone, thisOutcome.viewname); + newOutcome.setID(newEvent.getID()); + impView.setEventId(newEvent.getID()); + try { + Gateway.getStorage().put(getItemPath(), newOutcome, null); + Gateway.getStorage().put(getItemPath(), impView, null); + } catch (PersistencyException e) { + throw new ObjectCannotBeUpdated("Could not store data for view "+thisOutcome.schema+"/"+thisOutcome.viewname+" in "+name); + } + } + + // register domain path (before collections in case of recursive collections) + if (!domPath.exists()) { + domPath.setItemPath(getItemPath()); + Gateway.getLookupManager().add(domPath); + } + } + + public String getInitialPath() { + return initialPath; + } + + public void setInitialPath(String initialPath) { + this.initialPath = initialPath; + } + + public String getWorkflow() { + return workflow; + } + + public void setWorkflow(String workflow) { + this.workflow = workflow; + } + + public Integer getWorkflowVer() { + return workflowVer; + } + + public void setWorkflowVer(Integer workflowVer) { + this.workflowVer = workflowVer; + } + + public ArrayList getProperties() { + return properties; + } + + public void setProperties(ArrayList properties) { + this.properties = properties; + } + + public ArrayList getAggregationList() { + return aggregationList; + } + + public void setAggregationList(ArrayList aggregationList) { + this.aggregationList = aggregationList; + } + + public ArrayList getDependencyList() { + return dependencyList; + } + + public void setDependencyList(ArrayList dependencyList) { + this.dependencyList = dependencyList; + } + + public ArrayList getOutcomes() { + return outcomes; + } + + public void setOutcomes(ArrayList outcomes) { + this.outcomes = outcomes; + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportOutcome.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportOutcome.java new file mode 100644 index 0000000..b3be323 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportOutcome.java @@ -0,0 +1,48 @@ +/** + * 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.entity.imports; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.process.Gateway; + + +public class ImportOutcome { + public String schema, viewname, path, data; + public int version; + + public ImportOutcome() { + } + + public ImportOutcome(String schema, int version, String viewname, String path) { + super(); + this.schema = schema; + this.version = version; + this.viewname = viewname; + this.path = path; + } + + public String getData(String ns) throws ObjectNotFoundException { + if (data == null) + data = Gateway.getResource().getTextResource(ns, path); + return data; + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/imports/ImportRole.java b/src/main/java/org/cristalise/kernel/entity/imports/ImportRole.java new file mode 100644 index 0000000..daf1b4c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/imports/ImportRole.java @@ -0,0 +1,75 @@ +/** + * 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.entity.imports; + +import java.util.Iterator; + +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.lookup.Path; +import org.cristalise.kernel.lookup.RolePath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.process.module.ModuleImport; + + +public class ImportRole extends ModuleImport { + + private boolean jobList; + + public ImportRole() { + } + + @Override + public void create(AgentPath agentPath, boolean reset) throws ObjectAlreadyExistsException, ObjectCannotBeUpdated, CannotManageException, ObjectNotFoundException { + RolePath parent = new RolePath(); + if (name.indexOf('/') > -1) { + String[] roleComp = name.split("/"); + for (int i=0; i childIter = parent.getChildren(); + boolean found = false; + while (childIter.hasNext()) { + RolePath childRole = (RolePath)childIter.next(); + if (childRole.getName().equals(roleComp[i])) { + parent = childRole; + found = true; + break; + } + } + if (!found) throw new ObjectNotFoundException("Parent role "+roleComp[i]+" was not found"); + } + name = roleComp[roleComp.length-1]; + } + RolePath newRole = new RolePath(parent, name, jobList); + if (!newRole.exists()) Gateway.getLookupManager().createRole(newRole); + } + + public boolean hasJobList() { + return jobList; + } + + public void setJobList(boolean jobList) { + this.jobList = jobList; + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/package-info.java b/src/main/java/org/cristalise/kernel/entity/package-info.java new file mode 100644 index 0000000..23ab74c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/package-info.java @@ -0,0 +1,39 @@ +/** + * 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 + */ +/** + * The implementations of Items, and their core functionality. + * + *

The CORBA IDLs generate the Item and Agent interfaces and their support + * classes in this package. In the kernel source tree, the classes + * {@link TraceableEntity} and {@link ItemImplementation} provides the + * implementing object for the Item on the server side, while the Locator class, + * plus the {@link CorbaServer} handle instantiation and caching of Items (and + * Agents) on the server. + * + *

The corresponding implementation for Agents is located in the agent + * sub-package. + * + *

Also in this package is the {@link C2KLocalObject} interface, which is + * implemented by all objects that may be stored in the CRISTAL persistency + * mechanism. + */ + +package org.cristalise.kernel.entity; \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/AgentProxy.java b/src/main/java/org/cristalise/kernel/entity/proxy/AgentProxy.java new file mode 100644 index 0000000..4b05764 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/AgentProxy.java @@ -0,0 +1,323 @@ +/** + * 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.entity.proxy; + +import java.util.Date; +import java.util.Iterator; + +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.Agent; +import org.cristalise.kernel.entity.AgentHelper; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.agent.Job; +import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep; +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.Path; +import org.cristalise.kernel.persistency.outcome.OutcomeValidator; +import org.cristalise.kernel.persistency.outcome.Schema; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.process.auth.Authenticator; +import org.cristalise.kernel.scripting.ErrorInfo; +import org.cristalise.kernel.scripting.Script; +import org.cristalise.kernel.scripting.ScriptErrorException; +import org.cristalise.kernel.scripting.ScriptingEngineException; +import org.cristalise.kernel.utils.LocalObjectLoader; +import org.cristalise.kernel.utils.Logger; + + +/****************************************************************************** + * It is a wrapper for the connection and communication with Agent + * It caches data loaded from the Agent to reduce communication + * + * @version $Revision: 1.37 $ $Date: 2005/10/05 07:39:36 $ + * @author $Author: abranson $ + ******************************************************************************/ +public class AgentProxy extends ItemProxy +{ + + AgentPath mAgentPath; + String mAgentName; + Authenticator auth; + /************************************************************************** + * Creates an AgentProxy without cache and change notification + **************************************************************************/ + protected AgentProxy( org.omg.CORBA.Object ior, + AgentPath agentPath) + throws ObjectNotFoundException + { + super(ior, agentPath); + mAgentPath = agentPath; + } + + public Authenticator getAuthObj() { + return auth; + } + + public void setAuthObj(Authenticator auth) { + this.auth = auth; + } + + @Override + public Agent narrow() throws ObjectNotFoundException + { + try { + return AgentHelper.narrow(mIOR); + } catch (org.omg.CORBA.BAD_PARAM ex) { } + throw new ObjectNotFoundException("CORBA Object was not an Agent, or the server is down."); + } + + /** + * Standard execution of jobs. Note that this method should always be the one used from clients - all execution + * parameters are taken from the job where they're probably going to be correct. + * + * @param job + * @throws AccessRightsException + * @throws InvalidDataException + * @throws InvalidTransitionException + * @throws ObjectNotFoundException + * @throws PersistencyException + * @throws ObjectAlreadyExistsException + * @throws ScriptErrorException + * @throws InvalidCollectionModification + */ + public String execute(Job job) + throws AccessRightsException, + InvalidDataException, + InvalidTransitionException, + ObjectNotFoundException, + PersistencyException, + ObjectAlreadyExistsException, + ScriptErrorException, InvalidCollectionModification + { + ItemProxy item = Gateway.getProxyManager().getProxy(job.getItemPath()); + OutcomeValidator validator = null; + Date startTime = new Date(); + Logger.msg(3, "AgentProxy - executing "+job.getStepPath()+" for "+mAgentPath.getAgentName()); + // get the outcome validator if present + if (job.hasOutcome()) + { + String schemaName = job.getSchemaName(); + int schemaVersion = job.getSchemaVersion(); + + Logger.msg(5, "AgentProxy - fetching schema "+schemaName+"_"+schemaVersion+" for validation"); + // retrieve schema + Schema schema = LocalObjectLoader.getSchema(schemaName, schemaVersion); + + if (schema == null) + throw new InvalidDataException("Job references outcome type "+schemaName+" version "+schemaVersion+" that does not exist in this centre."); + + try { + validator = OutcomeValidator.getValidator(schema); + } catch (Exception e) { + throw new InvalidDataException("Could not create validator: "+e.getMessage()); + } + } + + if(job.hasScript()) { + Logger.msg(3, "AgentProxy - executing script "+job.getScriptName()+" v"+job.getScriptVersion()); + try { + + // pre-validate outcome from script if there is one + if (job.getOutcomeString()!= null && validator != null) { + Logger.msg(5, "AgentProxy - validating outcome before script execution"); + String error = validator.validate(job.getOutcomeString()); + if (error.length() > 0) { + Logger.error("Outcome not valid: \n " + error); + throw new InvalidDataException(error); + } + } + + // load script + ErrorInfo scriptErrors = (ErrorInfo)callScript(item, job); + String errorString = scriptErrors.toString(); + if (scriptErrors.getFatal()) { + Logger.msg(3, "AgentProxy - fatal script error"); + throw new ScriptErrorException(scriptErrors); + } + if (errorString.length() > 0) + Logger.warning("Script errors: "+errorString); + } catch (ScriptingEngineException ex) { + Logger.error(ex); + throw new InvalidDataException(ex.getMessage()); + } + } + + if (job.isOutcomeSet()) { + Logger.msg(3, "AgentProxy - validating outcome"); + String error = validator.validate(job.getOutcomeString()); + if (error.length() > 0) + throw new InvalidDataException(error); + } + + job.setAgentPath(mAgentPath); + Logger.msg(3, "AgentProxy - submitting job to item proxy"); + String result = item.requestAction(job); + if (Logger.doLog(3)) { + Date timeNow = new Date(); + long secsNow = (timeNow.getTime()-startTime.getTime())/1000; + Logger.msg(3, "Execution took "+secsNow+" seconds"); + } + + return result; + } + + private Object callScript(ItemProxy item, Job job) throws ScriptingEngineException { + Script script = new Script(item, this, job); + return script.execute(); + } + + public String execute(ItemProxy item, String predefStep, C2KLocalObject obj) + throws AccessRightsException, + InvalidDataException, + InvalidTransitionException, + ObjectNotFoundException, + PersistencyException, + ObjectAlreadyExistsException, InvalidCollectionModification + { + String param; + try { + param = marshall(obj); + } catch (Exception ex) { + Logger.error(ex); + throw new InvalidDataException("Error on marshall"); + } + return execute(item, predefStep, param); + } + + /** + * Multi-parameter execution. Wraps parameters up in a PredefinedStepOutcome + * if the schema of the requested step is such. + * + * @param item The item on which to execute the step + * @param predefStep The step name to run + * @param params An array of parameters to pass to the step. See each step's + * documentation for its required parameters + * + * @return The outcome after processing. May have been altered by the step. + * + * @throws AccessRightsException The agent was not allowed to execute this step + * @throws InvalidDataException The parameters supplied were incorrect + * @throws InvalidTransitionException The step wasn't available + * @throws ObjectNotFoundException Thrown by some steps that try to locate additional objects + * @throws PersistencyException Problem writing or reading the database + * @throws ObjectAlreadyExistsException Thrown by steps that create additional object + * @throws InvalidCollectionModification + */ + public String execute(ItemProxy item, String predefStep, String[] params) + throws AccessRightsException, + InvalidDataException, + InvalidTransitionException, + ObjectNotFoundException, + PersistencyException, + ObjectAlreadyExistsException, InvalidCollectionModification + { + String schemaName = PredefinedStep.getPredefStepSchemaName(predefStep); + String param; + if (schemaName.equals("PredefinedStepOutcome")) + param = PredefinedStep.bundleData(params); + else + param = params[0]; + + return item.getItem().requestAction(mAgentPath.getSystemKey(), "workflow/predefined/"+predefStep, PredefinedStep.DONE, param); + } + + /** + * Single parameter execution + * + * @see #execute(ItemProxy, String, String[]) + * + * @param item + * @param predefStep + * @param param + * @return + * @throws AccessRightsException + * @throws InvalidDataException + * @throws InvalidTransitionException + * @throws ObjectNotFoundException + * @throws PersistencyException + * @throws ObjectAlreadyExistsException + * @throws InvalidCollectionModification + */ + + public String execute(ItemProxy item, String predefStep, String param) + throws AccessRightsException, + InvalidDataException, + InvalidTransitionException, + ObjectNotFoundException, + PersistencyException, + ObjectAlreadyExistsException, InvalidCollectionModification + { + return execute(item, predefStep, new String[] {param }); + } + + /** Wrappers for scripts */ + public String marshall(Object obj) throws Exception { + return Gateway.getMarshaller().marshall(obj); + } + + public Object unmarshall(String obj) throws Exception { + return Gateway.getMarshaller().unmarshall(obj); + } + + /** Let scripts resolve items */ + public ItemProxy searchItem(String name) throws ObjectNotFoundException { + Iterator results = Gateway.getLookup().search(new DomainPath(""),name); + + Path returnPath = null; + if (!results.hasNext()) + throw new ObjectNotFoundException(name); + + while(results.hasNext()) { + Path nextMatch = results.next(); + if (returnPath != null && nextMatch.getUUID() != null && !returnPath.getUUID().equals(nextMatch.getUUID())) + throw new ObjectNotFoundException("Too many items with that name"); + returnPath = nextMatch; + } + + return Gateway.getProxyManager().getProxy(returnPath); + } + + public ItemProxy getItem(String itemPath) throws ObjectNotFoundException { + return (getItem(new DomainPath(itemPath))); + } + + @Override + public AgentPath getPath() { + return mAgentPath; + } + + public ItemProxy getItem(Path itemPath) throws ObjectNotFoundException { + return Gateway.getProxyManager().getProxy(itemPath); + } + + public ItemProxy getItemByUUID(String uuid) throws ObjectNotFoundException, InvalidItemPathException { + return Gateway.getProxyManager().getProxy(new ItemPath(uuid)); + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/DomainPathSubscriber.java b/src/main/java/org/cristalise/kernel/entity/proxy/DomainPathSubscriber.java new file mode 100644 index 0000000..bce1fa7 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/DomainPathSubscriber.java @@ -0,0 +1,38 @@ +/** + * 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.entity.proxy; + +import org.cristalise.kernel.lookup.DomainPath; + +/************************************************************************** + * + * $Revision: 1.1 $ + * $Date: 2004/02/05 16:11:57 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public interface DomainPathSubscriber { + + public void pathAdded(DomainPath path); + public void pathRemoved(DomainPath path); +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ItemProxy.java b/src/main/java/org/cristalise/kernel/entity/proxy/ItemProxy.java new file mode 100644 index 0000000..326da36 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ItemProxy.java @@ -0,0 +1,390 @@ +/** + * 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.entity.proxy; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; + +import org.cristalise.kernel.collection.Collection; +import org.cristalise.kernel.collection.CollectionArrayList; +import org.cristalise.kernel.common.AccessRightsException; +import org.cristalise.kernel.common.InvalidCollectionModification; +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.InvalidTransitionException; +import org.cristalise.kernel.common.ObjectAlreadyExistsException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.common.PersistencyException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.Item; +import org.cristalise.kernel.entity.ItemHelper; +import org.cristalise.kernel.entity.agent.Job; +import org.cristalise.kernel.entity.agent.JobArrayList; +import org.cristalise.kernel.lifecycle.instance.CompositeActivity; +import org.cristalise.kernel.lifecycle.instance.Workflow; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Viewpoint; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.utils.CastorXMLUtility; +import org.cristalise.kernel.utils.Logger; +import org.exolab.castor.mapping.MappingException; +import org.exolab.castor.xml.MarshalException; +import org.exolab.castor.xml.ValidationException; + + +/****************************************************************************** + * It is a wrapper for the connection and communication with Item + * It caches data loaded from the Item to reduce communication + * + * @version $Revision: 1.25 $ $Date: 2005/05/10 11:40:09 $ + * @author $Author: abranson $ + ******************************************************************************/ +public class ItemProxy +{ + + protected Item mItem = null; + protected ItemPath mItemPath; + protected org.omg.CORBA.Object mIOR; + private final HashMap, ProxyObserver> + mSubscriptions; + + /************************************************************************** + * + **************************************************************************/ + protected ItemProxy( org.omg.CORBA.Object ior, + ItemPath itemPath) + { + Logger.msg(8, "ItemProxy::initialise() - Initialising item proxy " +itemPath); + + mIOR = ior; + mItemPath = itemPath; + mSubscriptions = new HashMap, ProxyObserver>(); + + } + + public ItemPath getPath() { + return mItemPath; + } + + protected Item getItem() throws ObjectNotFoundException { + if (mItem == null) + mItem = narrow(); + return mItem; + } + + public Item narrow() throws ObjectNotFoundException + { + try { + return ItemHelper.narrow(mIOR); + } catch (org.omg.CORBA.BAD_PARAM ex) { } + throw new ObjectNotFoundException("CORBA Object was not an Item, or the server is down."); + } + + public void initialise( AgentPath agentId, + PropertyArrayList itemProps, + CompositeActivity workflow, + CollectionArrayList colls + ) + throws AccessRightsException, InvalidDataException, PersistencyException, ObjectNotFoundException, MarshalException, ValidationException, IOException, MappingException, InvalidCollectionModification + { + Logger.msg(7, "ItemProxy::initialise - started"); + CastorXMLUtility xml = Gateway.getMarshaller(); + if (itemProps == null) throw new InvalidDataException("No initial properties supplied"); + String propString = xml.marshall(itemProps); + String wfString = ""; + if (workflow != null) wfString = xml.marshall(workflow); + String collString = ""; + if (colls != null) collString = xml.marshall(colls); + + getItem().initialise( agentId.getSystemKey(), propString, wfString, collString); + } + + public void setProperty(AgentProxy agent, String name, String value) + throws AccessRightsException, + PersistencyException, InvalidDataException + { + String[] params = new String[2]; + params[0] = name; + params[1] = value; + try { + agent.execute(this, "WriteProperty", params); + } catch (AccessRightsException e) { + throw (e); + } catch (PersistencyException e) { + throw (e); + } catch (InvalidDataException e) { + throw (e); + } catch (Exception e) { + Logger.error(e); + throw new PersistencyException("Could not store property"); + } + } + + /** + * @throws InvalidCollectionModification + * + **************************************************************************/ + public String requestAction( Job thisJob ) + throws AccessRightsException, + InvalidTransitionException, + ObjectNotFoundException, + InvalidDataException, + PersistencyException, + ObjectAlreadyExistsException, + InvalidCollectionModification + { + String outcome = thisJob.getOutcomeString(); + // check fields that should have been filled in + if (outcome==null) + if (thisJob.isOutcomeRequired()) + throw new InvalidDataException("Outcome is required."); + else + outcome=""; + + if (thisJob.getAgentPath() == null) + throw new InvalidDataException("No Agent specified."); + + Logger.msg(7, "ItemProxy - executing "+thisJob.getStepPath()+" for "+thisJob.getAgentName()); + return getItem().requestAction (thisJob.getAgentPath().getSystemKey(), thisJob.getStepPath(), + thisJob.getTransition().getId(), outcome); + } + + /************************************************************************** + * + **************************************************************************/ + private ArrayList getJobList(AgentPath agentPath, boolean filter) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException + { + JobArrayList thisJobList; + try { + String jobs = getItem().queryLifeCycle(agentPath.getSystemKey(), filter); + thisJobList = (JobArrayList)Gateway.getMarshaller().unmarshall(jobs); + } + catch (Exception e) { + Logger.error(e); + throw new PersistencyException("Exception::ItemProxy::getJobList() - Cannot unmarshall the jobs"); + } + return thisJobList.list; + } + + public ArrayList getJobList(AgentProxy agent) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException + { + return getJobList(agent.getPath(), true); + } + + private Job getJobByName(String actName, AgentPath agent) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException { + + ArrayList jobList = getJobList(agent, true); + for (Job job : jobList) { + if (job.getStepName().equals(actName) && job.hasOutcome()) + return job; + } + return null; + + } + + public Collection getCollection(String collName) throws ObjectNotFoundException { + return (Collection)getObject(ClusterStorage.COLLECTION+"/"+collName+"/last"); + } + + public Workflow getWorkflow() throws ObjectNotFoundException { + return (Workflow)getObject(ClusterStorage.LIFECYCLE+"/workflow"); + } + + public Viewpoint getViewpoint(String schemaName, String viewName) throws ObjectNotFoundException { + return (Viewpoint)getObject(ClusterStorage.VIEWPOINT+"/"+schemaName+"/"+viewName); + } + + public Job getJobByName(String actName, AgentProxy agent) + throws AccessRightsException, + ObjectNotFoundException, + PersistencyException { + return getJobByName(actName, agent.getPath()); + } + + /** + * If this is reaped, clear out the cache for it too. + */ + @Override + protected void finalize() throws Throwable { + Logger.msg(7, "Proxy "+mItemPath+" reaped"); + Gateway.getStorage().clearCache(mItemPath, null); + Gateway.getProxyManager().removeProxy(mItemPath); + super.finalize(); + } + + /************************************************************************** + * + **************************************************************************/ + public String queryData( String path ) + throws ObjectNotFoundException + { + + try { + Logger.msg(7, "EntityProxy.queryData() - "+mItemPath+"/"+path); + if (path.endsWith("all")) { + Logger.msg(7, "EntityProxy.queryData() - listing contents"); + String[] result = Gateway.getStorage().getClusterContents(mItemPath, path.substring(0, path.length()-3)); + StringBuffer retString = new StringBuffer(); + for (int i = 0; i < result.length; i++) { + retString.append(result[i]); + if (i"+e.getMessage()+""; + } + } + + public String[] getContents( String path ) throws ObjectNotFoundException { + try { + return Gateway.getStorage().getClusterContents(mItemPath, path.substring(0, path.length())); + } catch (PersistencyException e) { + throw new ObjectNotFoundException(e.toString()); + } + } + + + /************************************************************************** + * + **************************************************************************/ + public C2KLocalObject getObject( String xpath ) + throws ObjectNotFoundException + { + // load from storage, falling back to proxy loader if not found in others + try + { + return Gateway.getStorage().get( mItemPath, xpath , null); + } + catch( PersistencyException ex ) + { + Logger.msg(4, "Exception loading object :"+mItemPath+"/"+xpath); + throw new ObjectNotFoundException( ex.toString() ); + } + } + + + + public String getProperty( String name ) + throws ObjectNotFoundException + { + Logger.msg(5, "Get property "+name+" from item "+mItemPath); + Property prop = (Property)getObject("Property/"+name); + try + { + return prop.getValue(); + } + catch (NullPointerException ex) + { + throw new ObjectNotFoundException(); + } + } + + public String getName() + { + try { + return getProperty("Name"); + } catch (ObjectNotFoundException ex) { + return null; + } + } + + + + + /************************************************************************** + * Subscription methods + **************************************************************************/ + + public void subscribe(MemberSubscription newSub) { + + newSub.setSubject(this); + synchronized (this){ + mSubscriptions.put( newSub, newSub.getObserver() ); + } + new Thread(newSub).start(); + Logger.msg(7, "Subscribed "+newSub.getObserver().getClass().getName()+" for "+newSub.interest); + } + + public void unsubscribe(ProxyObserver observer) + { + synchronized (this){ + for (Iterator> e = mSubscriptions.keySet().iterator(); e.hasNext();) { + MemberSubscription thisSub = e.next(); + if (mSubscriptions.get( thisSub ) == observer) { + e.remove(); + Logger.msg(7, "Unsubscribed "+observer.getClass().getName()); + } + } + } + } + + public void dumpSubscriptions(int logLevel) { + if (mSubscriptions.size() == 0) return; + Logger.msg(logLevel, "Subscriptions to proxy "+mItemPath+":"); + synchronized(this) { + for (MemberSubscription element : mSubscriptions.keySet()) { + ProxyObserver obs = element.getObserver(); + if (obs != null) + Logger.msg(logLevel, " "+element.getObserver().getClass().getName()+" subscribed to "+element.interest); + else + Logger.msg(logLevel, " Phantom subscription to "+element.interest); + } + } + } + + public void notify(ProxyMessage message) { + Logger.msg(4, "EntityProxy.notify() - Received change notification for "+message.getPath()+" on "+mItemPath); + synchronized (this){ + if (Gateway.getProxyServer()== null || !message.getServer().equals(Gateway.getProxyServer().getServerName())) + Gateway.getStorage().clearCache(mItemPath, message.getPath()); + for (Iterator> e = mSubscriptions.keySet().iterator(); e.hasNext();) { + MemberSubscription newSub = e.next(); + if (newSub.getObserver() == null) { // phantom + Logger.msg(4, "Removing phantom subscription to "+newSub.interest); + e.remove(); + } + else + newSub.update(message.getPath(), message.getState()); + } + } + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/MemberSubscription.java b/src/main/java/org/cristalise/kernel/entity/proxy/MemberSubscription.java new file mode 100644 index 0000000..2873eb8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/MemberSubscription.java @@ -0,0 +1,141 @@ +/** + * 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.entity.proxy; +import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.StringTokenizer; + +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.utils.Logger; + + +public class MemberSubscription implements Runnable { + public static final String ERROR = "Error"; + public static final String END = "theEND"; + + ItemProxy subject; + String interest; + // keep the subscriber by weak reference, so it is not kept from the garbage collector if no longer used + WeakReference> observerReference; + ArrayList contents = new ArrayList(); + boolean preLoad; + + public MemberSubscription(ProxyObserver observer, String interest, boolean preLoad) { + setObserver(observer); + this.interest = interest; + this.preLoad = preLoad; + } + + @Override + public void run() { + Thread.currentThread().setName("Member Subscription: "+subject.getPath()+":"+interest); + if (preLoad) loadChildren(); + } + + private void loadChildren() { + C newMember; + ProxyObserver observer = getObserver(); + if (observer == null) return; //reaped + try { + // fetch contents of path + String children = subject.queryData(interest+"/all"); + StringTokenizer tok = new StringTokenizer(children, ","); + ArrayList newContents = new ArrayList(); + while (tok.hasMoreTokens()) + newContents.add(tok.nextToken()); + + // look to see what's new + for (String newChild: newContents) { + + // load child object + try { + newMember = (C)subject.getObject(interest+"/"+newChild); + contents.remove(newChild); + observer.add(newMember); + } catch (ObjectNotFoundException ex) { + observer.control(ERROR, "Listed member "+newChild+" was not found."); + } catch (ClassCastException ex) { + Logger.error(ex); + observer.control(ERROR, "Listed member "+newChild+" was the wrong type."); + } + } + // report what's left in old contents as deleted + for (String oldChild: contents) { + observer.remove(interest+"/"+oldChild); + } + //replace contents arraylist + contents = newContents; + //report that we're done + observer.control(END, null); + } catch (Exception ex) { + observer.control(ERROR, "Query on "+interest+" failed with "+ex.getMessage()); + } + } + + public boolean isRelevant(String path) { + Logger.msg(7, "Checking relevance of "+path+" to "+interest); + return (path.startsWith(interest)); + } + + public void update(String path, boolean deleted) { + ProxyObserver observer = getObserver(); + if (observer == null) return; //reaped + Logger.msg(7, "Processing proxy message path "+path +" for "+observer+". Interest: "+interest+" Was Deleted:"+deleted); + if (!path.startsWith(interest)) // doesn't concern us + return; + + if (path.equals(interest)) // refresh contents + loadChildren(); + else { + String name = path.substring(interest.length()); + if (deleted) { + Logger.msg(4, "Removing "+path); + contents.remove(name); + observer.remove(name); + } + else { + try { + C newMember = (C)subject.getObject(path); + Logger.msg(4, "Adding "+path); + contents.add(name); + observer.add(newMember); + } catch (ObjectNotFoundException e) { + Logger.error("Member Subscription: could not load "+path); + Logger.error(e); + } + } + } + } + + public void setObserver(ProxyObserver observer) { + observerReference = new WeakReference>(observer); + } + + public void setSubject(ItemProxy subject) { + this.subject = subject; + } + + public ProxyObserver getObserver() { + return observerReference.get(); + } +} + diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ProxyClientConnection.java b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyClientConnection.java new file mode 100644 index 0000000..9f65afa --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyClientConnection.java @@ -0,0 +1,208 @@ +/** + * 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.entity.proxy; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.InterruptedIOException; +import java.io.PrintWriter; +import java.net.Socket; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Iterator; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; +import org.cristalise.kernel.utils.server.SocketHandler; + + +/************************************************************************** + * + * $Revision: 1.18 $ + * $Date: 2005/05/10 11:40:09 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public class ProxyClientConnection implements SocketHandler { + + Socket clientSocket = null; + static int clientId = -1; + int thisClientId; + ArrayList subscribedItems; + PrintWriter response; + BufferedReader request; + boolean closing = false; + + public ProxyClientConnection() { + super(); + thisClientId = ++clientId; + Gateway.getProxyServer().registerProxyClient(this); + Logger.msg(1, "Proxy Client Connection Handler "+thisClientId+" ready."); + } + + + @Override + public String getName() { + return "Proxy Client Connection"; + } + + @Override + public boolean isBusy() { + return clientSocket != null; + } + + @Override + public synchronized void setSocket(Socket newSocket) { + try { + Logger.msg(1, "Proxy Client Connection "+thisClientId+" connect from "+newSocket.getInetAddress()+":"+newSocket.getPort()); + newSocket.setSoTimeout(500); + clientSocket = newSocket; + response = new PrintWriter(clientSocket.getOutputStream(), true); + subscribedItems = new ArrayList(); + } catch (SocketException ex) { + Logger.msg("Could not set socket timeout:"); + Logger.error(ex); + closeSocket(); + } catch (IOException ex) { + Logger.msg("Could not setup output stream:"); + Logger.error(ex); + closeSocket(); + } + } + + /** + * Main loop. Reads proxy commands from the client and acts on them. + */ + @Override + public void run() { + Thread.currentThread().setName("Proxy Client Connection: "+clientSocket.getInetAddress()); + Logger.msg(7, "ProxyClientConnection "+thisClientId+" - Setting up proxy client connection with "+clientSocket.getInetAddress()); + try { + request = new BufferedReader(new InputStreamReader(clientSocket.getInputStream())); + String input = null; + ProxyMessage thisMessage; + while (clientSocket != null) { + try { + input = request.readLine(); + Logger.msg(9, "ProxyClientConnection "+thisClientId+" - received "+input); + thisMessage = new ProxyMessage(input); + processMessage(thisMessage); + } catch (InterruptedIOException ex) { //timeout + } catch (InvalidDataException ex) { // invalid proxy message + Logger.error("ProxyClientConnection "+thisClientId+" - Invalid proxy message: "+input); + } + + } + } catch (IOException ex) { + if (!closing) + Logger.error("ProxyClientConnection "+thisClientId+" - Error reading from socket."); + } + closeSocket(); + Logger.msg(1, "ProxyClientConnection "+thisClientId+" closed."); + } + + private void processMessage(ProxyMessage message) throws InvalidDataException { + + // proxy disconnection + if (message.getPath().equals(ProxyMessage.BYEPATH)) { + Logger.msg(7, "ProxyClientConnection "+thisClientId+" disconnecting"); + closeSocket(); + } + + // proxy checking connection + else if (message.getPath().equals(ProxyMessage.PINGPATH)) + response.println(ProxyMessage.pingMessage); + + // new subscription to entity changes + else if (message.getPath().equals(ProxyMessage.ADDPATH)) { + Logger.msg(7, "ProxyClientConnection "+thisClientId+" subscribed to "+message.getItemPath()); + synchronized (subscribedItems) { + subscribedItems.add(message.getItemPath()); + } + } + + // remove of subscription to entity changes + else if (message.getPath().equals(ProxyMessage.DELPATH)) { + synchronized (subscribedItems) { + subscribedItems.remove(message.getItemPath()); + } + Logger.msg(7, "ProxyClientConnection "+thisClientId+" unsubscribed from "+message.getItemPath()); + } + + else // unknown message + Logger.error("ProxyClientConnection "+thisClientId+" - Unknown message type: "+message); + + } + + public synchronized void sendMessage(ProxyMessage message) { + if (clientSocket==null) return; // idle + boolean relevant = message.getItemPath() == null; + synchronized (subscribedItems) { + for (Iterator iter = subscribedItems.iterator(); iter.hasNext() && !relevant;) { + ItemPath thisKey = iter.next(); + if (thisKey.equals(message.getItemPath())) + relevant = true; + } + } + if (!relevant) return; // not for our client + + response.println(message); + } + + @Override + public void shutdown() { + if (isBusy()) { + closing = true; + Logger.msg("ProxyClientConnection "+thisClientId+" closing."); + closeSocket(); + } + } + + @Override + public String toString() { + if (clientSocket == null) return thisClientId+": idle"; + else return thisClientId+": "+clientSocket.getInetAddress(); + } + + private synchronized void closeSocket() { + if (clientSocket==null) return; + try { + request.close(); + response.close(); + clientSocket.close(); + } catch (IOException e) { + Logger.error("ProxyClientConnection "+thisClientId+" - Could not close socket."); + Logger.error(e); + } + synchronized (subscribedItems) { + subscribedItems = null; + } + + clientSocket = null; + + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ProxyManager.java b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyManager.java new file mode 100644 index 0000000..6f5bde3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyManager.java @@ -0,0 +1,277 @@ +/** + * 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.entity.proxy; + +import java.util.ArrayList; +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.Iterator; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.lookup.AgentPath; +import org.cristalise.kernel.lookup.DomainPath; +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.lookup.Path; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.utils.Logger; +import org.cristalise.kernel.utils.SoftCache; + + + +public class ProxyManager +{ + SoftCache proxyPool = new SoftCache(50); + HashMap treeSubscribers = new HashMap(); + HashMap connections = new HashMap(); + + /** + * Create a proxy manager to listen for proxy events and reap unused proxies + */ + public ProxyManager() + { + Logger.msg(5, "ProxyManager - Starting....."); + + Iterator servers = Gateway.getLookup().search(new DomainPath("/servers"), new Property("Type", "Server", false)); + while(servers.hasNext()) { + Path thisServerResult = servers.next(); + try { + ItemPath thisServerPath = thisServerResult.getItemPath(); + String remoteServer = ((Property)Gateway.getStorage().get(thisServerPath, ClusterStorage.PROPERTY+"/Name", null)).getValue(); + String portStr = ((Property)Gateway.getStorage().get(thisServerPath, ClusterStorage.PROPERTY+"/ProxyPort", null)).getValue(); + int remotePort = Integer.parseInt(portStr); + connectToProxyServer(remoteServer, remotePort); + + } catch (Exception ex) { + Logger.error("Exception retrieving proxy server connection data for "+thisServerResult); + Logger.error(ex); + } + } + } + + public void connectToProxyServer(String name, int port) { + ProxyServerConnection oldConn = connections.get(name); + if (oldConn != null) + oldConn.shutdown(); + connections.put(name, new ProxyServerConnection(name, port, this)); + } + + + protected void resubscribe(ProxyServerConnection conn) { + synchronized (proxyPool) { + for (ItemPath key : proxyPool.keySet()) { + ProxyMessage sub = new ProxyMessage(key, ProxyMessage.ADDPATH, false); + Logger.msg(5, "Subscribing to item "+key); + conn.sendMessage(sub); + } + } + } + + /** + * @param sub + */ + private void sendMessage(ProxyMessage sub) { + for (ProxyServerConnection element : connections.values()) { + element.sendMessage(sub); + } + + } + + public void shutdown() { + Logger.msg("ProxyManager.shutdown() - flagging shutdown of server connections"); + for (ProxyServerConnection element : connections.values()) { + element.shutdown(); + } + } + + protected void processMessage(ProxyMessage thisMessage) throws InvalidDataException { + if (Logger.doLog(9)) Logger.msg(9, thisMessage.toString()); + + if (thisMessage.getPath().equals(ProxyMessage.PINGPATH)) // ping response + return; + + if (thisMessage.getItemPath() == null) // must be domain path info + informTreeSubscribers(thisMessage.getState(), thisMessage.getPath()); + else { + // proper proxy message + Logger.msg(5, "Received proxy message: "+thisMessage.toString()); + ItemProxy relevant = proxyPool.get(thisMessage.getItemPath()); + if (relevant == null) + Logger.warning("Received proxy message for sysKey "+thisMessage.getItemPath()+" which we don't have a proxy for."); + else + try { + relevant.notify(thisMessage); + } catch (Throwable ex) { + Logger.error("Error caught notifying proxy listener "+relevant.toString()+" of "+thisMessage.toString()); + Logger.error(ex); + } + } + } + + private void informTreeSubscribers(boolean state, String path) { + DomainPath last = new DomainPath(path); + DomainPath parent; boolean first = true; + synchronized(treeSubscribers) { + while((parent = last.getParent()) != null) { + ArrayList currentKeys = new ArrayList(); + currentKeys.addAll(treeSubscribers.keySet()); + for (DomainPathSubscriber sub : currentKeys) { + DomainPath interest = treeSubscribers.get(sub); + if (interest!= null && interest.equals(parent)) { + if (state == ProxyMessage.ADDED) + sub.pathAdded(last); + else if (first) + sub.pathRemoved(last); + } + } + last = parent; + first = false; + } + } + } + + public void subscribeTree(DomainPathSubscriber sub, DomainPath interest) { + synchronized(treeSubscribers) { + treeSubscribers.put(sub, interest); + } + } + + public void unsubscribeTree(DomainPathSubscriber sub) { + synchronized(treeSubscribers) { + treeSubscribers.remove(sub); + } + } + + /************************************************************************** + * + **************************************************************************/ + private ItemProxy createProxy( org.omg.CORBA.Object ior, + ItemPath itemPath) + throws ObjectNotFoundException + { + + ItemProxy newProxy = null; + + Logger.msg(5, "ProxyManager::creating proxy on Item " + itemPath); + + if( itemPath instanceof AgentPath ) { + newProxy = new AgentProxy(ior, (AgentPath)itemPath); + } + else { + newProxy = new ItemProxy(ior, itemPath); + } + + // subscribe to changes from server + ProxyMessage sub = new ProxyMessage(itemPath, ProxyMessage.ADDPATH, false); + sendMessage(sub); + reportCurrentProxies(9); + return ( newProxy ); + } + + protected void removeProxy( ItemPath itemPath ) + { + ProxyMessage sub = new ProxyMessage(itemPath, ProxyMessage.DELPATH, true); + Logger.msg(5,"ProxyManager.removeProxy() - Unsubscribing to proxy informer for "+itemPath); + sendMessage(sub); + } + + + /************************************************************************** + * Called by the other GetProxy methods. Fills in either the ior or the + * SystemKey + **************************************************************************/ + private ItemProxy getProxy( org.omg.CORBA.Object ior, + ItemPath itemPath) + throws ObjectNotFoundException + { + + synchronized(proxyPool) { + ItemProxy newProxy; + // return it if it exists + newProxy = proxyPool.get(itemPath); + if (newProxy == null) { + // create a new one + newProxy = createProxy(ior, itemPath); + proxyPool.put(itemPath, newProxy); + } + return newProxy; + + } + } + + /************************************************************************** + * ItemProxy getProxy( String ) + * + * Proxy from Alias + **************************************************************************/ + public ItemProxy getProxy( Path path ) + throws ObjectNotFoundException + { + ItemPath itemPath; + if (path instanceof ItemPath) itemPath = (ItemPath)path; + else itemPath = path.getItemPath(); + Logger.msg(8,"ProxyManager::getProxy(" + path.toString() + ")"); + return getProxy( Gateway.getLookup().resolve(itemPath), + itemPath ); + + } + + public AgentProxy getAgentProxy( AgentPath path ) + throws ObjectNotFoundException + { + return (AgentProxy) getProxy(path); + } + + /************************************************************************** + * void reportCurrentProxies() + * + * A utility to Dump the current proxies loaded + **************************************************************************/ + public void reportCurrentProxies(int logLevel) + { + if (!Logger.doLog(logLevel)) return; + Logger.msg(logLevel, "Current proxies: "); + try { + synchronized(proxyPool) { + Iterator i = proxyPool.keySet().iterator(); + + for( int count=0; i.hasNext(); count++ ) + { + ItemPath nextProxy = i.next(); + ItemProxy thisProxy = proxyPool.get(nextProxy); + if (thisProxy != null) + Logger.msg(logLevel, + "" + count + ": " + + proxyPool.get(nextProxy).getClass().getName() + + ": " + nextProxy); + } + } + } catch (ConcurrentModificationException ex) { + Logger.msg(logLevel, "Proxy cache modified. Aborting."); + } + } + + + +} + diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ProxyMessage.java b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyMessage.java new file mode 100644 index 0000000..61fdcd4 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyMessage.java @@ -0,0 +1,129 @@ +/** + * 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.entity.proxy; + +import java.io.IOException; +import java.net.DatagramPacket; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.lookup.InvalidItemPathException; +import org.cristalise.kernel.lookup.ItemPath; + + + +/************************************************************************** + * + * $Revision: 1.11 $ + * $Date: 2005/05/10 11:40:09 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public class ProxyMessage { + + // special server message paths + public static final String BYEPATH = "bye"; + public static final String ADDPATH = "add"; + public static final String DELPATH = "del"; + public static final String PINGPATH = "ping"; + public static final boolean ADDED = false; + public static final boolean DELETED = true; + + static ProxyMessage byeMessage = new ProxyMessage(null, BYEPATH, ADDED); + static ProxyMessage pingMessage = new ProxyMessage(null, PINGPATH, ADDED); + + private ItemPath itemPath = null; + private String path = ""; + private String server = null; + private boolean state = ADDED; + + public ProxyMessage() { + super(); + } + public ProxyMessage(ItemPath itemPath, String path, boolean state) { + this(); + setItemPath(itemPath); + setPath(path); + setState(state); + } + + public ProxyMessage(String line) throws InvalidDataException, IOException { + if (line == null) + throw new IOException("Null proxy message"); + String[] tok = line.split(":"); + if (tok.length != 2) + throw new InvalidDataException("String '"+line+"' does not constitute a valid proxy message."); + if (tok[0].length() > 0 && !tok[0].equals("tree")) { + try { + itemPath = new ItemPath(tok[0]); + } catch (InvalidItemPathException e) { + throw new InvalidDataException("Item in proxy message "+line+" was not valid"); + } + } + path = tok[1]; + if (path.startsWith("-")) { + state = DELETED; + path = path.substring(1); + } + } + + public ProxyMessage(DatagramPacket packet) throws InvalidDataException, IOException { + this(new String(packet.getData())); + } + + public ItemPath getItemPath() { + return itemPath; + } + + public void setItemPath(ItemPath itemPath) { + this.itemPath = itemPath; + } + + public String getPath() { + return path; + } + + public void setPath(String newPath) { + this.path = newPath; + } + + public boolean getState() { + return state; + } + + public void setState(boolean state) { + this.state = state; + } + + @Override + public String toString() { + return (itemPath==null?"tree":itemPath.getUUID())+":"+(state?"-":"")+path; + } + + public String getServer() { + return server; + } + + public void setServer(String server) { + this.server = server; + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ProxyObserver.java b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyObserver.java new file mode 100644 index 0000000..bd21034 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyObserver.java @@ -0,0 +1,47 @@ +/** + * 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.entity.proxy; + +import org.cristalise.kernel.entity.C2KLocalObject; + + + +public interface ProxyObserver +{ + /************************************************************************** + * Subscribed items are broken apart and fed one by one to these methods. + * Replacement after an event is done by feeding the new memberbase with the same id. + * ID could be an XPath? + **************************************************************************/ + public void add(V contents); + + /************************************************************************** + * the 'type' parameter should be an indication of the type of object + * supplied so that the subscriber can associate the call back with + * one of its subscriptions. If we go with an Xpath subscription form, + * then the id will probably be sufficient. + * Should be comparable (substring whatever) with the parameter given to + * the subscribe method of ItemProxy. + **************************************************************************/ + public void remove(String id); + + public void control(String control, String msg); +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ProxyServer.java b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyServer.java new file mode 100644 index 0000000..249ec0f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyServer.java @@ -0,0 +1,129 @@ +/** + * 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.entity.proxy; + +import java.util.ArrayList; +import java.util.concurrent.LinkedBlockingQueue; + +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.Logger; +import org.cristalise.kernel.utils.server.SimpleTCPIPServer; + + +public class ProxyServer implements Runnable { + + // server objects + ArrayList proxyClients; + SimpleTCPIPServer proxyListener = null; + String serverName = null; + boolean keepRunning = true; + LinkedBlockingQueue messageQueue; + + public ProxyServer(String serverName) { + Logger.msg(5, "ProxyManager::initServer - Starting....."); + int port = Gateway.getProperties().getInt("ItemServer.Proxy.port", 0); + this.serverName = serverName; + this.proxyClients = new ArrayList(); + this.messageQueue = new LinkedBlockingQueue(); + + if (port == 0) { + Logger.error("ItemServer.Proxy.port not defined in connect file. Remote proxies will not be informed of changes."); + return; + } + + // set up the proxy server + try { + Logger.msg(5, "ProxyManager::initServer - Initialising proxy informer on port "+port); + proxyListener = new SimpleTCPIPServer(port, ProxyClientConnection.class, 200); + proxyListener.startListening(); + } catch (Exception ex) { + Logger.error("Error setting up Proxy Server. Remote proxies will not be informed of changes."); + Logger.error(ex); + } + // start the message queue delivery thread + new Thread(this).start(); + } + + @Override + public void run() { + + while(keepRunning) { + ProxyMessage message = messageQueue.poll(); + if (message != null) { + synchronized(proxyClients) { + for (ProxyClientConnection client : proxyClients) { + client.sendMessage(message); + } + } + } else + try { + synchronized(this) { + if (messageQueue.isEmpty()) wait(); + } + } catch (InterruptedException e) { } + } + + } + + public String getServerName() { + return serverName; + } + + public void sendProxyEvent(ProxyMessage message) { + try { + synchronized(this) { + messageQueue.put(message); + notify(); + } + } catch (InterruptedException e) { } + } + + public void reportConnections(int logLevel) { + synchronized(proxyClients) { + Logger.msg(logLevel, "Currently connected proxy clients:"); + for (ProxyClientConnection client : proxyClients) { + Logger.msg(logLevel, " "+client); + } + } + } + + public void shutdownServer() { + Logger.msg(1, "ProxyManager: Closing Server."); + proxyListener.stopListening(); + synchronized(this) { + keepRunning = false; + notify(); + } + } + + public void registerProxyClient(ProxyClientConnection client) { + synchronized(proxyClients) { + proxyClients.add(client); + } + } + + public void unRegisterProxyClient(ProxyClientConnection client) { + synchronized(proxyClients) { + proxyClients.remove(client); + } + } + +} diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/ProxyServerConnection.java b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyServerConnection.java new file mode 100644 index 0000000..1b4fba4 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/ProxyServerConnection.java @@ -0,0 +1,145 @@ +/** + * 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.entity.proxy; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.InterruptedIOException; +import java.io.PrintWriter; +import java.net.Socket; + +import org.cristalise.kernel.common.InvalidDataException; +import org.cristalise.kernel.utils.Logger; + + + +public class ProxyServerConnection extends Thread +{ + + public boolean serverIsActive = true; + // proxy client details + String serverName; + int serverPort; + Socket serverConnection; + ProxyManager manager; + // for talking to the proxy server + PrintWriter serverStream; + boolean listening = false; + static boolean isServer = false; + + /** + * Create an entity proxy manager to listen for proxy events and reap unused proxies + */ + public ProxyServerConnection(String host, int port, ProxyManager manager) + { + Logger.msg(5, "ProxyServerConnection - Initialising connection to "+host+":"+port); + serverName = host; + serverPort = port; + this.manager = manager; + listening = true; + start(); + } + + @Override + public void run() { + Thread.currentThread().setName("Proxy Client Connection Listener to "+serverName+":"+serverPort); + while (listening) { + try { + if (serverConnection == null) connect(); + if (serverConnection != null) { + BufferedReader request = new BufferedReader(new InputStreamReader(serverConnection.getInputStream())); + String input = null; + ProxyMessage thisMessage; + while (listening && serverConnection != null) { + try { + input = request.readLine(); + thisMessage = new ProxyMessage(input); + thisMessage.setServer(serverName); + manager.processMessage(thisMessage); + } catch (InterruptedIOException ex) { // timeout - send a ping + sendMessage(ProxyMessage.pingMessage); + } catch (InvalidDataException ex) { // invalid proxy message + if (input != null) + Logger.error("EntityProxyManager - Invalid proxy message: "+input); + } + } + } + } catch (IOException ex) { + Logger.error("ProxyServerConnection - Disconnected from "+serverName+":"+serverPort); + try { + serverStream.close(); + serverConnection.close(); + } catch (IOException e1) { } + + + serverStream = null; + serverConnection = null; + } + } + + if (serverStream != null) { + try { + Logger.msg(1, "Disconnecting from proxy server on "+serverName+":"+serverPort); + serverStream.println(ProxyMessage.byeMessage.toString()); + serverStream.close(); + serverConnection.close(); + serverConnection = null; + } catch (Exception e) { + Logger.error("Error disconnecting from proxy server."); + } + } + } + + public void connect() { + Logger.msg(3, "ProxyServerConnection - connecting to proxy server on "+serverName+":"+serverPort); + try { + serverConnection = new Socket(serverName, serverPort); + serverConnection.setKeepAlive(true); + serverIsActive = true; + serverConnection.setSoTimeout(5000); + serverStream = new PrintWriter(serverConnection.getOutputStream(), true); + Logger.msg("Connected to proxy server on "+serverName+":"+serverPort); + manager.resubscribe(this); + } catch (Exception e) { + Logger.msg(3, "Could not connect to proxy server. Retrying in 5s"); + try { Thread.sleep(5000); } catch (InterruptedException ex) { } + serverStream = null; + serverConnection = null; + serverIsActive = false; + } + } + + public void shutdown() { + Logger.msg("Proxy Client: flagging shutdown."); + listening = false; + } + + /** + * @param sub + */ + public void sendMessage(ProxyMessage sub) { + if (serverStream != null) + serverStream.println(sub); + } + +} + diff --git a/src/main/java/org/cristalise/kernel/entity/proxy/package-info.java b/src/main/java/org/cristalise/kernel/entity/proxy/package-info.java new file mode 100644 index 0000000..6391b65 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/proxy/package-info.java @@ -0,0 +1,76 @@ +/** + * 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 + */ +/** + * The Proxy API is a major part of the client-side functionality of the + * CRISTAL API, which provides client-side proxy objects that represent the + * Items and Agents on the server. It is the main entry point for many + * components, such as Scripts and Job execution. An AgentProxy is returned on + * login, and should be used as the root for all user-based CRISTAL interactions. + * + *

The Proxy API provides the following functionality: + * + *

    + *
  • Transparent storage integration - Combines direct database access + * with remote calls to data retrieval methods on the Items. This allows client + * processes to load Item data directly from databases whenever possible + * without bothering the CRISTAL server. For example, the LDAP Lookup + * implementation allows client processes to load Item Properties directly from + * the LDAP server.
  • + * + *
  • Data object browsing and loading - The proxy objects allow client + * processes to browse through the storage cluster structure beneath the Item, + * and access the objects directly without having to unmarshall their XML forms. + * All object types have their own get methods, so there's no need to construct + * their paths nor cast. + * + *
  • Item object and directory change notification - When a proxy + * object is created, it notifies the CRISTAL server that its Item is located + * on, and it notified of all additions, deletions and modifications of objects + * within that Item so it can remain up-to-date. Client applications may use + * the {@link ProxyObserver} interface to be notified of changes, using + * {@link MemberSubscription} instances to set up push subscriptions to cluster + * contents. It also provides a mechanism for subscribing to directory paths, + * so that domain tree browsers can implement asynchronous loading and update + * themselves when the tree changes.
  • + * + *
  • Job querying - Job objects may be retrieved directly from an + * ItemProxy, and may also be filtered by Activity name.
  • + * + *
  • Job execution - The {@link AgentProxy} provides the main + * execution method for Jobs. This method performs outcome validation and + * executes required CRISTAL Scripts in the client process before the execution + * is requested on the server. Additional execution methods to call Predefined + * Steps are also available. + * + *
  • Utility methods for resolution and marshalling - The AgentProxy + * provides utility methods for finding Items in the directory by name, path, + * or system key, and gives access to the Castor XML marshalling system to + * transform CRISTAL objects to XML and back again.
  • + *
+ *

The core object of the Proxy API is the ProxyManager, which is initialized + * as a static member of the Gateway on initialization. This object can be used + * to create a Proxy object from a Path from the directory, and maintains a + * connection to the server called the Proxy Update Notification Channel, + * through which it subscribes to Items it holds proxies for so it can be + * informed of changes to Item data through {@link ProxyMessage} objects. + * + */ +package org.cristalise.kernel.entity.proxy; \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/transfer/TransferItem.java b/src/main/java/org/cristalise/kernel/entity/transfer/TransferItem.java new file mode 100644 index 0000000..6b6901f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/transfer/TransferItem.java @@ -0,0 +1,177 @@ +/** + * 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.entity.transfer; + +import java.io.File; +import java.util.ArrayList; +import java.util.Iterator; + +import org.cristalise.kernel.collection.Collection; +import org.cristalise.kernel.collection.CollectionArrayList; +import org.cristalise.kernel.common.ObjectNotFoundException; +import org.cristalise.kernel.entity.C2KLocalObject; +import org.cristalise.kernel.entity.TraceableEntity; +import org.cristalise.kernel.lifecycle.instance.Workflow; +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.Path; +import org.cristalise.kernel.persistency.ClusterStorage; +import org.cristalise.kernel.persistency.outcome.Outcome; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.property.Property; +import org.cristalise.kernel.property.PropertyArrayList; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.Logger; + + +public class TransferItem { + private ArrayList domainPaths; + protected ItemPath itemPath; + static AgentPath importAgentId; + + public TransferItem() throws Exception { + try { + importAgentId = Gateway.getLookup().getAgentPath("system"); + } catch (ObjectNotFoundException e) { + Logger.error("TransferItem - System user not found!"); + throw e; + } + } + + public TransferItem(ItemPath itemPath) throws Exception { + this.itemPath = itemPath; + domainPaths = new ArrayList(); + Iterator paths = Gateway.getLookup().searchAliases(itemPath); + while (paths.hasNext()) { + DomainPath thisPath = (DomainPath)paths.next(); + domainPaths.add(thisPath.toString()); + } + } + + public ArrayList getDomainPaths() { + return domainPaths; + } + + public void setDomainPaths(ArrayList domainPaths) { + this.domainPaths = domainPaths; + } + + public void setUUID( String uuid ) throws InvalidItemPathException + { + itemPath = new ItemPath(uuid); + } + + public String getUUID() { + return itemPath.getUUID().toString(); + } + + public void exportItem(File dir, String path) throws Exception { + Logger.msg("Path " + path + " in " + itemPath); + String[] contents = Gateway.getStorage().getClusterContents(itemPath, path); + if (contents.length > 0) { + FileStringUtility.createNewDir(dir.getCanonicalPath()); + for (String content : contents) { + exportItem(new File(dir, content), path + "/" + content); + } + } else { //no children, try to dump object + try { + C2KLocalObject obj = Gateway.getStorage().get(itemPath, path, null); + Logger.msg("Dumping object " + path + " in " + itemPath); + File dumpPath = new File(dir.getCanonicalPath() + ".xml"); + FileStringUtility.string2File(dumpPath, Gateway.getMarshaller().marshall(obj)); + return; + } catch (ObjectNotFoundException ex) { + } // not an object + } + } + + public void importItem(File dir) throws Exception { + // check if already exists + try { + Property name = (Property)Gateway.getStorage().get(itemPath, ClusterStorage.PROPERTY + "/Name", null); + throw new Exception("Entity " + itemPath + " already in use as " + name.getValue()); + } catch (Exception ex) { + } + + // retrieve objects + ArrayList objectFiles = FileStringUtility.listDir(dir.getCanonicalPath(), false, true); + ArrayList objects = new ArrayList(); + for (String element : objectFiles) { + String xmlFile = FileStringUtility.file2String(element); + C2KLocalObject newObj; + String choppedPath = element.substring(dir.getCanonicalPath().length()+1, element.length()-4); + Logger.msg(choppedPath); + if (choppedPath.startsWith(ClusterStorage.OUTCOME)) + newObj = new Outcome(choppedPath, xmlFile); + else + newObj = (C2KLocalObject)Gateway.getMarshaller().unmarshall(xmlFile); + + objects.add(newObj); + } + + // create item + TraceableEntity newItem = Gateway.getCorbaServer().createItem(itemPath); + Gateway.getLookupManager().add(itemPath); + + PropertyArrayList props = new PropertyArrayList(); + CollectionArrayList colls = new CollectionArrayList(); + Workflow wf = null; + // put objects + for (C2KLocalObject obj : objects) { + if (obj instanceof Property) + props.list.add((Property)obj); + else if (obj instanceof Collection) + colls.list.add((Collection)obj); + else if (obj instanceof Workflow) + wf = (Workflow)obj; + } + + if (wf == null) + throw new Exception("No workflow found in import for "+itemPath); + + // init item + newItem.initialise(importAgentId.getSystemKey(), + Gateway.getMarshaller().marshall(props), + Gateway.getMarshaller().marshall(wf.search("workflow/domain")), + Gateway.getMarshaller().marshall(colls)); + + // store objects + importByType(ClusterStorage.HISTORY, objects); + importByType(ClusterStorage.OUTCOME, objects); + importByType(ClusterStorage.VIEWPOINT, objects); + Gateway.getStorage().commit(this); + // add domPaths + for (String element : domainPaths) { + DomainPath newPath = new DomainPath(element, itemPath); + Gateway.getLookupManager().add(newPath); + } + } + + private void importByType(String type, ArrayList objects) throws Exception { + for (C2KLocalObject element : objects) { + if (element.getClusterType().equals(type)) + Gateway.getStorage().put(itemPath, element, this); + } + + } +} \ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/entity/transfer/TransferSet.java b/src/main/java/org/cristalise/kernel/entity/transfer/TransferSet.java new file mode 100644 index 0000000..c4a578a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/transfer/TransferSet.java @@ -0,0 +1,94 @@ +/** + * 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.entity.transfer; + +import java.io.File; +import java.util.ArrayList; + +import org.cristalise.kernel.lookup.ItemPath; +import org.cristalise.kernel.process.Gateway; +import org.cristalise.kernel.utils.FileStringUtility; +import org.cristalise.kernel.utils.Logger; + + +/************************************************************************** + * + * $Revision: 1.5 $ + * $Date: 2005/04/26 06:48:13 $ + * + * Copyright (C) 2003 CERN - European Organization for Nuclear Research + * All rights reserved. + **************************************************************************/ + +public class TransferSet { + + public ArrayList items; + + public TransferSet() { + } + + public TransferSet(ItemPath[] itemPaths) { + items = new ArrayList(); + for (ItemPath item : itemPaths) { + try { + items.add(new TransferItem(item)); + } catch (Exception ex) { + Logger.error("Could not add item "+item); + Logger.error(ex); + } + } + } + + public void exportPackage(File dir) throws Exception { + if (items==null || items.size() == 0) + throw new Exception("Nothing to dump"); + FileStringUtility.createNewDir(dir.getAbsolutePath()); + for (TransferItem element : items) { + try { + element.exportItem(new File(dir, element.itemPath.getUUID().toString()), "/"); + } catch (Exception ex) { + Logger.error("Error dumping item "+element.itemPath); + Logger.error(ex); + } + } + + try { + String self = Gateway.getMarshaller().marshall(this); + FileStringUtility.string2File(new File(dir, "transferSet.xml"), self); + } catch (Exception ex) { + Logger.error("Error writing header file"); + Logger.error(ex); + } + } + + public void importPackage(File rootDir) { + for (TransferItem element : items) { + Logger.msg(5, "Importing "+element.itemPath); + try { + element.importItem(new File(rootDir, element.itemPath.getUUID().toString())); + } catch (Exception ex) { + Logger.error("Import of item "+element.itemPath+" failed. Rolling back"); + Logger.error(ex); + Gateway.getStorage().abort(element); + } + } + } +} diff --git a/src/main/java/org/cristalise/kernel/entity/transfer/package-info.java b/src/main/java/org/cristalise/kernel/entity/transfer/package-info.java new file mode 100644 index 0000000..bfd8317 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/entity/transfer/package-info.java @@ -0,0 +1,36 @@ +/** + * 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 + */ +/** + * Export and Import of Items. + * + *

{@link TransferItem} provides a mechanism for marshalling all of the + * C2KLocalObjects in an Item to XML and exporting them to disk, and then + * importing that Item on another server. {@link TransferSet} can export many + * Items at a time and preserve their domain paths. + * + *

This package is not currently used, as with the previous system key + * integer sequence it was not possible to import collections onto other servers + * but now Items are identified using UUIDs, this may now converge with the + * module mechanism. + * + */ + +package org.cristalise.kernel.entity.transfer; \ No newline at end of file -- cgit v1.2.3