diff options
Diffstat (limited to 'src/main/java/org/cristalise/kernel/entity')
36 files changed, 5041 insertions, 0 deletions
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
+ * <p>Each object will be stored as the path /clustertype/name in most cases. Exceptions are:
+ * <ul>
+ * <li>Collections - /Collection/Name/Version (default 'last')
+ * <li>Outcomes - /Outcome/SchemaType/SchemaVersion/EventId
+ * <li>Viewpoints - /ViewPoint/SchemaType/Name
+ * </ul>
+ *
+ * @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<ItemPath, Servant> mItemCache;
+ private POA mRootPOA;
+ private POA mItemPOA;
+ private POA mAgentPOA;
+ private POAManager mPOAManager;
+
+ public CorbaServer() throws InvalidDataException {
+ mItemCache = new SoftCache<ItemPath, Servant>(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:
+*
+* <pre>
+* ,. '\'\ ,---.
+* . | \\ l\\l_ // |
+* _ _ | \\/ `/ `.| |
+* /~\\ \ //~\ | Y | | || Y |
+* | \\ \ // | | \| | |\ / |
+* [ || || ] \ | o|o | > /
+* ] Y || || Y [ \___\_--_ /_/__/
+* | \_|l,------.l|_/ | /.-\(____) /--.\
+* | >' `< | `--(______)----'
+* \ (/~`--____--'~\) / u// u / \
+* `-_>-__________-<_-' / \ / /|
+* /(_#(__)#_)\ ( .) / / ]
+* \___/__\___/ `.`' / [
+* /__`--'__\ |`-' |
+* /\(__,>-~~ __) | |_
+* /\//\\( `--~~ ) _l |-:.
+* '\/ <^\ /^> | ` ( < \\
+* _\ >-__-< /_ ,-\ ,-~~->. \ `:._,/
+* (___\ /___) (____/ (____) `-'
+* Kovax and, paradoxically, Kovax
+* </pre>
+***************************************************************************/
+
+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.
+ *
+ * <p>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<String, OutcomeInitiator> ocInitCache = new HashMap<String, OutcomeInitiator>();
+
+ /***************************************************************************
+ * 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<Job>
+{
+
+ public JobArrayList()
+ {
+ super();
+ }
+
+ public JobArrayList(ArrayList<Job> 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<Job>
+{
+
+ /**************************************************************************
+ * 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<Job> 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<String> staleJobs = new ArrayList<String>();
+ Iterator<String> 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<Job> getJobsOfItem( ItemPath itemPath )
+ {
+ Iterator<Job> currentMembers = values().iterator();
+ Job j = null;
+ Vector<Job> jobs = new Vector<Job>();
+
+ 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.
+ *
+ * <p>This package contains the classes for the implementation of
+ * Agents on the CRISTAL server. They correspond to the Item implementations in
+ * the parent package.
+ * <p>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<Property> properties = new ArrayList<Property>();
+ private ArrayList<String> roles = new ArrayList<String>();
+
+ 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<String> getRoles() {
+ return roles;
+ }
+
+ public void setRoles(ArrayList<String> roles) {
+ this.roles = roles;
+ }
+
+ public ArrayList<Property> getProperties() {
+ return properties;
+ }
+
+ public void setProperties(ArrayList<Property> 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<ImportAggregationMember> aggregationMemberList = new ArrayList<ImportAggregationMember>();
+ 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<ImportDependencyMember> dependencyMemberList = new ArrayList<ImportDependencyMember>();
+ 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<Property> properties = new ArrayList<Property>();
+ protected ArrayList<ImportAggregation> aggregationList = new ArrayList<ImportAggregation>();
+ protected ArrayList<ImportDependency> dependencyList = new ArrayList<ImportDependency>();
+ protected ArrayList<ImportOutcome> outcomes = new ArrayList<ImportOutcome>();
+
+ 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<Property> getProperties() {
+ return properties;
+ }
+
+ public void setProperties(ArrayList<Property> properties) {
+ this.properties = properties;
+ }
+
+ public ArrayList<ImportAggregation> getAggregationList() {
+ return aggregationList;
+ }
+
+ public void setAggregationList(ArrayList<ImportAggregation> aggregationList) {
+ this.aggregationList = aggregationList;
+ }
+
+ public ArrayList<ImportDependency> getDependencyList() {
+ return dependencyList;
+ }
+
+ public void setDependencyList(ArrayList<ImportDependency> dependencyList) {
+ this.dependencyList = dependencyList;
+ }
+
+ public ArrayList<ImportOutcome> getOutcomes() {
+ return outcomes;
+ }
+
+ public void setOutcomes(ArrayList<ImportOutcome> 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<roleComp.length-1; i++) {
+ Iterator<Path> 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.
+ *
+ * <p>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.
+ *
+ * <p>The corresponding implementation for Agents is located in the agent
+ * sub-package.
+ *
+ * <p>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<Path> 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<MemberSubscription<?>, 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<MemberSubscription<?>, 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<Job> 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<Job> getJobList(AgentProxy agent)
+ throws AccessRightsException,
+ ObjectNotFoundException,
+ PersistencyException
+ {
+ return getJobList(agent.getPath(), true);
+ }
+
+ private Job getJobByName(String actName, AgentPath agent)
+ throws AccessRightsException,
+ ObjectNotFoundException,
+ PersistencyException {
+
+ ArrayList<Job> 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<result.length-1) retString.append(",");
+ }
+ Logger.msg(7, "EntityProxy.queryData() - "+retString.toString());
+ return retString.toString();
+ }
+ C2KLocalObject target = Gateway.getStorage().get(mItemPath, path, null);
+ return Gateway.getMarshaller().marshall(target);
+ } catch (ObjectNotFoundException e) {
+ throw e;
+ } catch (Exception e) {
+ Logger.error(e);
+ return "<ERROR>"+e.getMessage()+"</ERROR>";
+ }
+ }
+
+ 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<MemberSubscription<?>> 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<MemberSubscription<?>> 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<C extends C2KLocalObject> 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<ProxyObserver<C>> observerReference;
+ ArrayList<String> contents = new ArrayList<String>();
+ boolean preLoad;
+
+ public MemberSubscription(ProxyObserver<C> 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<C> observer = getObserver();
+ if (observer == null) return; //reaped
+ try {
+ // fetch contents of path
+ String children = subject.queryData(interest+"/all");
+ StringTokenizer tok = new StringTokenizer(children, ",");
+ ArrayList<String> newContents = new ArrayList<String>();
+ 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<C> 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<C> observer) {
+ observerReference = new WeakReference<ProxyObserver<C>>(observer);
+ }
+
+ public void setSubject(ItemProxy subject) {
+ this.subject = subject;
+ }
+
+ public ProxyObserver<C> 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<ItemPath> 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<ItemPath>();
+ } 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<ItemPath> 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<ItemPath, ItemProxy> proxyPool = new SoftCache<ItemPath, ItemProxy>(50);
+ HashMap<DomainPathSubscriber, DomainPath> treeSubscribers = new HashMap<DomainPathSubscriber, DomainPath>();
+ HashMap<String, ProxyServerConnection> connections = new HashMap<String, ProxyServerConnection>();
+
+ /**
+ * Create a proxy manager to listen for proxy events and reap unused proxies
+ */
+ public ProxyManager()
+ {
+ Logger.msg(5, "ProxyManager - Starting.....");
+
+ Iterator<Path> 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<DomainPathSubscriber> currentKeys = new ArrayList<DomainPathSubscriber>();
+ 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<ItemPath> 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<V extends C2KLocalObject>
+{
+ /**************************************************************************
+ * 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<ProxyClientConnection> proxyClients;
+ SimpleTCPIPServer proxyListener = null;
+ String serverName = null;
+ boolean keepRunning = true;
+ LinkedBlockingQueue<ProxyMessage> 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<ProxyClientConnection>();
+ this.messageQueue = new LinkedBlockingQueue<ProxyMessage>();
+
+ 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.
+ *
+ * <p>The Proxy API provides the following functionality:
+ *
+ * <ul>
+ * <li><b>Transparent storage integration</b> - 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.</li>
+ *
+ * <li><b>Data object browsing and loading</b> - 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.</b>
+ *
+ * <li><b>Item object and directory change notification</b> - 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.</li>
+ *
+ * <li><b>Job querying</b> - Job objects may be retrieved directly from an
+ * ItemProxy, and may also be filtered by Activity name.</li>
+ *
+ * <li><b>Job execution</b> - 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.
+ *
+ * <li><b>Utility methods for resolution and marshalling</b> - 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.</li>
+ * </ul>
+ * <p>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<String> 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<String>();
+ Iterator<Path> paths = Gateway.getLookup().searchAliases(itemPath);
+ while (paths.hasNext()) {
+ DomainPath thisPath = (DomainPath)paths.next();
+ domainPaths.add(thisPath.toString());
+ }
+ }
+
+ public ArrayList<String> getDomainPaths() {
+ return domainPaths;
+ }
+
+ public void setDomainPaths(ArrayList<String> 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<String> objectFiles = FileStringUtility.listDir(dir.getCanonicalPath(), false, true);
+ ArrayList<C2KLocalObject> objects = new ArrayList<C2KLocalObject>();
+ 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<C2KLocalObject> 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<TransferItem> items;
+
+ public TransferSet() {
+ }
+
+ public TransferSet(ItemPath[] itemPaths) {
+ items = new ArrayList<TransferItem>();
+ 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.
+ *
+ * <p>{@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.
+ *
+ * <p>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 |
