diff options
Diffstat (limited to 'src/main/java/org')
233 files changed, 28929 insertions, 0 deletions
diff --git a/src/main/java/org/cristalise/kernel/collection/Aggregation.java b/src/main/java/org/cristalise/kernel/collection/Aggregation.java new file mode 100644 index 0000000..2ae450b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/Aggregation.java @@ -0,0 +1,178 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.collection;
+
+import org.cristalise.kernel.common.InvalidCollectionModification;
+import org.cristalise.kernel.common.ObjectAlreadyExistsException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.graph.model.GraphModel;
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.graph.model.TypeNameAndConstructionInfo;
+import org.cristalise.kernel.graph.model.Vertex;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.CastorHashMap;
+import org.cristalise.kernel.utils.Language;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**
+ * A Collection with a graph layout
+ */
+
+abstract public class Aggregation extends Collection<AggregationMember>
+{
+
+ protected GraphModel mLayout = new GraphModel(new AggregationVertexOutlineCreator());
+
+ private final TypeNameAndConstructionInfo[] mVertexTypeNameAndConstructionInfo = {
+ new TypeNameAndConstructionInfo(Language.translate("Slot"), "AggregationMember")
+ };
+
+ public Aggregation()
+ {
+ setName("Aggregation");
+ }
+
+
+ public GraphModel getLayout()
+ {
+ return mLayout;
+ }
+
+ public void setLayout(GraphModel layout)
+ {
+ mLayout = layout;
+ layout.setVertexOutlineCreator(new AggregationVertexOutlineCreator());
+ }
+
+ public TypeNameAndConstructionInfo[] getVertexTypeNameAndConstructionInfo()
+ {
+ return mVertexTypeNameAndConstructionInfo;
+ }
+
+ public boolean exists(ItemPath itemPath)
+ {
+ for (int i=0; i<size(); i++)
+ {
+ AggregationMember element = mMembers.list.get(i);
+ if (element.getItemPath().equals(itemPath))
+ return true;
+ }
+ return false;
+ }
+
+ public AggregationMember getMemberPair(int vertexID)
+ {
+ for (int i=0; i<size(); i++)
+ {
+ AggregationMember element = mMembers.list.get(i);
+ if (element.getID() == vertexID)
+ return element;
+ }
+ return null;
+ }
+
+ public AggregationMember addSlot(CastorHashMap props, String classProps, GraphPoint location, int w, int h)
+ {
+
+ // Default geometry if not present
+ if (location == null) location = new GraphPoint(100,100*getCounter());
+ if (w<0) w = 20;
+ if (h<0) h = 20;
+
+ // Create new member object
+ AggregationMember aggMem = new AggregationMember();
+ aggMem.setProperties(props);
+ aggMem.setClassProps(classProps);
+ // create vertex
+ Vertex vertex = new Vertex();
+ vertex.setHeight(h); vertex.setWidth(w);
+ mLayout.addVertexAndCreateId(vertex,location);
+ aggMem.setCollection(this);
+ aggMem.setID(vertex.getID());
+ aggMem.setIsLayoutable(true);
+
+ mMembers.list.add(aggMem);
+ Logger.msg(8, "AggregationDescription::addSlot new slot linked to vertexid " + vertex.getID());
+ return aggMem;
+ }
+
+ public AggregationMember addMember(ItemPath itemPath, CastorHashMap props, String classProps, GraphPoint location, int w, int h)
+ throws InvalidCollectionModification, ObjectAlreadyExistsException
+ {
+ AggregationMember aggMem = addSlot(props, classProps, location, w, h);
+ if (itemPath != null) { // some clients use this method when not setting a member
+ aggMem.assignItem(itemPath);
+ aggMem.setIsComposite( getIsComposite(itemPath, getName()) );
+ }
+ Logger.msg(8, "AggregationDescription::addMember(" + itemPath + ") assigned to new slot " + aggMem.getID());
+ return aggMem;
+ }
+
+
+ @Override
+ public AggregationMember addMember(ItemPath itemPath, CastorHashMap props, String classProps)
+ throws InvalidCollectionModification, ObjectAlreadyExistsException
+ {
+ return addMember(itemPath, props, classProps, null, -1, -1);
+ }
+
+
+ public AggregationMember addMember(CastorHashMap props, String classProps, GraphPoint location, int w, int h)
+ throws InvalidCollectionModification {
+ try {
+ return addMember(null, props, classProps, location, w, h);
+ } catch (ObjectAlreadyExistsException e) { // not assigning an item so this won't happen
+ return null;
+ }
+ }
+
+ public AggregationMember addSlot(CastorHashMap props, String classProps)
+ {
+ return addSlot(props, classProps, null, -1, -1);
+ }
+
+ @Override
+ public void removeMember(int memberId) throws ObjectNotFoundException {
+ for (AggregationMember element : mMembers.list) {
+ if (element.getID() == memberId) {
+ element.clearItem();
+ mLayout.removeVertex(getLayout().getVertexById(memberId));
+ return;
+ }
+ }
+ throw new ObjectNotFoundException("Member "+memberId+" not found");
+ }
+
+ static public boolean getIsComposite(ItemPath itemPath, String name)
+ {
+ if (itemPath == null) return false;
+ try {
+ for(String collName: Gateway.getProxyManager().getProxy(itemPath).getContents(ClusterStorage.COLLECTION) )
+ if (name == null || name.equals(collName)) return true;
+ } catch (ObjectNotFoundException e) {
+ return false;
+ }
+ return false;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/collection/AggregationDescription.java b/src/main/java/org/cristalise/kernel/collection/AggregationDescription.java new file mode 100644 index 0000000..dbcf030 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/AggregationDescription.java @@ -0,0 +1,82 @@ +/**
+ * 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.collection;
+
+/**
+ * The description of a Collection with a graph layout. Each slot is
+ * instantiated empty in the resulting Aggregation, with ClassProps taken from
+ * the PropertyDescription outcome of the description slot's referenced Item.
+ */
+
+import org.cristalise.kernel.common.InvalidCollectionModification;
+import org.cristalise.kernel.common.ObjectAlreadyExistsException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.graph.model.Vertex;
+import org.cristalise.kernel.property.PropertyDescriptionList;
+import org.cristalise.kernel.property.PropertyUtility;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class AggregationDescription extends Aggregation implements CollectionDescription<AggregationMember>
+{
+
+ public AggregationDescription()
+ {
+ setName("AggregationDescription");
+ }
+
+ public AggregationDescription(String name)
+ {
+ setName(name);
+ }
+
+ @Override
+ public Aggregation newInstance() throws ObjectNotFoundException
+ {
+ AggregationInstance newInstance = new AggregationInstance(getName());
+ //for each desc member
+ for (int i=0; i<size(); i++)
+ {
+ AggregationMember mem = mMembers.list.get(i);
+ //get the propdesc of the member item and look for an explicit version
+ String descVer = getDescVer(mem);
+ PropertyDescriptionList pdList = PropertyUtility.getPropertyDescriptionOutcome(mem.getItemPath(), descVer);
+ if (pdList!=null)
+ {
+ //create the new props of the member object
+ try {
+ Vertex v = getLayout().getVertexById(mem.getID());
+ newInstance.addMember(null, PropertyUtility.createProperty(pdList), pdList.getClassProps(),v.getCentrePoint(),v.getWidth(),v.getHeight());
+ } catch (InvalidCollectionModification e) {
+ } catch (ObjectAlreadyExistsException e) { }
+ }
+ else
+ {
+ Logger.error("AggregationDescription::newInstance() There is no PropertyDescription. Cannot instantiate. " + mem.getItemPath());
+ return null;
+ }
+
+
+ }
+
+ return newInstance;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/collection/AggregationInstance.java b/src/main/java/org/cristalise/kernel/collection/AggregationInstance.java new file mode 100644 index 0000000..850e32b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/AggregationInstance.java @@ -0,0 +1,69 @@ +/**
+ * 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.collection;
+
+/**
+ * Instance of an Aggregation. Unlike in the description, Items may only be
+ * assigned to one slot.
+ */
+
+import org.cristalise.kernel.common.InvalidCollectionModification;
+import org.cristalise.kernel.common.ObjectAlreadyExistsException;
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.utils.CastorHashMap;
+
+
+public class AggregationInstance extends Aggregation
+{
+
+ public AggregationInstance()
+ {
+ setName("AggregationInstance");
+ }
+
+ public AggregationInstance(String name)
+ {
+ setName(name);
+ }
+
+
+ @Override
+ public AggregationMember addMember(ItemPath itemPath, CastorHashMap props, String classProps)
+ throws InvalidCollectionModification, ObjectAlreadyExistsException
+ {
+ if( itemPath != null && exists(itemPath))
+ throw new ObjectAlreadyExistsException(itemPath+" already exists in this collection.");
+ else
+ return super.addMember(itemPath, props, classProps);
+ }
+
+ @Override
+ public AggregationMember addMember(ItemPath itemPath, CastorHashMap props, String classProps, GraphPoint location, int w, int h)
+ throws InvalidCollectionModification, ObjectAlreadyExistsException
+ {
+ if( itemPath != null && exists(itemPath))
+ throw new ObjectAlreadyExistsException(itemPath+" already exists in this collection.");
+ else
+ return super.addMember(itemPath, props, classProps, location, w, h);
+ }
+}
+
diff --git a/src/main/java/org/cristalise/kernel/collection/AggregationMember.java b/src/main/java/org/cristalise/kernel/collection/AggregationMember.java new file mode 100644 index 0000000..cafebd8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/AggregationMember.java @@ -0,0 +1,170 @@ +/**
+ * 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.collection;
+
+import java.util.StringTokenizer;
+
+import org.cristalise.kernel.common.InvalidCollectionModification;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.entity.proxy.ItemProxy;
+import org.cristalise.kernel.graph.model.GraphableVertex;
+import org.cristalise.kernel.lookup.InvalidItemPathException;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.property.Property;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**
+* A CollectionMember, or slot, of an Aggregation instance or description.
+* Verifies type information of Items during assignment based on
+* PropertyDescription information stored in slot properties and listed as
+* ClassProps.
+*/
+
+public class AggregationMember extends GraphableVertex implements CollectionMember
+{
+
+ private ItemPath mItemPath = null;
+ private ItemProxy mItem = null;
+ private Aggregation mCollection = null;
+ private String mClassProps = null;
+ private String mItemName = null;
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public AggregationMember()
+ {
+ super();
+ }
+
+ public void setCollection(Aggregation aggregation)
+ {
+ mCollection = aggregation;
+ }
+
+ public void setClassProps(String props)
+ {
+ mClassProps = props;
+ }
+
+ @Override
+ public ItemPath getItemPath()
+ {
+ return mItemPath;
+ }
+
+ public Aggregation getCollection()
+ {
+ return mCollection;
+ }
+
+ @Override
+ public String getClassProps()
+ {
+ return mClassProps;
+ }
+
+ @Override
+ public void assignItem(ItemPath itemPath) throws InvalidCollectionModification
+ {
+ if (itemPath != null) {
+ if (mClassProps == null || getProperties() == null)
+ throw new InvalidCollectionModification("ClassProps not yet set. Cannot check membership validity.");
+
+ //for each mandatory prop check if its in the member property and has the matching value
+ StringTokenizer sub = new StringTokenizer(mClassProps, ",");
+ while (sub.hasMoreTokens())
+ {
+ String aClassProp = sub.nextToken();
+ try {
+ String memberValue = (String)getProperties().get(aClassProp);
+ Property ItemProperty = (Property)Gateway.getStorage().get(itemPath, ClusterStorage.PROPERTY+"/"+aClassProp, null);
+ if (ItemProperty == null)
+ throw new InvalidCollectionModification("Property "+aClassProp+ " does not exist for item " + itemPath );
+ if (ItemProperty.getValue() == null || !ItemProperty.getValue().equalsIgnoreCase(memberValue))
+ throw new InvalidCollectionModification("Value of mandatory prop "+aClassProp+" does not match: " + ItemProperty.getValue()+"!="+memberValue);
+ }
+ catch (InvalidCollectionModification ex) {
+ throw ex;
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ throw new InvalidCollectionModification("Error checking properties");
+ }
+ }
+ }
+
+ mItemPath = itemPath;
+ mItem = null;
+ mItemName = null;
+ }
+
+ @Override
+ public void clearItem() {
+ mItemPath = null;
+ mItem = null;
+ mItemName = null;
+ }
+
+ @Override
+ public ItemProxy resolveItem() throws ObjectNotFoundException {
+ if (mItem == null && mItemPath != null) {
+ mItem = Gateway.getProxyManager().getProxy(mItemPath);
+ }
+ return mItem;
+
+ }
+
+ public String getItemName() {
+ if (mItemName == null) {
+ if (mItemPath != null) {
+ try {
+ mItemName = resolveItem().getName();
+ } catch (ObjectNotFoundException ex) {
+ Logger.error(ex);
+ mItemName = "Error ("+mItemPath+")";
+ }
+ }
+ else
+ mItemName = "Empty";
+ }
+
+ return mItemName;
+ }
+
+ public void setChildUUID(String uuid) throws InvalidCollectionModification, InvalidItemPathException {
+ mItemPath = new ItemPath(uuid);
+ mItemName = null;
+ }
+
+
+ @Override
+ public String getChildUUID() {
+ if (getItemPath() == null) return null;
+ return getItemPath().getUUID().toString();
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/collection/AggregationVertexFactory.java b/src/main/java/org/cristalise/kernel/collection/AggregationVertexFactory.java new file mode 100644 index 0000000..de5c9db --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/AggregationVertexFactory.java @@ -0,0 +1,59 @@ +/**
+ * 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.collection;
+
+import org.cristalise.kernel.graph.model.GraphModelManager;
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.graph.model.TypeNameAndConstructionInfo;
+import org.cristalise.kernel.graph.model.VertexFactory;
+import org.cristalise.kernel.utils.CastorHashMap;
+
+/**
+ * GraphModel vertex factory for AggregationMembers
+ *
+ */
+public class AggregationVertexFactory implements VertexFactory
+{
+ private Aggregation mAggregation = null;
+
+
+ @Override
+ public void setCreationContext(Object aggregation)
+ {
+ if (aggregation != null && aggregation instanceof Aggregation)
+ mAggregation = (Aggregation)aggregation;
+ }
+
+
+ @Override
+ public void create
+ (
+ GraphModelManager graphModelManager,
+ GraphPoint location,
+ TypeNameAndConstructionInfo typeNameAndConstructionInfo
+ ) throws Exception
+ {
+ if (typeNameAndConstructionInfo.mInfo.equals("AggregationMember")) {
+ mAggregation.addMember(null, new CastorHashMap(), "",location, 40, 40);
+ }
+ }
+}
+
diff --git a/src/main/java/org/cristalise/kernel/collection/AggregationVertexOutlineCreator.java b/src/main/java/org/cristalise/kernel/collection/AggregationVertexOutlineCreator.java new file mode 100644 index 0000000..62b519d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/AggregationVertexOutlineCreator.java @@ -0,0 +1,68 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.collection;
+
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.graph.model.Vertex;
+import org.cristalise.kernel.graph.model.VertexOutlineCreator;
+
+/**
+ * AggregationMember vertex outline creator. Sets up the new dimensions and
+ * position on the GraphModel.
+ *
+ */
+public class AggregationVertexOutlineCreator implements VertexOutlineCreator
+{
+ @Override
+ public void setOutline(Vertex vertex)
+ {
+ GraphPoint centre = vertex.getCentrePoint();
+ int height = vertex.getHeight();
+ int width = vertex.getWidth();
+
+
+ if (height==0 || width==0)
+ vertex.setOutlinePoints
+ (
+ new GraphPoint[]
+ {
+ new GraphPoint(centre.x-20, centre.y-20),
+ new GraphPoint(centre.x+20, centre.y-20),
+ new GraphPoint(centre.x+20, centre.y+20),
+ new GraphPoint(centre.x-20, centre.y+20)
+
+ }
+ );
+ else
+
+ vertex.setOutlinePoints
+ (
+ new GraphPoint[]
+ {
+ new GraphPoint(centre.x-width/2, centre.y-height/2),
+ new GraphPoint(centre.x+width/2, centre.y-height/2),
+ new GraphPoint(centre.x+width/2, centre.y+height/2),
+ new GraphPoint(centre.x-width/2, centre.y+height/2)
+
+ }
+ );
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/collection/Collection.java b/src/main/java/org/cristalise/kernel/collection/Collection.java new file mode 100644 index 0000000..04adee7 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/Collection.java @@ -0,0 +1,262 @@ +/**
+ * 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.collection;
+
+import org.cristalise.kernel.common.InvalidCollectionModification;
+import org.cristalise.kernel.common.ObjectAlreadyExistsException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.graph.model.GraphModel;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.utils.CastorHashMap;
+
+
+/**
+ * Collections are Item local objects that reference other Items.
+ *
+ * <p>In parallel with the OO meta-model, Items can be linked to other Items in
+ * different ways. These links are modelled with Collections, which are local
+ * objects stored in an Item which reference a number of other Items in the same
+ * server. The Collections holds a CollectionMember, sometimes known as a slot,
+ * to reference each Item and store additional information about the link.
+ *
+ * <p>Features:
+ * <ul>
+ * <li><b>Typing</b> - Collections can restrict membership of based on type
+ * information derived from Item, Property and Collection descriptions. This
+ * restriction may be per-slot or apply to the whole Collection.
+ *
+ * <li><b>Fixed or flexible slots</b> - The CollectionMember objects of a
+ * Collection may be empty, individually typed, or created and removed as
+ * required, simulating either array, structures or lists.
+ *
+ * <li><b>Layout</b> - Collections can include a {@link GraphModel} to lay out
+ * its slots on a two-dimensional canvas, for modelling real world compositions.
+ * </ul>
+ *
+ * <p>Collections are managed through predefined steps.
+ */
+abstract public class Collection<E extends CollectionMember> implements C2KLocalObject
+{
+
+ public static final short EMPTY = -1;
+ private int mCounter = -1; // Contains next available Member ID
+ protected CollectionMemberList<E> mMembers = new CollectionMemberList<E>();
+ protected String mName = ""; // Not checked for uniqueness
+ protected Integer mVersion = null;
+
+ /**
+ * Fetch the current highest member ID of the collection. This is found by
+ * scanning all the current members and kept in the mCounter field, but is
+ * not persistent.
+ * @return the current highest member ID
+ */
+ public int getCounter()
+ {
+ if (mCounter == -1)
+ for (E element : mMembers.list) {
+ if (mCounter < element.getID())
+ mCounter = element.getID();
+ }
+ return ++mCounter;
+ }
+
+ /**
+ * @return The total number of slots in this collection, including empty
+ * ones
+ */
+ public int size()
+ {
+ return mMembers.list.size();
+ }
+
+ /**
+ * Sets the collection name
+ */
+ @Override
+ public void setName(String name)
+ {
+ mName = name;
+ }
+
+ /**
+ * @return The collection's name
+ */
+ @Override
+ public String getName()
+ {
+ return mName;
+ }
+
+ /**
+ * Get the collection version. Null if not set, and will be stored as 'last'
+ * @return Integer version
+ */
+ public Integer getVersion() {
+ return mVersion;
+ }
+
+ /**
+ * Set a named version for this collection. Must be an integer or null.
+ * Named versions will be stored separately to the current version ('last')
+ * and should not change once saved.
+ *
+ * @param Integer version
+ */
+ public void setVersion(Integer mVersion) {
+ this.mVersion = mVersion;
+ }
+
+ /**
+ * Get the version name for storage, which is 'last' unless the version
+ * number is set.
+ *
+ * @return
+ */
+ public String getVersionName() {
+ return mVersion==null?"last":String.valueOf(mVersion);
+ }
+
+ @Override
+ public String getClusterType()
+ {
+ return ClusterStorage.COLLECTION;
+ }
+
+ public void setMembers(CollectionMemberList<E> newMembers)
+ {
+ mMembers = newMembers;
+ }
+
+ public boolean contains(ItemPath itemPath) {
+ for (E element : mMembers.list) {
+ if (element.getItemPath().equals(itemPath))
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Gets the description version referenced by the given collection member.
+ * Assumes 'last' if version not given.
+ *
+ * @param mem The member in question
+ * @return String version tag
+ */
+ public String getDescVer(E mem) {
+ String descVer = "last";
+ Object descVerObj = mem.getProperties().get("Version");
+ if (descVerObj != null) descVer = descVerObj.toString();
+ return descVer;
+ }
+
+ /**
+ * Check if all slots have an assigned Item
+ * @return boolean
+ */
+ public boolean isFull()
+ {
+ for (E element : mMembers.list) {
+ if (element.getItemPath() == null)
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Find collection member by integer ID
+ * @param memberId to find
+ * @return the CollectionMember with that ID
+ * @throws ObjectNotFoundException when the ID wasn't found
+ */
+ public E getMember(int memberId) throws ObjectNotFoundException {
+ for (E element : mMembers.list) {
+ if (element.getID() == memberId)
+ return element;
+ }
+ throw new ObjectNotFoundException("Member "+memberId+" not found in "+mName);
+ }
+
+ public CollectionMemberList<E> getMembers()
+ {
+ return mMembers;
+ }
+
+ /**
+ * Add a member to this collection, with the given property and class properties
+ * and optionally an Item to assign, which may be null if the collection allows
+ * empty slots.
+ *
+ * @param itemPath the Item to assign to the new slot. Optional for collections
+ * that allow empty slots
+ * @param props the Properties of the new member
+ * @param classProps the names of the properties that dictate the type of
+ * assigned Items.
+ * @return the new CollectionMember instance
+ * @throws InvalidCollectionModification when the assignment was invalid because
+ * of collection constraints, such as global type constraints, or not allowing
+ * empty slots.
+ * @throws ObjectAlreadyExistsException some collections don't allow multiple
+ * slots assigned to the same Item, and throw this Exception if it is attempted
+ */
+ public abstract E addMember(ItemPath itemPath, CastorHashMap props, String classProps) throws InvalidCollectionModification, ObjectAlreadyExistsException;
+
+ /**
+ * Removes the slot with the given ID from the collection.
+ *
+ * @param memberId to remove
+ * @throws ObjectNotFoundException when there was no slot with this ID found.
+ */
+ public abstract void removeMember(int memberId) throws ObjectNotFoundException;
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((mMembers == null) ? 0 : mMembers.hashCode());
+ result = prime * result + ((mName == null) ? 0 : mName.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;
+ Collection<?> other = (Collection<?>) obj;
+ if (mMembers == null) {
+ if (other.mMembers != null)
+ return false;
+ } else if (!mMembers.equals(other.mMembers))
+ return false;
+ if (mName == null) {
+ if (other.mName != null)
+ return false;
+ } else if (!mName.equals(other.mName))
+ return false;
+ return true;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/collection/CollectionArrayList.java b/src/main/java/org/cristalise/kernel/collection/CollectionArrayList.java new file mode 100644 index 0000000..6b92e23 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/CollectionArrayList.java @@ -0,0 +1,60 @@ +/**
+ * 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.collection;
+
+import java.util.ArrayList;
+
+import org.cristalise.kernel.utils.CastorArrayList;
+
+
+/**
+ * A bundle of Collections. Used for storage and export/import using XML
+ * persistency via Castor, and to set up an Item's initial collections during
+ * initialization.
+ *
+ */
+public class CollectionArrayList extends CastorArrayList<Collection<? extends CollectionMember>> {
+ public CollectionArrayList()
+ {
+ super();
+ }
+
+ public CollectionArrayList(ArrayList<Collection<? extends CollectionMember>> aList)
+ {
+ super();
+ for (Collection<? extends CollectionMember> coll : aList) {
+ put(coll);
+ }
+ }
+
+ /** This put method overwrites any collections with the same name already in
+ * the list.
+ */
+ public void put(Collection<? extends CollectionMember> c) {
+ for (Collection<? extends CollectionMember> thisColl : list) {
+ if (thisColl.getName().equals(c.getName())) {
+ list.remove(thisColl);
+ break;
+ }
+ }
+ list.add(c);
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/collection/CollectionDescription.java b/src/main/java/org/cristalise/kernel/collection/CollectionDescription.java new file mode 100644 index 0000000..87a97c6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/CollectionDescription.java @@ -0,0 +1,41 @@ +/**
+ * 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.collection;
+
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.entity.C2KLocalObject;
+
+
+/**
+ * A collection that can be instantiated. Collection descriptions link Item
+ * descriptions together, which constrains membership of their instance.
+ *
+ */
+public interface CollectionDescription<E extends CollectionMember> extends C2KLocalObject {
+
+ /**
+ * Create a new instance of this collection.
+ * @return a new collection instance
+ * @throws ObjectNotFoundException When an essential piece of description
+ * data, such as a child Item PropertyDescription outcome, doesn't exist.
+ */
+ public Collection<E> newInstance() throws ObjectNotFoundException;
+}
diff --git a/src/main/java/org/cristalise/kernel/collection/CollectionMember.java b/src/main/java/org/cristalise/kernel/collection/CollectionMember.java new file mode 100644 index 0000000..3a0b642 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/CollectionMember.java @@ -0,0 +1,99 @@ +/**
+ * 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.collection;
+
+import org.cristalise.kernel.common.InvalidCollectionModification;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.entity.proxy.ItemProxy;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.utils.CastorHashMap;
+
+
+/**
+ * CollectionMembers are pointers to individual Items in a collection. Under
+ * certain circumstances they may be empty, or they can be created and destroyed
+ * as required. They can hold properties containing annotations about the link,
+ * including information on the typing of the Item they should point to.
+ * Properties that dictate type information are specified in the ClassProps, and
+ * assignment of an Item will fail if those member properties do not match the
+ * Property values of the Item attempting to be assigned, throwing a
+ * {@link MembershipException} detailing the mismatches.
+ *
+ */
+
+public interface CollectionMember {
+
+ /**
+ * Returns the current assigned ItemPath
+ * @return the ItemPath, null if empty
+ */
+ public ItemPath getItemPath();
+
+ /**
+ * Returns the UUID of the currently assigned Item
+ * @return
+ */
+ public String getChildUUID();
+
+ /**
+ * Assign the given item to the slot, if it fits
+ *
+ * @param itemPath The item to assign
+ * @throws MembershipException When the Item Properties don't match the
+ * typing specification in ClassProps and Properties
+ * @throws InvalidCollectionModification
+ */
+ public void assignItem(ItemPath itemPath) throws InvalidCollectionModification;
+
+ /**
+ * De-assign the slot, leaving it empty.
+ */
+ public void clearItem();
+
+ /**
+ * Resolve the Item currently assigned
+ * @return the ItemProxy of the assigned Item
+ * @throws ObjectNotFoundException When empty
+ */
+ public ItemProxy resolveItem() throws ObjectNotFoundException;
+
+ /**
+ * Get the integer slot ID, as generated by the parent Collection
+ * @return ID
+ */
+ public int getID();
+
+ /**
+ * Gets the member properties.
+ * @return CastorHashMap
+ */
+ public CastorHashMap getProperties();
+
+ /**
+ * Gets the class properties, which specify type information in child Items.
+ * On instantiation from a CollectionDescription, the ClassProps are
+ * generated from the PropertyDescriptions which have the isClassIdentifier
+ * boolean set to true.
+ *
+ * @return Comma-separated list of property names that relate to Item type
+ */
+ public String getClassProps();
+}
diff --git a/src/main/java/org/cristalise/kernel/collection/CollectionMemberList.java b/src/main/java/org/cristalise/kernel/collection/CollectionMemberList.java new file mode 100644 index 0000000..0d9c591 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/CollectionMemberList.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
+ */
+package org.cristalise.kernel.collection;
+
+import org.cristalise.kernel.utils.CastorArrayList;
+
+/**
+ * A list of CollectionMembers, used internally in the Collection for XML
+ * marshalling convenience.
+ * *
+ * @param <E> The CollectionMember implementation stored.
+ */
+public class CollectionMemberList<E extends CollectionMember> extends CastorArrayList<E>
+{
+
+ public CollectionMemberList()
+ {
+ super();
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/collection/Dependency.java b/src/main/java/org/cristalise/kernel/collection/Dependency.java new file mode 100644 index 0000000..1641756 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/Dependency.java @@ -0,0 +1,147 @@ +/**
+ * 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.collection;
+
+
+import org.cristalise.kernel.common.InvalidCollectionModification;
+import org.cristalise.kernel.common.ObjectAlreadyExistsException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.utils.CastorHashMap;
+import org.cristalise.kernel.utils.KeyValuePair;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**
+ * A Collection implementation that contains a variable number of members of the
+ * same type, like a variable-length array. CollectionMembers are created and
+ * destroyed as needed. A Dependency never contains empty slots, nor duplicated
+ * members.
+ *
+ * <p>ClassProps are stored at the collection level and duplicated in each slot.
+ * Slots may still have their own individual properties annotating their link.
+ *
+ * Predefined steps managing Dependencies:
+ *
+ * <ul>
+ * <li>
+ */
+public class Dependency extends Collection<DependencyMember>
+{
+
+ protected CastorHashMap mProperties = new CastorHashMap();
+ protected String mClassProps = "";
+
+ public Dependency()
+ {
+ setName("Dependency");
+ }
+
+ public Dependency(String name)
+ {
+ setName(name);
+ }
+
+ public CastorHashMap getProperties() {
+ return mProperties;
+ }
+
+ public void setProperties(CastorHashMap props) {
+ mProperties = props;
+ }
+
+ public KeyValuePair[] getKeyValuePairs()
+ {
+ return mProperties.getKeyValuePairs();
+ }
+ public void setKeyValuePairs(KeyValuePair[] pairs)
+ {
+ mProperties.setKeyValuePairs(pairs);
+ }
+
+ public void setClassProps(String classProps) {
+ this.mClassProps = classProps;
+ }
+
+ public String getClassProps() {
+ return mClassProps;
+ }
+
+ public DependencyMember addMember(ItemPath itemPath) throws InvalidCollectionModification, ObjectAlreadyExistsException {
+ if (contains(itemPath)) throw new ObjectAlreadyExistsException("Item "+itemPath+" already exists in Dependency "+getName());
+ // create member object
+ DependencyMember depMember = new DependencyMember();
+ depMember.setID(getCounter());
+ depMember.setProperties((CastorHashMap)mProperties.clone());
+ depMember.setClassProps(mClassProps);
+
+ // assign entity
+ depMember.assignItem(itemPath);
+ mMembers.list.add(depMember);
+ Logger.msg(8, "Dependency::addMember(" + itemPath + ") added to children.");
+ return depMember;
+ }
+
+ @Override
+ public DependencyMember addMember(ItemPath itemPath, CastorHashMap props, String classProps)
+ throws InvalidCollectionModification, ObjectAlreadyExistsException
+ {
+ if (contains(itemPath)) throw new ObjectAlreadyExistsException("Item "+itemPath+" already exists in Dependency "+getName());
+ if (classProps != null && !classProps.equals(mClassProps))
+ throw new InvalidCollectionModification("Cannot change classProps in dependency member");
+ DependencyMember depMember = new DependencyMember();
+ depMember.setID(getCounter());
+
+ // merge props
+ CastorHashMap newProps = new CastorHashMap();
+ for (Object name : props.keySet()) {
+ String key = (String)name;
+ newProps.put(key, props.get(key));
+
+ }
+ // class props override local
+ for (Object name : mProperties.keySet()) {
+ String key = (String)name;
+ newProps.put(key, mProperties.get(key));
+
+ }
+ depMember.setProperties(newProps);
+ depMember.setClassProps(mClassProps);
+
+ // assign entity
+ depMember.assignItem(itemPath);
+ mMembers.list.add(depMember);
+ Logger.msg(8, "Dependency::addMember(" + itemPath + ") added to children.");
+ return depMember;
+ }
+
+ @Override
+ public void removeMember(int memberId) throws ObjectNotFoundException {
+ for (DependencyMember element : mMembers.list) {
+ if (element.getID() == memberId) {
+ mMembers.list.remove(element);
+ return;
+ }
+ }
+ throw new ObjectNotFoundException("Member "+memberId+" not found");
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/collection/DependencyDescription.java b/src/main/java/org/cristalise/kernel/collection/DependencyDescription.java new file mode 100644 index 0000000..9c02245 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/DependencyDescription.java @@ -0,0 +1,79 @@ +/**
+ * 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.collection;
+
+import org.cristalise.kernel.common.InvalidCollectionModification;
+import org.cristalise.kernel.common.ObjectAlreadyExistsException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.property.PropertyDescriptionList;
+import org.cristalise.kernel.property.PropertyUtility;
+import org.cristalise.kernel.utils.CastorHashMap;
+
+
+public class DependencyDescription extends Dependency implements CollectionDescription<DependencyMember>{
+
+ public DependencyDescription()
+ {
+ setName("DependencyDescription");
+ }
+
+ public DependencyDescription(String name)
+ {
+ setName(name);
+ }
+
+ @Override
+ public Collection<DependencyMember> newInstance() throws ObjectNotFoundException{
+ String depName = getName().replaceFirst("\'$", ""); // HACK: Knock the special 'prime' off the end for the case of descriptions of descriptions
+ Dependency newDep = new Dependency(depName);
+ if (mMembers.list.size() == 1) { // constrain the members based on the property description
+ DependencyMember mem = mMembers.list.get(0);
+ String descVer = getDescVer(mem);
+ PropertyDescriptionList pdList = PropertyUtility.getPropertyDescriptionOutcome(mem.getItemPath(), descVer);
+ if (pdList!=null) {
+ newDep.setProperties(PropertyUtility.createProperty(pdList));
+ newDep.setClassProps(pdList.getClassProps());
+ }
+ }
+ return newDep;
+ }
+
+
+ @Override
+ public DependencyMember addMember(ItemPath itemPath) throws InvalidCollectionModification, ObjectAlreadyExistsException {
+ checkMembership();
+ return super.addMember(itemPath);
+ }
+
+ @Override
+ public DependencyMember addMember(ItemPath itemPath, CastorHashMap props, String classProps)
+ throws InvalidCollectionModification, ObjectAlreadyExistsException {
+ checkMembership();
+ return super.addMember(itemPath, props, classProps);
+ }
+
+ public void checkMembership() throws InvalidCollectionModification {
+ if (mMembers.list.size() > 0)
+ throw new InvalidCollectionModification("Dependency descriptions may not have more than one member.");
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/collection/DependencyMember.java b/src/main/java/org/cristalise/kernel/collection/DependencyMember.java new file mode 100644 index 0000000..e631113 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/DependencyMember.java @@ -0,0 +1,165 @@ +/**
+ * 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.collection;
+
+import java.util.StringTokenizer;
+
+import org.cristalise.kernel.common.InvalidCollectionModification;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.entity.proxy.ItemProxy;
+import org.cristalise.kernel.lookup.InvalidItemPathException;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.property.Property;
+import org.cristalise.kernel.utils.CastorHashMap;
+import org.cristalise.kernel.utils.KeyValuePair;
+import org.cristalise.kernel.utils.Logger;
+
+
+
+/**
+* @version $Revision: 1.10 $ $Date: 2004/10/21 08:02:23 $
+* @author $Author: abranson $
+*/
+
+
+public class DependencyMember implements CollectionMember
+{
+
+ private ItemPath mItemPath = null;
+ private ItemProxy mItem = null;
+ private int mId = -1;
+ private CastorHashMap mProperties = null;
+ private String mClassProps;
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public DependencyMember()
+ {
+ mProperties = new CastorHashMap();
+ }
+
+ @Override
+ public ItemPath getItemPath()
+ {
+ return mItemPath;
+ }
+
+ public void setProperties(CastorHashMap props)
+ {
+ mProperties = props;
+ }
+
+ @Override
+ public CastorHashMap getProperties()
+ {
+ return mProperties;
+ }
+
+ public KeyValuePair[] getKeyValuePairs()
+ {
+ return mProperties.getKeyValuePairs();
+ }
+ public void setKeyValuePairs(KeyValuePair[] pairs)
+ {
+ mProperties.setKeyValuePairs(pairs);
+ }
+
+ @Override
+ public int getID() {
+ return mId;
+ }
+
+ public void setID(int id) {
+ mId = id;
+ }
+
+ public void setClassProps(String props)
+ {
+ mClassProps = props;
+ }
+
+ @Override
+ public String getClassProps()
+ {
+ return mClassProps;
+ }
+
+ @Override
+ public void assignItem(ItemPath itemPath) throws InvalidCollectionModification
+ {
+ if (itemPath != null) {
+ if (mClassProps == null || getProperties() == null)
+ throw new InvalidCollectionModification("ClassProps not yet set. Cannot check membership validity.");
+
+ //for each mandatory prop check if its in the member property and has the matching value
+ StringTokenizer sub = new StringTokenizer(mClassProps, ",");
+ while (sub.hasMoreTokens())
+ {
+ String aClassProp = sub.nextToken();
+ try {
+ String memberValue = (String)getProperties().get(aClassProp);
+ Property ItemProperty = (Property)Gateway.getStorage().get(itemPath, ClusterStorage.PROPERTY+"/"+aClassProp, null);
+ if (ItemProperty == null)
+ throw new InvalidCollectionModification("Property "+aClassProp+ " does not exist for item " + itemPath );
+ if (!ItemProperty.getValue().equalsIgnoreCase(memberValue))
+ throw new InvalidCollectionModification("DependencyMember::checkProperty() Values of mandatory prop "+aClassProp+" do not match " + ItemProperty.getValue()+"!="+memberValue);
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ throw new InvalidCollectionModification("Error checking properties");
+ }
+ }
+ }
+
+ mItemPath = itemPath;
+ mItem = null;
+ }
+
+ @Override
+ public void clearItem() {
+ mItemPath = null;
+ mItem = null;
+ }
+
+ @Override
+ public ItemProxy resolveItem() throws ObjectNotFoundException {
+ if (mItem == null && mItemPath != null)
+ mItem = Gateway.getProxyManager().getProxy(mItemPath);
+ return mItem;
+ }
+
+ public void setChildUUID(String uuid) throws InvalidCollectionModification, InvalidItemPathException {
+ mItemPath = new ItemPath(uuid);
+ }
+
+
+ @Override
+ public String getChildUUID() {
+ return mItemPath.getUUID().toString();
+ }
+
+
+}
diff --git a/src/main/java/org/cristalise/kernel/collection/package-info.java b/src/main/java/org/cristalise/kernel/collection/package-info.java new file mode 100644 index 0000000..ec01be2 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/collection/package-info.java @@ -0,0 +1,27 @@ +/**
+ * 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
+ */
+/**
+ * Collections are Item local objects that reference other Items.
+ *
+ * @see Collection
+ */
+
+package org.cristalise.kernel.collection;
\ No newline at end of file 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 diff --git a/src/main/java/org/cristalise/kernel/events/Event.java b/src/main/java/org/cristalise/kernel/events/Event.java new file mode 100644 index 0000000..192685f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/events/Event.java @@ -0,0 +1,369 @@ +/**
+ * 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.events;
+
+import java.util.Calendar;
+
+import org.cristalise.kernel.common.GTimeStamp;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.InvalidItemPathException;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+
+
+
+/**
+ * The data structure of events, which are passed over the event service.
+ *
+ * Events are incrementaly numbered objects maintained by the History.
+ *
+ * @version $Revision: 1.13 $ $Date: 2004/11/22 09:12:28 $
+ * @author $Author: abranson $
+ */
+public class Event implements C2KLocalObject
+{
+ ItemPath mItemPath; AgentPath mAgentPath;
+ int mOriginState, mTransition, mTargetState;
+ Integer mID, mSchemaVersion, mStateMachineVersion;
+ String mName, mStepName, mStepPath, mStepType, mSchemaName, mStateMachineName, mViewName, mAgentRole;
+ GTimeStamp mTimeStamp;
+
+ public int getOriginState() {
+ return mOriginState;
+ }
+
+ public void setOriginState(int originState) {
+ this.mOriginState = originState;
+ }
+
+ public int getTargetState() {
+ return mTargetState;
+ }
+
+ public void setTargetState(int targetState) {
+ this.mTargetState = targetState;
+ }
+
+ public Integer getStateMachineVersion() {
+ return mStateMachineVersion;
+ }
+
+ public void setStateMachineVersion(Integer stateMachineVersion) {
+ this.mStateMachineVersion = stateMachineVersion;
+ }
+
+ public String getStateMachineName() {
+ return mStateMachineName;
+ }
+
+ public void setStateMachineName(String stateMachineName) {
+ this.mStateMachineName = stateMachineName;
+ }
+
+ public void setID( Integer id ) {
+ mID = id;
+ mName = String.valueOf(id);
+ }
+
+ /**
+ */
+ public void setItemPath( ItemPath itemPath )
+ {
+ mItemPath = itemPath;
+ }
+
+ public void setItemUUID( String uuid ) throws InvalidItemPathException
+ {
+ setItemPath(new ItemPath(uuid));
+ }
+
+ public String getItemUUID() {
+ return getItemPath().getUUID().toString();
+ }
+
+ public void setAgentUUID( String uuid ) throws InvalidItemPathException
+ {
+ if (uuid == null || uuid.length() == 0)
+ mAgentPath = null;
+ else
+ setAgentPath(AgentPath.fromUUIDString(uuid));
+ }
+
+ public String getAgentUUID() {
+ if (mAgentPath != null)
+ return getAgentPath().getUUID().toString();
+ else
+ return null;
+ }
+
+ /**
+ * Set the Event Name, in parameter is a String
+ */
+ @Override
+ public void setName(String name)
+ {
+ mName = name;
+ try {
+ mID = Integer.parseInt(name);
+ } catch (NumberFormatException ex) {
+ mID = -1;
+ }
+ }
+
+ /**
+ * Set the StepPath of the Event, in parameter is a String
+ */
+ public void setStepName(String name)
+ {
+ mStepName = name;
+ }
+
+ /**
+ * Set the StepPath of the Event, in parameter is a String
+ */
+ public void setStepPath(String path)
+ {
+ mStepPath = path;
+ }
+
+ /**
+ * Set the StepType of the Event, in parameter is a String
+ */
+ public void setStepType(String type)
+ {
+ mStepType = type;
+ }
+
+ /**
+ * @param viewName the viewName to set
+ */
+ public void setViewName(String viewName) {
+ this.mViewName = viewName;
+ }
+
+ /**
+ * Set the AgentInfo in the Event, in parameter is an AgentInfo
+ */
+ public void setAgentPath(AgentPath agentPath)
+ {
+ mAgentPath = agentPath;
+ }
+
+ public void setAgentRole(String agentRole)
+ {
+ mAgentRole = agentRole;
+ }
+
+ /**
+ * Set the TimeStamp in the Event, in parameter is an GTimeStamp
+ */
+ public void setTimeStamp(GTimeStamp inTimeStamp)
+ {
+ mTimeStamp = inTimeStamp;
+ }
+
+
+ /**
+ * Return the Event's ID
+ */
+ public Integer getID()
+ {
+ return mID;
+ }
+
+ /**
+ */
+ public ItemPath getItemPath()
+ {
+ return mItemPath;
+ }
+
+ /**
+ * Return the Event Name
+ */
+ @Override
+ public String getName()
+ {
+ return mName;
+ }
+
+ /**
+ * Return the StepPath of the Event.
+ */
+ public String getStepName()
+ {
+ return mStepName;
+ }
+
+ /**
+ * Return the StepPath of the Event.
+ */
+ public String getStepPath()
+ {
+ return mStepPath;
+ }
+
+ /**
+ * Return the StepPath of the Event.
+ */
+ public String getStepType()
+ {
+ return mStepType;
+ }
+
+ /**
+ * @return the mViewName
+ */
+ public String getViewName() {
+ return mViewName;
+ }
+
+ /**
+ * Return the AgentInfo of the Event.
+ */
+ public AgentPath getAgentPath()
+ {
+ return mAgentPath;
+ }
+
+ public String getAgentRole()
+ {
+ return mAgentRole;
+ }
+
+ /**
+ * Return the Event's TimeStamp.
+ */
+ public GTimeStamp getTimeStamp()
+ {
+ return mTimeStamp;
+ }
+
+ /**
+ * Return the TimeStamp in a form that will
+ * convert nicely to a String
+ * YYYY-MM-DD HH:MI:SS
+ */
+ public String getTimeString()
+ {
+ return Event.timeToString(mTimeStamp);
+ }
+
+ public static String timeToString(GTimeStamp timeStamp) {
+ StringBuffer time = new StringBuffer().append(timeStamp.mYear).append("-");
+
+ if (timeStamp.mMonth<10) time.append("0");
+ time.append(timeStamp.mMonth).append("-");
+
+ if (timeStamp.mDay<10) time.append("0");
+ time.append(timeStamp.mDay).append(" ");
+
+ if (timeStamp.mHour<10) time.append("0");
+ time.append(timeStamp.mHour).append(":");
+
+ if (timeStamp.mMinute<10) time.append("0");
+ time.append(timeStamp.mMinute).append(":");
+
+ if (timeStamp.mSecond<10) time.append("0");
+ time.append(timeStamp.mSecond);
+
+ return time.toString();
+ }
+
+ public void setTimeString(String time) throws InvalidDataException
+ {
+ if (time.length() == 19)
+ mTimeStamp = new GTimeStamp(
+ Integer.parseInt(time.substring(0,4)),
+ Integer.parseInt(time.substring(5,7)),
+ Integer.parseInt(time.substring(8,10)),
+ Integer.parseInt(time.substring(11,13)),
+ Integer.parseInt(time.substring(14,16)),
+ Integer.parseInt(time.substring(17,19)),
+ Calendar.getInstance().get(Calendar.ZONE_OFFSET));
+ else if (time.length() == 14) // support for some sql formats
+ mTimeStamp = new GTimeStamp(
+ Integer.parseInt(time.substring(0,4)),
+ Integer.parseInt(time.substring(4,6)),
+ Integer.parseInt(time.substring(6,8)),
+ Integer.parseInt(time.substring(8,10)),
+ Integer.parseInt(time.substring(10,12)),
+ Integer.parseInt(time.substring(12,14)),
+ Calendar.getInstance().get(Calendar.ZONE_OFFSET));
+ else
+ throw new InvalidDataException("Unknown time format: "+time);
+ }
+
+
+
+ static public GTimeStamp getGMT()
+ {
+ java.util.Calendar now = Calendar.getInstance();
+
+ return new GTimeStamp( now.get(Calendar.YEAR),
+ now.get(Calendar.MONTH)+1,
+ now.get(Calendar.DAY_OF_MONTH),
+ now.get(Calendar.HOUR_OF_DAY),
+ now.get(Calendar.MINUTE),
+ now.get(Calendar.SECOND),
+ now.get(Calendar.ZONE_OFFSET) );
+ }
+ /**
+ * @see org.cristalise.kernel.entity.C2KLocalObject#getClusterType()
+ */
+ @Override
+ public String getClusterType() {
+ return ClusterStorage.HISTORY;
+ }
+
+ /**
+ * @return
+ */
+ public int getTransition() {
+ return mTransition;
+ }
+
+ /**
+ * @param i
+ */
+ public void setTransition(int i) {
+ mTransition = i;
+ }
+
+ public Integer getSchemaVersion() {
+ return mSchemaVersion;
+ }
+
+ public void setSchemaVersion(Integer schemaVersion) {
+ this.mSchemaVersion = schemaVersion;
+ }
+
+ public String getSchemaName() {
+ return mSchemaName;
+ }
+
+ public void setSchemaName(String schemaName) {
+ this.mSchemaName = schemaName;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/events/History.java b/src/main/java/org/cristalise/kernel/events/History.java new file mode 100644 index 0000000..bca0fa8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/events/History.java @@ -0,0 +1,152 @@ +/**
+ * 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.events;
+
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.lifecycle.instance.stateMachine.Transition;
+import org.cristalise.kernel.lookup.AgentPath;
+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 Andrew Branson
+ *
+ * $Revision: 1.20 $
+ * $Date: 2004/07/21 09:55:11 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ */
+
+public class History extends RemoteMap<Event> {
+
+ int lastID = -1;
+
+ public History(ItemPath itemPath, Object locker) {
+ super(itemPath, ClusterStorage.HISTORY, locker);
+ }
+ public Event addEvent(AgentPath agentPath, String agentRole,
+ String stepName,
+ String stepPath,
+ String stepType,
+ String stateMachineName,
+ Integer stateMachineVersion,
+ Transition transition) {
+ return addEvent(agentPath, agentRole, stepName, stepPath, stepType, null, null, stateMachineName, stateMachineVersion, transition, null);
+ }
+
+ public Event addEvent(AgentPath agentPath, String agentRole,
+ String stepName,
+ String stepPath,
+ String stepType,
+ String schemaName,
+ Integer schemaVersion,
+ String stateMachineName,
+ Integer stateMachineVersion,
+ Transition transition,
+ String viewName) {
+ Logger.msg(7, "History.addEvent() - creating new event for "+transition.getName()+" on "+stepName+" in "+mItemPath);
+ Event newEvent = new Event();
+ newEvent.setItemPath(mItemPath);
+ newEvent.setAgentPath(agentPath);
+ newEvent.setAgentRole(agentRole);
+ newEvent.setStepName(stepName);
+ newEvent.setStepPath(stepPath);
+ newEvent.setStepType(stepType);
+ newEvent.setSchemaName(schemaName);
+ newEvent.setSchemaVersion(schemaVersion);
+ newEvent.setViewName(viewName);
+ newEvent.setOriginState(transition.getOriginStateId());
+ newEvent.setTargetState(transition.getTargetStateId());
+ newEvent.setTransition(transition.getId());
+ newEvent.setStateMachineName(stateMachineName);
+ newEvent.setStateMachineVersion(stateMachineVersion);
+ newEvent.setTimeStamp(Event.getGMT());
+ return storeNewEvent(newEvent);
+ }
+
+ public Event addEvent(AgentPath agentPath, String agentRole,
+ String stepName,
+ String stepPath,
+ String stepType,
+ String stateMachineName,
+ Integer stateMachineVersion,
+ Transition transition,
+ String timeString) throws InvalidDataException {
+ return addEvent(agentPath, agentRole, stepName, stepPath, stepType, null, null, stateMachineName, stateMachineVersion, transition, null, timeString);
+ }
+
+ public Event addEvent(AgentPath agentPath, String agentRole,
+ String stepName,
+ String stepPath,
+ String stepType,
+ String schemaName,
+ Integer schemaVersion,
+ String stateMachineName,
+ Integer stateMachineVersion,
+ Transition transition,
+ String viewName,
+ String timeString) throws InvalidDataException {
+ Logger.msg(7, "History.addEvent() - creating new event for "+transition.getName()+" on "+stepName+" in "+mItemPath);
+ Event newEvent = new Event();
+ newEvent.setItemPath(mItemPath);
+ newEvent.setAgentPath(agentPath);
+ newEvent.setAgentRole(agentRole);
+ newEvent.setStepName(stepName);
+ newEvent.setStepPath(stepPath);
+ newEvent.setStepType(stepType);
+ newEvent.setSchemaName(schemaName);
+ newEvent.setSchemaVersion(schemaVersion);
+ newEvent.setViewName(viewName);
+ newEvent.setOriginState(transition.getOriginStateId());
+ newEvent.setTargetState(transition.getTargetStateId());
+ newEvent.setTransition(transition.getId());
+ newEvent.setStateMachineName(stateMachineName);
+ newEvent.setStateMachineVersion(stateMachineVersion);
+ newEvent.setTimeString(timeString);
+ return storeNewEvent(newEvent);
+ }
+
+ private Event storeNewEvent(Event newEvent) {
+ synchronized (this) {
+ int newEventID = getLastId()+1;
+ newEvent.setID(newEventID);
+ put(newEvent.getName(), newEvent);
+ lastID = newEventID;
+ return newEvent;
+ }
+ }
+
+ public Event getEvent(int id) {
+ return get(String.valueOf(id));
+ }
+
+ @Override
+ public Event remove(Object key) {
+ // forbidden
+ return null;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/events/package-info.java b/src/main/java/org/cristalise/kernel/events/package-info.java new file mode 100644 index 0000000..3e3c37d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/events/package-info.java @@ -0,0 +1,29 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+/**
+ * Events are generated and stored whenever a step in an Item's lifecycle
+ * changes state, and provide a full record of what was done, when, and by whom.
+ *
+ * <p>The History object is an instance of {@link RemoteMap} which provides a
+ * live view onto the Events of an Item.
+ */
+
+package org.cristalise.kernel.events;
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/graph/event/ClearedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/ClearedEvent.java new file mode 100644 index 0000000..8589637 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/ClearedEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class ClearedEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/EdgeRemovedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/EdgeRemovedEvent.java new file mode 100644 index 0000000..bac5715 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/EdgeRemovedEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class EdgeRemovedEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/EdgesChangedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/EdgesChangedEvent.java new file mode 100644 index 0000000..c3cfe7a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/EdgesChangedEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class EdgesChangedEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/EntireModelChangedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/EntireModelChangedEvent.java new file mode 100644 index 0000000..1ea5fa4 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/EntireModelChangedEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class EntireModelChangedEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/ForcedNotifyEvent.java b/src/main/java/org/cristalise/kernel/graph/event/ForcedNotifyEvent.java new file mode 100644 index 0000000..e2801f2 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/ForcedNotifyEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class ForcedNotifyEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/GraphModelEvent.java b/src/main/java/org/cristalise/kernel/graph/event/GraphModelEvent.java new file mode 100644 index 0000000..cc066f8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/GraphModelEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public abstract class GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/GraphModelResizedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/GraphModelResizedEvent.java new file mode 100644 index 0000000..a4de89d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/GraphModelResizedEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class GraphModelResizedEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/NewEdgeEndPointChangedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/NewEdgeEndPointChangedEvent.java new file mode 100644 index 0000000..42a2507 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/NewEdgeEndPointChangedEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class NewEdgeEndPointChangedEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/StartVertexIdChangedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/StartVertexIdChangedEvent.java new file mode 100644 index 0000000..7d3d7e3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/StartVertexIdChangedEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class StartVertexIdChangedEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/VertexAddedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/VertexAddedEvent.java new file mode 100644 index 0000000..7f4fcbe --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/VertexAddedEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class VertexAddedEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/VertexCreatedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/VertexCreatedEvent.java new file mode 100644 index 0000000..e0f0eee --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/VertexCreatedEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class VertexCreatedEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/VertexMovedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/VertexMovedEvent.java new file mode 100644 index 0000000..9e5d8a8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/VertexMovedEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class VertexMovedEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/VertexRemovedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/VertexRemovedEvent.java new file mode 100644 index 0000000..29f4367 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/VertexRemovedEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class VertexRemovedEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/event/VerticesChangedEvent.java b/src/main/java/org/cristalise/kernel/graph/event/VerticesChangedEvent.java new file mode 100644 index 0000000..68cc9f1 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/event/VerticesChangedEvent.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.event;
+
+
+public class VerticesChangedEvent extends GraphModelEvent
+{
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/layout/DefaultGraphLayoutGenerator.java b/src/main/java/org/cristalise/kernel/graph/layout/DefaultGraphLayoutGenerator.java new file mode 100644 index 0000000..097c554 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/layout/DefaultGraphLayoutGenerator.java @@ -0,0 +1,139 @@ +/**
+ * 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.graph.layout;
+
+import java.util.Vector;
+
+import org.cristalise.kernel.graph.model.DirectedEdge;
+import org.cristalise.kernel.graph.model.GraphModel;
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.graph.model.Vertex;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class DefaultGraphLayoutGenerator {
+ private static int mTopMargin = 100;
+ private static int mLeftMargin = 100;
+ private static int mHorzGap = 180;
+ private static int mVertGap = 100;
+
+ private DefaultGraphLayoutGenerator() {
+ }
+
+ public static void layoutGraph(GraphModel graphModel) {
+ Vertex start = graphModel.getStartVertex();
+ Vector<Vector<Vertex>> rowVector = new Vector<Vector<Vertex>>(10, 10);
+ int[] midPoints = null;
+ int valueOfLargestMidPoint = 0;
+ if (start == null) {
+ Logger.msg(1,"Error graph must have a starting vertex to be layed out");
+ return;
+ }
+ graphModel.clearTags(start);
+ visitVertex(graphModel, start, 0, rowVector, start);
+ midPoints = new int[rowVector.size()];
+ valueOfLargestMidPoint = calculateRowMidPoints(rowVector, midPoints, valueOfLargestMidPoint);
+ fillInVertexLocations(graphModel, rowVector, valueOfLargestMidPoint, midPoints);
+ fillInEdgeLocations(graphModel);
+ graphModel.forceNotify();
+ }
+
+ private static void visitVertex(GraphModel graphModel, Vertex vertex, int rowIndex, Vector<Vector<Vertex>> rowVector, Object tag) {
+ int i = 0;
+ Vertex[] children = graphModel.getOutVertices(vertex);
+ vertex.setTag(tag);
+ addVertexToRow(vertex, rowIndex, rowVector);
+ for (i = 0; i < children.length; i++) {
+ if (!(children[i].hasTag(tag))) {
+ visitVertex(graphModel, children[i], rowIndex + 1, rowVector, tag);
+ }
+ }
+ }
+
+ private static void addVertexToRow(Vertex vertex, int rowIndex, Vector<Vector<Vertex>> rowVector) {
+ Vector<Vertex> rowsVertices = null;
+ // If there is no vector of vertices already created for this row,
+ // then create one
+ if (rowVector.size() == rowIndex) {
+ rowVector.add(new Vector<Vertex>(10, 10));
+ }
+ // Add the vertex to the row's vector of vertices
+ rowsVertices = rowVector.elementAt(rowIndex);
+ rowsVertices.add(vertex);
+ }
+
+ private static int calculateRowMidPoints(Vector<Vector<Vertex>> rowVector, int[] midPoints, int valueOfLargestMidPoint) {
+ Vector<Vertex> rowsVertices = null;
+ int newValueOfLargestMidPoint = valueOfLargestMidPoint;
+ int rowsWidth = 0;
+ int i = 0;
+ for (i = 0; i < midPoints.length; i++) {
+ rowsVertices = rowVector.elementAt(i);
+ rowsWidth = mHorzGap * (rowsVertices.size() - 1);
+ midPoints[i] = rowsWidth / 2;
+ if (midPoints[i] > newValueOfLargestMidPoint) {
+ newValueOfLargestMidPoint = midPoints[i];
+ }
+ }
+ return newValueOfLargestMidPoint;
+ }
+
+ private static void fillInVertexLocations(GraphModel graphModel, Vector<Vector<Vertex>> rowVector,
+ int valueOfLargestMidPoint, int[] midPoints) {
+ Vector<Vertex> rowsVertices = null;
+ Vertex vertex = null;
+ int rowIndex = 0;
+ int column = 0;
+ int rowsLeftMargin = 0;
+ GraphPoint point = new GraphPoint(0, 0);
+ for (rowIndex = 0; rowIndex < rowVector.size(); rowIndex++) {
+ rowsVertices = rowVector.elementAt(rowIndex);
+ rowsLeftMargin = mLeftMargin + valueOfLargestMidPoint - midPoints[rowIndex];
+ for (column = 0; column < rowsVertices.size(); column++) {
+ vertex = rowsVertices.elementAt(column);
+ point.x = rowsLeftMargin + column * mHorzGap;
+ point.y = mTopMargin + rowIndex * mVertGap;
+ vertex.moveAbsolute(point);
+ graphModel.checkSize(vertex);
+ }
+ }
+ }
+
+ private static void fillInEdgeLocations(GraphModel graphModel) {
+ Vertex[] vertices = graphModel.getVertices();
+ GraphPoint centrePoint = null;
+ DirectedEdge[] inEdges = null;
+ DirectedEdge[] outEdges = null;
+ int i = 0;
+ int j = 0;
+ for (i = 0; i < vertices.length; i++) {
+ centrePoint = vertices[i].getCentrePoint();
+ inEdges = graphModel.getInEdges(vertices[i]);
+ outEdges = graphModel.getOutEdges(vertices[i]);
+ for (j = 0; j < inEdges.length; j++) {
+ inEdges[j].setTerminusPoint(centrePoint);
+ }
+ for (j = 0; j < outEdges.length; j++) {
+ outEdges[j].setOriginPoint(centrePoint);
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/model/DirectedEdge.java b/src/main/java/org/cristalise/kernel/graph/model/DirectedEdge.java new file mode 100644 index 0000000..e384131 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/DirectedEdge.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.graph.model;
+
+
+
+
+public abstract class DirectedEdge
+{
+ // Persistent data
+ private int mId = -1;
+ private GraphPoint mOriginPoint = new GraphPoint(0, 0);
+ private GraphPoint mTerminusPoint = new GraphPoint(0, 0);
+ private int mOriginVertexId = -1;
+ private int mTerminusVertexId = -1;
+
+
+ public void setID(int id)
+ {
+ mId = id;
+ }
+
+
+ public int getID()
+ {
+ return mId;
+ }
+
+
+ public void setOriginPoint(GraphPoint p)
+ {
+ mOriginPoint = p;
+ }
+
+
+ public GraphPoint getOriginPoint()
+ {
+ return mOriginPoint;
+ }
+
+
+ public void setTerminusPoint(GraphPoint p)
+ {
+ mTerminusPoint = p;
+ }
+
+
+ public GraphPoint getTerminusPoint()
+ {
+ return mTerminusPoint;
+ }
+
+
+ public boolean containsPoint(GraphPoint p)
+ {
+ int midX = mOriginPoint.x + (mTerminusPoint.x - mOriginPoint.x)/2;
+ int midY = mOriginPoint.y + (mTerminusPoint.y - mOriginPoint.y)/2;
+ int minX = midX - 10;
+ int minY = midY - 10;
+ int maxX = midX + 10;
+ int maxY = midY + 10;
+
+ return (p.x >= minX) && (p.x <= maxX) && (p.y >= minY) && (p.y <= maxY);
+ }
+
+
+ public void setOriginVertexId(int id)
+ {
+ mOriginVertexId = id;
+ }
+
+
+ public int getOriginVertexId()
+ {
+ return mOriginVertexId;
+ }
+
+
+ public void setTerminusVertexId(int id)
+ {
+ mTerminusVertexId = id;
+ }
+
+
+ public int getTerminusVertexId()
+ {
+ return mTerminusVertexId;
+ }
+
+
+ public void setName(String name)
+ {
+ }
+
+
+ public String getName()
+ {
+ return null;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/model/EdgeFactory.java b/src/main/java/org/cristalise/kernel/graph/model/EdgeFactory.java new file mode 100644 index 0000000..f4c119a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/EdgeFactory.java @@ -0,0 +1,34 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.model;
+
+
+
+public interface EdgeFactory
+{
+ public void create
+ (
+ GraphModelManager graphModelManager,
+ Vertex origin,
+ Vertex terminus,
+ TypeNameAndConstructionInfo typeNameAndConstructionInfo
+ );
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/model/GraphModel.java b/src/main/java/org/cristalise/kernel/graph/model/GraphModel.java new file mode 100644 index 0000000..4ccbece --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/GraphModel.java @@ -0,0 +1,544 @@ +/**
+ * 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.graph.model;
+
+import java.util.Hashtable;
+
+import org.cristalise.kernel.graph.event.ClearedEvent;
+import org.cristalise.kernel.graph.event.EdgeRemovedEvent;
+import org.cristalise.kernel.graph.event.EdgesChangedEvent;
+import org.cristalise.kernel.graph.event.ForcedNotifyEvent;
+import org.cristalise.kernel.graph.event.GraphModelEvent;
+import org.cristalise.kernel.graph.event.GraphModelResizedEvent;
+import org.cristalise.kernel.graph.event.NewEdgeEndPointChangedEvent;
+import org.cristalise.kernel.graph.event.StartVertexIdChangedEvent;
+import org.cristalise.kernel.graph.event.VertexAddedEvent;
+import org.cristalise.kernel.graph.event.VertexCreatedEvent;
+import org.cristalise.kernel.graph.event.VertexMovedEvent;
+import org.cristalise.kernel.graph.event.VertexRemovedEvent;
+import org.cristalise.kernel.graph.event.VerticesChangedEvent;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class GraphModel {
+ /* Persistent data */
+
+ private int mWidth = 0;
+ private int mHeight = 0;
+ private int mNextId = 0;
+ protected int mStartVertexId = -1;
+ protected Hashtable<String, Vertex> mVertexHashtable = new Hashtable<String, Vertex>();
+ protected Hashtable<String, DirectedEdge> mEdgeHashtable = new Hashtable<String, DirectedEdge>();
+ private GraphableVertex mContainingVertex;
+
+ /* Transient data */
+
+ protected transient Vertex mNewEdgeOriginVertex = null;
+ protected transient GraphPoint mNewEdgeEndPoint = null;
+
+ private transient GraphModelManager mManager = null;
+
+ /* External factories */
+
+ private VertexFactory mExternalVertexFactory = null;
+ private EdgeFactory mExternalEdgeFactory = null;
+
+ /* Vertex outline creator */
+
+ private VertexOutlineCreator mVertexOutlineCreator = null;
+
+ /* Notification Events */
+
+ private final ClearedEvent mClearedEvent = new ClearedEvent();
+ private final EdgeRemovedEvent mEdgeRemovedEvent = new EdgeRemovedEvent();
+ private final EdgesChangedEvent mEdgesChangedEvent = new EdgesChangedEvent();
+ private final ForcedNotifyEvent mForcedNotifyEvent = new ForcedNotifyEvent();
+ private final NewEdgeEndPointChangedEvent mNewEdgeEndPointChangedEvent = new NewEdgeEndPointChangedEvent();
+ private final StartVertexIdChangedEvent mStartVertexIdChangedEvent = new StartVertexIdChangedEvent();
+ private final VertexAddedEvent mVertexAddedEvent = new VertexAddedEvent();
+ private final VertexCreatedEvent mVertexCreatedEvent = new VertexCreatedEvent();
+ private final VertexMovedEvent mVertexMovedEvent = new VertexMovedEvent();
+ private final VertexRemovedEvent mVertexRemovedEvent = new VertexRemovedEvent();
+ private final VerticesChangedEvent mVerticesChangedEvent = new VerticesChangedEvent();
+ private final GraphModelResizedEvent mGraphModelResizedEvent = new GraphModelResizedEvent();
+
+ // Calling this constructor does not create a vertex outline creator
+ // which is required by the method addVertexAndCreateId()
+
+ private static int count=0;
+
+ // count instances for debugging
+ private int number;
+
+ public GraphModel() {
+ number=++count;
+
+ }
+
+ public int getNumber() {
+ return number;
+ }
+
+ public void setNextId(int id) {
+ mNextId = id;
+ }
+
+ public int getNextId() {
+ return mNextId;
+ }
+
+ public void setManager(GraphModelManager mgr) {
+ mManager = mgr;
+ }
+
+ public GraphModelManager getManager() {
+ return mManager;
+ }
+
+ public GraphModel(VertexOutlineCreator vertexOutlineCreator) {
+ mVertexOutlineCreator = vertexOutlineCreator;
+ }
+
+ public void setWidth(int width) {
+
+ mWidth = width;
+ }
+
+ public int getWidth() {
+ return mWidth;
+ }
+
+ public void setHeight(int height) {
+
+ mHeight = height;
+ }
+
+ public int getHeight() {
+ return mHeight;
+ }
+
+ public void checkSize(Vertex v) {
+ boolean resized = false;
+ GraphPoint centre = v.getCentrePoint();
+ if (getWidth() < centre.x + v.getWidth()/2 +10 ) {
+ setWidth( centre.x + v.getWidth()/2 +10 );
+ resized = true;
+ }
+
+ if (getHeight() < centre.y + v.getHeight()/2 +10 ) {
+ setHeight(centre.y + v.getHeight()/2 +10 );
+ resized = true;
+ }
+
+ if (resized) {
+ publishEvent(mGraphModelResizedEvent);
+ }
+
+ }
+
+ public void setStartVertexId(int id) {
+ mStartVertexId = id;
+ publishEvent(mStartVertexIdChangedEvent);
+ }
+
+ public int getStartVertexId() {
+ return mStartVertexId;
+ }
+
+ public Vertex getStartVertex() {
+ return resolveVertex(getStartVertexId());
+ }
+
+ /**
+ * @return Returns the mParentVertex.
+ */
+ public GraphableVertex getContainingVertex() {
+ return mContainingVertex;
+ }
+ /**
+ * @param parentVertex The mParentVertex to set.
+ */
+ public void setContainingVertex(GraphableVertex vertex) {
+ mContainingVertex = vertex;
+ }
+
+ public void setVertices(Vertex[] vertices) {
+ mVertexHashtable = new Hashtable<String, Vertex>();
+ for (Vertex vertice : vertices) {
+ mVertexHashtable.put(String.valueOf(vertice.getID()), vertice);
+ checkSize(vertice);
+
+ }
+ publishEvent(mVerticesChangedEvent);
+ }
+
+ public Vertex[] getVertices() {
+ Object[] vertexObjs = mVertexHashtable.values().toArray();
+ Vertex[] vertices = new Vertex[vertexObjs.length];
+ int i = 0;
+ for (i = 0; i < vertices.length; i++) {
+ vertices[i] = (Vertex)vertexObjs[i];
+ }
+ return vertices;
+ }
+
+ public void setEdges(DirectedEdge[] edges) {
+ mEdgeHashtable = new Hashtable<String, DirectedEdge>();
+ for (DirectedEdge edge : edges) {
+ mEdgeHashtable.put(String.valueOf(edge.getID()), edge);
+ }
+ publishEvent(mEdgesChangedEvent);
+ }
+
+ public DirectedEdge[] getEdges() {
+ Object[] edgeObjs = mEdgeHashtable.values().toArray();
+ DirectedEdge[] edges = new DirectedEdge[edgeObjs.length];
+ int i = 0;
+ for (i = 0; i < edges.length; i++) {
+ edges[i] = (DirectedEdge)edgeObjs[i];
+ }
+ return edges;
+ }
+
+ public Vertex getVertexById(int id) {
+ return mVertexHashtable.get(String.valueOf(id));
+ }
+
+
+ public int addEdgeAndCreateId(DirectedEdge e, int originId, int terminusId) {
+ return addEdgeAndCreateId(e, resolveVertex(originId), resolveVertex(terminusId));
+ }
+
+ public int addEdgeAndCreateId(DirectedEdge e, Vertex origin, Vertex terminus) {
+ e.setID(mNextId);
+ e.setOriginVertexId(origin.getID());
+ e.setOriginPoint(origin.getCentrePoint());
+ e.setTerminusVertexId(terminus.getID());
+ e.setTerminusPoint(terminus.getCentrePoint());
+ origin.addOutEdgeId(mNextId);
+ terminus.addInEdgeId(mNextId);
+ mEdgeHashtable.put(String.valueOf(mNextId), e);
+ mNextId++;
+ return mNextId - 1;
+ }
+
+ // Removes an edge, but does not modify the selection
+ public void removeEdge(DirectedEdge e) {
+ Vertex origin = getOrigin(e);
+ Vertex terminus = getTerminus(e);
+ int edgeId = e.getID();
+ // Remove the id of the edge from the origin and terminus vertices
+ origin.removeOutEdgeId(edgeId);
+ terminus.removeInEdgeId(edgeId);
+ // Remove the edge
+ mEdgeHashtable.remove(String.valueOf(e.getID()));
+ publishEvent(mEdgeRemovedEvent);
+ }
+
+ public int addVertexAndCreateId(Vertex v, GraphPoint location) {
+ if (location!= null)
+ {
+ if (mVertexOutlineCreator == null) {
+ Logger.msg(1,"You cannot add a vertex with no outline creator");
+ return -1;
+
+ }
+ mVertexHashtable.put(String.valueOf(mNextId), v);
+ placeVertex(v, location);
+ }
+ v.setID(mNextId);
+ return mNextId++;
+ }
+
+ public void placeVertex(Vertex v, GraphPoint location) {
+ v.setCentrePoint(location);
+ if (mVertexOutlineCreator != null) {
+ mVertexOutlineCreator.setOutline(v);
+ }
+ publishEvent(mVertexAddedEvent);
+ checkSize(v);
+ }
+
+ // Removes a vertex, but does not modify the selection
+ public void removeVertex(Vertex v) {
+ DirectedEdge[] inEdges = getInEdges(v);
+ DirectedEdge[] outEdges = getOutEdges(v);
+ Vertex origin = null;
+ Vertex terminus = null;
+ int edgeId = -1;
+ int i = 0;
+ // For each in edge
+ for (i = 0; i < inEdges.length; i++) {
+ edgeId = inEdges[i].getID();
+ origin = getOrigin(inEdges[i]);
+ // Remove the id of the edge from the origin vertex
+ origin.removeOutEdgeId(edgeId);
+ // Remove the edge
+ mEdgeHashtable.remove(String.valueOf(edgeId));
+ }
+ // Remove all the out edges
+ for (i = 0; i < outEdges.length; i++) {
+ edgeId = outEdges[i].getID();
+ terminus = getTerminus(outEdges[i]);
+ // Remove the id of the edge from the terminus vertex
+ terminus.removeInEdgeId(edgeId);
+ // Remove the edge
+ mEdgeHashtable.remove(String.valueOf(edgeId));
+ }
+ // Remove the vertex
+ mVertexHashtable.remove(String.valueOf(v.getID()));
+ publishEvent(mVertexRemovedEvent);
+ }
+
+ public void moveAbsoluteVertex(Vertex v, GraphPoint p) {
+ // Make sure the new position stays within the graph
+ if (p.x < 0) p.x = 0;
+ if (p.y < 0) p.y = 0;
+ if (p.x > mWidth) p.x = mWidth;
+ if (p.y > mHeight) p.y = mHeight;
+ moveAbsoluteVertexAndConnectingEdges(v, p);
+ publishEvent(mVertexMovedEvent);
+ }
+
+ private void moveAbsoluteVertexAndConnectingEdges(Vertex v, GraphPoint p) {
+ DirectedEdge[] inEdges = getInEdges(v);
+ DirectedEdge[] outEdges = getOutEdges(v);
+ int i = 0;
+ // Move the vertex to the new position
+ v.moveAbsolute(p);
+ // Move the ends of the incoming edges to the new position
+ for (i = 0; i < inEdges.length; i++) {
+ inEdges[i].setTerminusPoint(p);
+ }
+ // Move the ends of the outgoing edges to the new position
+ for (i = 0; i < outEdges.length; i++) {
+ outEdges[i].setOriginPoint(p);
+ }
+ checkSize(v);
+ }
+
+
+
+ public Vertex resolveVertex(int id) {
+ return mVertexHashtable.get(String.valueOf(id));
+ }
+
+ public DirectedEdge resolveEdge(int id) {
+ return mEdgeHashtable.get(String.valueOf(id));
+ }
+
+ public DirectedEdge[] getInEdges(Vertex v) {
+ int[] ids = v.getInEdgeIds();
+ return resolveEdges(ids);
+ }
+
+ public DirectedEdge[] getOutEdges(Vertex v) {
+ int[] ids = v.getOutEdgeIds();
+ return resolveEdges(ids);
+ }
+
+ private DirectedEdge[] resolveEdges(int[] ids) {
+ DirectedEdge[] edges = new DirectedEdge[ids.length];
+ int i = 0;
+ for (i = 0; i < ids.length; i++) {
+ edges[i] = resolveEdge(ids[i]);
+ }
+ return edges;
+ }
+
+ public Vertex getOrigin(DirectedEdge e) {
+ return resolveVertex(e.getOriginVertexId());
+ }
+
+ public Vertex getTerminus(DirectedEdge e) {
+ return resolveVertex(e.getTerminusVertexId());
+ }
+
+ public Vertex[] getInVertices(Vertex v) {
+ DirectedEdge[] inEdges = getInEdges(v);
+ Vertex[] inVertices = new Vertex[inEdges.length];
+ int i = 0;
+ for (i = 0; i < inEdges.length; i++) {
+ inVertices[i] = getOrigin(inEdges[i]);
+ }
+ return inVertices;
+ }
+
+ public Vertex[] getOutVertices(Vertex v) {
+ DirectedEdge[] outEdges = getOutEdges(v);
+ Vertex[] outVertices = new Vertex[outEdges.length];
+ int i = 0;
+ for (i = 0; i < outEdges.length; i++) {
+ outVertices[i] = getTerminus(outEdges[i]);
+ }
+ return outVertices;
+ }
+
+ public DirectedEdge[] getConnectingEdges(int originVertexId, int terminusVertexId) {
+ Vertex origin = resolveVertex(originVertexId);
+ DirectedEdge[] outEdges = null;
+ int numEdgesFound = 0;
+ DirectedEdge[] edgesFound = null;
+ int i = 0;
+ int j = 0;
+ if (origin == null) return null;
+ outEdges = getOutEdges(origin);
+ for (i = 0; i < outEdges.length; i++) {
+ if (outEdges[i].getTerminusVertexId() == terminusVertexId) {
+ numEdgesFound++;
+ }
+ }
+ edgesFound = new DirectedEdge[numEdgesFound];
+ for (i = 0; i < outEdges.length; i++) {
+ if (outEdges[i].getTerminusVertexId() == terminusVertexId) {
+ edgesFound[j] = outEdges[i];
+ j++;
+ }
+ }
+ return edgesFound;
+ }
+
+ public void clearTags(Object tag) {
+ Vertex vertex = null;
+ Object[] vertexObjs = mVertexHashtable.values().toArray();
+ int i = 0;
+ for (i = 0; i < vertexObjs.length; i++) {
+ vertex = (Vertex)vertexObjs[i];
+ vertex.clearTag(tag);
+ }
+ }
+
+ public void forceNotify() {
+ publishEvent(mForcedNotifyEvent);
+ }
+
+ public void clear() {
+ mVertexHashtable = new Hashtable<String, Vertex>();
+ mEdgeHashtable = new Hashtable<String, DirectedEdge>();
+ mStartVertexId = -1;
+ publishEvent(mClearedEvent);
+ }
+
+
+
+ public void setNewEdgeOriginVertex(Vertex v) {
+ mNewEdgeOriginVertex = v;
+ }
+
+ public Vertex getNewEdgeOriginVertex() {
+ return mNewEdgeOriginVertex;
+ }
+
+ public void setNewEdgeEndPoint(GraphPoint p) {
+ mNewEdgeEndPoint = p;
+ publishEvent(mNewEdgeEndPointChangedEvent);
+ }
+
+ public GraphPoint getNewEdgeEndPoint() {
+ return mNewEdgeEndPoint;
+ }
+
+ public void setExternalVertexFactory(VertexFactory factory) {
+ mExternalVertexFactory = factory;
+ }
+
+ public void createVertex(GraphPoint location, TypeNameAndConstructionInfo typeNameAndConstructionInfo) throws Exception {
+ if (mExternalVertexFactory != null) {
+ mExternalVertexFactory.create(mManager, location, typeNameAndConstructionInfo);
+ publishEvent(mVertexCreatedEvent);
+ }
+ }
+
+ private void publishEvent(GraphModelEvent event) {
+ if (mManager!=null)
+ mManager.notifyObservers(event);
+
+ }
+
+ public void setExternalEdgeFactory(EdgeFactory factory) {
+ mExternalEdgeFactory = factory;
+ }
+
+ public void setVertexOutlineCreator(VertexOutlineCreator outlineCreator) {
+ mVertexOutlineCreator = outlineCreator;
+ }
+
+ public void createDirectedEdge(Vertex origin, Vertex terminus, TypeNameAndConstructionInfo typeNameAndConstructionInfo) {
+ if (mExternalEdgeFactory != null) {
+ mExternalEdgeFactory.create(mManager, origin, terminus, typeNameAndConstructionInfo);
+ }
+ }
+
+
+
+ public void resetVertexOutlines() {
+ Vertex[] vertices = getVertices();
+ int i = 0;
+ for (i = 0; i < vertices.length; i++) {
+ mVertexOutlineCreator.setOutline(vertices[i]);
+ }
+ }
+
+ public void setGraphModelCastorData(GraphModelCastorData data) {
+ int i = 0;
+
+ // Create and populate the vertex hashtable
+ mVertexHashtable = new Hashtable<String, Vertex>();
+ for (i = 0; i < data.mVertexImpls.length; i++) {
+ mVertexHashtable.put(String.valueOf(data.mVertexImpls[i].getID()), data.mVertexImpls[i]);
+ checkSize(data.mVertexImpls[i]);
+ }
+ // Create and populate the edge hastable
+ mEdgeHashtable = new Hashtable<String, DirectedEdge>();
+ for (i = 0; i < data.mEdgeImpls.length; i++) {
+ mEdgeHashtable.put(String.valueOf(data.mEdgeImpls[i].getID()), data.mEdgeImpls[i]);
+ }
+ // Set the start vertex id and the id generation counter
+ mStartVertexId = data.mStartVertexId;
+ mNextId = data.mNextId;
+ }
+
+ public GraphModelCastorData getGraphModelCastorData() {
+ Object[] vertexObjs = mVertexHashtable.values().toArray();
+ Vertex[] vertexImpls = new Vertex[vertexObjs.length];
+ Object[] edgeObjs = mEdgeHashtable.values().toArray();
+ DirectedEdge[] directedEdgeImpls = new DirectedEdge[edgeObjs.length];
+ String className = null;
+ int i = 0;
+ // Put in the vertices
+ for (i = 0; i < vertexImpls.length; i++) {
+ vertexImpls[i] = (Vertex)vertexObjs[i];
+ }
+ // Put in the edges
+ for (i = 0; i < directedEdgeImpls.length; i++) {
+ directedEdgeImpls[i] = (DirectedEdge)edgeObjs[i];
+ }
+ // Disable persistency of the vertex outline creator: determined by container
+ // Determine the class name of the vertex outline creator
+// if (mVertexOutlineCreator == null) {
+// className = "";
+// }
+// else {
+// className = mVertexOutlineCreator.getClass().getName();
+// }
+ return new GraphModelCastorData(className, vertexImpls, directedEdgeImpls, mStartVertexId, mNextId);
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/model/GraphModelCastorData.java b/src/main/java/org/cristalise/kernel/graph/model/GraphModelCastorData.java new file mode 100644 index 0000000..1f467a7 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/GraphModelCastorData.java @@ -0,0 +1,50 @@ +/**
+ * 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.graph.model;
+
+
+public class GraphModelCastorData
+{
+ // Deprecated: Vertex outline creator is now set by the container
+ public String mClassNameOfVertexOutlineCreator = "";
+ public Vertex[] mVertexImpls = {};
+ public DirectedEdge[] mEdgeImpls = {};
+ public int mStartVertexId = 0;
+ public int mNextId = 0;
+
+
+ public GraphModelCastorData()
+ {
+ }
+
+ public GraphModelCastorData(String classNameOfVertexOutlineCreator,
+ Vertex[] vertexImpls,
+ DirectedEdge[] edgeImpls,
+ int startVertexId,
+ int nextId)
+ {
+ mClassNameOfVertexOutlineCreator = classNameOfVertexOutlineCreator;
+ mVertexImpls = vertexImpls;
+ mEdgeImpls = edgeImpls;
+ mStartVertexId = startVertexId;
+ mNextId = nextId;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/model/GraphModelManager.java b/src/main/java/org/cristalise/kernel/graph/model/GraphModelManager.java new file mode 100644 index 0000000..1f89b50 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/GraphModelManager.java @@ -0,0 +1,157 @@ +/**
+ * 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.graph.model;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Observable;
+import java.util.Stack;
+
+import org.cristalise.kernel.graph.event.EntireModelChangedEvent;
+import org.cristalise.kernel.graph.event.ForcedNotifyEvent;
+import org.cristalise.kernel.graph.event.GraphModelEvent;
+import org.cristalise.kernel.utils.Logger;
+
+
+
+public class GraphModelManager extends Observable
+{
+
+ private GraphModel mGraphModel;
+ private EdgeFactory mEdgeFactory;
+ private VertexFactory mVertexFactory;
+ private VertexOutlineCreator mVertexOutlineCreator;
+ private final EntireModelChangedEvent mEntireModelChangedEvent = new EntireModelChangedEvent();
+ private final ForcedNotifyEvent mForcedNotifyEvent = new ForcedNotifyEvent();
+ private final Stack<GraphModel> mParentModels = new Stack<GraphModel>();
+ private final ArrayList<Integer> mParentIds = new ArrayList<Integer>();
+ private boolean mEditable = true;
+
+ // Calling this constructor does not create a vertex outline creator
+ // which is required by the method addVertexAndCreateId()
+ public GraphModelManager()
+ {
+ mGraphModel = new GraphModel();
+ mGraphModel.setManager(this);
+ }
+
+ public GraphModelManager(GraphModel newModel) {
+ newModel.setManager(this);
+ mGraphModel = newModel;
+ }
+
+ public void replace(GraphModel newModel) {
+ mParentModels.clear();
+
+ //zoom back to where we were
+ for (Iterator<Integer> iter = mParentIds.iterator(); iter.hasNext();) {
+ Integer parentId = iter.next();
+ GraphableVertex childModelVertex = (GraphableVertex)newModel.getVertexById(parentId.intValue());
+ if (childModelVertex == null) { // we've been deleted, stay here
+ Logger.msg(7, "Didn't find "+parentId+" in new model tree. Stopping here.");
+ do { iter.remove(); } while (iter.hasNext());
+ break;
+ }
+ else {
+ mParentModels.push(newModel);
+ Logger.msg(7, "Pushing model and switching to "+parentId);
+ newModel = childModelVertex.getChildGraphModel();
+ }
+ }
+ setModel(newModel);
+ }
+
+ public void setModel(GraphModel newModel) {
+ // reset transient data
+ newModel.mNewEdgeOriginVertex = null;
+ newModel.mNewEdgeEndPoint = null;
+
+ // copy factories over
+ newModel.setExternalEdgeFactory(mEdgeFactory);
+ newModel.setExternalVertexFactory(mVertexFactory);
+ newModel.setVertexOutlineCreator(mVertexOutlineCreator);
+ mVertexFactory.setCreationContext(newModel.getContainingVertex());
+ newModel.setManager(this);
+ mGraphModel.setManager(null);
+ mGraphModel = newModel;
+
+ // notify
+ notifyObservers(mEntireModelChangedEvent);
+ }
+
+ public void zoomIn(Vertex child) {
+ GraphModel childModel = child.getChildGraphModel();
+ if (childModel != null) {
+ mParentModels.push(mGraphModel);
+ mParentIds.add(Integer.valueOf(child.getID()));
+ setModel(childModel);
+ Logger.msg(7, "ZoomIn - Stack size: "+mParentModels.size()+" ids:"+mParentIds.size());
+ }
+ }
+
+ public void zoomOut() {
+ if (!mParentModels.empty()) {
+ setModel(mParentModels.pop());
+ mParentIds.remove(mParentIds.size()-1);
+ }
+ Logger.msg(7, "ZoomOut - Stack size: "+mParentModels.size()+" ids:"+mParentIds.size());
+
+ }
+
+ public void forceNotify()
+ {
+ notifyObservers(mForcedNotifyEvent);
+ }
+
+ public GraphModel getModel() {
+ return mGraphModel;
+ }
+
+ public void setExternalEdgeFactory(EdgeFactory newEdgeFactory) {
+ mEdgeFactory = newEdgeFactory;
+ mGraphModel.setExternalEdgeFactory(newEdgeFactory);
+ }
+
+ public void setExternalVertexFactory(VertexFactory newVertexFactory) {
+ mVertexFactory = newVertexFactory;
+ mGraphModel.setExternalVertexFactory(newVertexFactory);
+ }
+
+ public void setVertexOutlineCreator(VertexOutlineCreator newVertexOutlineCreator) {
+ mVertexOutlineCreator = newVertexOutlineCreator;
+ mGraphModel.setVertexOutlineCreator(newVertexOutlineCreator);
+ }
+
+ public void notifyObservers(GraphModelEvent ev) {
+ setChanged();
+ super.notifyObservers(ev);
+ }
+
+ public void setEditable(boolean editable) {
+ mEditable = editable;
+ }
+
+ public boolean isEditable() {
+ return mEditable;
+ }
+
+
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/model/GraphPoint.java b/src/main/java/org/cristalise/kernel/graph/model/GraphPoint.java new file mode 100644 index 0000000..a619733 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/GraphPoint.java @@ -0,0 +1,37 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.model;
+
+
+public class GraphPoint {
+
+ public int x;
+ public int y;
+
+ public GraphPoint() {
+ x=0; y=0;
+ }
+
+ public GraphPoint(int x, int y) {
+ this.x = x;
+ this.y = y;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/model/Graphable.java b/src/main/java/org/cristalise/kernel/graph/model/Graphable.java new file mode 100644 index 0000000..f4acbb7 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/Graphable.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.graph.model;
+
+/**
+* @version $Revision: 1.6 $ $Date: 2003/05/12 13:10:20 $
+* @author $Author: abranson $
+*/
+
+import org.cristalise.kernel.utils.CastorHashMap;
+
+abstract public class Graphable extends Vertex
+{
+
+ protected CastorHashMap mProperties = null;
+ public GraphModel children;
+
+ public void setProperties(CastorHashMap props)
+ {
+ mProperties = props;
+ }
+
+ public CastorHashMap getProperties()
+ {
+ return mProperties;
+ }
+ /** @associates Graphable that is directly containing it*/
+ private Graphable parent;
+
+ /**
+ * Returns the parent.
+ * @return Graphable
+ */
+ public Graphable getParent()
+ {
+ return parent;
+ }
+
+ /**
+ * Sets the parent.
+ * @param parent The parent to set
+ */
+ public void setParent(Graphable parent)
+ {
+ this.parent = parent;
+ }
+ @Override
+ public GraphModel getChildGraphModel() {
+ return children;
+ }
+
+ @Override
+ public Object getCreationContext() {
+ return this;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/model/GraphableEdge.java b/src/main/java/org/cristalise/kernel/graph/model/GraphableEdge.java new file mode 100644 index 0000000..8f6ac79 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/GraphableEdge.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.graph.model;
+
+import org.cristalise.kernel.utils.CastorHashMap;
+import org.cristalise.kernel.utils.KeyValuePair;
+
+/**
+* @version $Revision: 1.2 $ $Date: 2003/05/12 13:10:20 $
+* @author $Author: abranson $
+*/
+public abstract class GraphableEdge extends DirectedEdge
+{
+
+ private GraphableVertex mParent;
+ private CastorHashMap mProperties = null;
+
+ public GraphableEdge()
+ {
+ mProperties = new CastorHashMap();
+ }
+
+ public GraphableEdge(GraphableVertex pre, GraphableVertex nex)
+ {
+ mProperties = new CastorHashMap();
+ setParent(pre.getParent());
+ pre.getParent().getChildrenGraphModel().addEdgeAndCreateId(this, pre, nex);
+ }
+
+ /**
+ * Returns the parent.
+ * @return GraphableVertex
+ */
+ public GraphableVertex getParent()
+ {
+ return mParent;
+ }
+
+ /**
+ * Sets the parent.
+ * @param parent The parent to set
+ */
+ public void setParent(GraphableVertex parent)
+ {
+ mParent = parent;
+ }
+
+ /**
+ * Returns the properties.
+ * @return CastorHashMap
+ */
+ public CastorHashMap getProperties()
+ {
+ return mProperties;
+ }
+
+ /**
+ * Sets the properties.
+ * @param properties The properties to set
+ */
+ public void setProperties(CastorHashMap properties)
+ {
+ mProperties = properties;
+ }
+
+ public KeyValuePair[] getKeyValuePairs() {
+ return mProperties.getKeyValuePairs();
+ }
+
+ public void setKeyValuePairs(KeyValuePair[] pairs) {
+ mProperties.setKeyValuePairs(pairs);
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/model/GraphableVertex.java b/src/main/java/org/cristalise/kernel/graph/model/GraphableVertex.java new file mode 100644 index 0000000..b82448e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/GraphableVertex.java @@ -0,0 +1,284 @@ +/**
+ * 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.graph.model;
+/**
+* @version $Revision: 1.24 $ $Date: 2005/10/05 07:39:37 $
+* @author $Author: abranson $
+*/
+
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.utils.CastorHashMap;
+import org.cristalise.kernel.utils.KeyValuePair;
+
+public abstract class GraphableVertex extends Vertex
+{
+ private CastorHashMap mProperties = null;
+ private boolean mIsLayoutable;
+ protected boolean mIsComposite;
+ private GraphModel mChildrenGraphModel;
+ public GraphableVertex()
+ {
+ mProperties = new CastorHashMap();
+ }
+ public void setProperties(CastorHashMap props)
+ {
+ mProperties = props;
+ }
+ public CastorHashMap getProperties()
+ {
+ return mProperties;
+ }
+ protected Integer getVersionNumberProperty(String propName) throws InvalidDataException {
+ Object val = getProperties().get(propName);
+ if (val == null || val.equals("") || val.toString().equals("-1")) return null;
+ try {
+ return Integer.valueOf(val.toString());
+ } catch (NumberFormatException ex) {
+ throw new InvalidDataException("Invalid version number for property '"+propName+"': "+val.toString());
+ }
+ }
+ public KeyValuePair[] getKeyValuePairs()
+ {
+ return mProperties.getKeyValuePairs();
+ }
+ public void setKeyValuePairs(KeyValuePair[] pairs)
+ {
+ mProperties.setKeyValuePairs(pairs);
+ }
+ /** @associates Graphable that is directly containing it*/
+ private GraphableVertex parent;
+ /**
+ * Returns the parent.
+ * @return Graphable
+ */
+ public GraphableVertex getParent()
+ {
+ return parent;
+ }
+ /**
+ * Sets the parent.
+ * @param parent The parent to set
+ */
+ public void setParent(GraphableVertex parent)
+ {
+ if (this.equals(parent))
+ throw new ExceptionInInitializerError();
+ this.parent = parent;
+ }
+ @Override
+ public GraphModel getChildGraphModel()
+ {
+ return mChildrenGraphModel;
+ }
+ @Override
+ public Object getCreationContext()
+ {
+ return this;
+ }
+ public Vertex[] getOutGraphables()
+ {
+ if (parent == null)
+ return new Vertex[0]; // none if no parent
+ return parent.mChildrenGraphModel.getOutVertices(this);
+ }
+ public DirectedEdge[] getOutEdges()
+ {
+ if (parent == null)
+ return new DirectedEdge[0]; // none if no parent
+ return parent.mChildrenGraphModel.getOutEdges(this);
+ }
+ public DirectedEdge[] getInEdges()
+ {
+ if (parent == null)
+ return new DirectedEdge[0]; // none if no parent
+ DirectedEdge[] edges = getParent().mChildrenGraphModel.getInEdges(this);
+ if (edges != null)
+ return edges;
+ else
+ return new DirectedEdge[0];
+ }
+ public GraphableVertex[] getChildren()
+ {
+ return getLayoutableChildren();
+ }
+
+ public DirectedEdge[] getChildrenEdges()
+ {
+ if (getIsComposite())
+ {
+ return getChildGraphModel().getEdges();
+ }
+ return null;
+ }
+
+ public GraphableVertex[] getLayoutableChildren()
+ {
+ if (getIsComposite())
+ {
+ Vertex[] vs = mChildrenGraphModel.getVertices();
+ GraphableVertex[] gvs = new GraphableVertex[vs.length];
+ for (int i = 0; i < vs.length; i++)
+ {
+ gvs[i] = (GraphableVertex) vs[i];
+ }
+ return gvs;
+ }
+ return null;
+ }
+
+ /**@returns the Graphable searched or null if not this or children*/
+ public GraphableVertex search(String ids)
+ {
+ if (getName().equals(ids))
+ return this;
+ if (String.valueOf(getID()).equals(ids))
+ return this;
+ if (getIsComposite())
+ {
+ GraphableVertex[] graphables = getChildren();
+ if (ids.startsWith(String.valueOf(getID())))
+ ids = ids.substring(ids.indexOf("/") + 1);
+ else if (ids.startsWith(getName()))
+ ids = ids.substring(getName().length() + 1);
+ else if (ids.startsWith(getPath()))
+ ids = ids.substring(getPath().length() + 1);
+ else
+ return null;
+
+ for (GraphableVertex graphable : graphables) {
+ GraphableVertex grap = graphable.search(ids);
+ if (grap != null) return grap;
+ }
+ }
+ return null;
+ }
+ /**
+ * Returns the isLayoutable.
+ * @return boolean
+ */
+ public boolean getIsLayoutable()
+ {
+ return mIsLayoutable;
+ }
+ /**
+ * Sets the isLayoutable.
+ * @param isLayoutable The isLayoutable to set
+ */
+ public void setIsLayoutable(boolean isLayoutable)
+ {
+ mIsLayoutable = isLayoutable;
+ }
+ /**
+ * Returns the isComposite.
+ * @return boolean
+ */
+ public boolean getIsComposite()
+ {
+ return mIsComposite;
+ }
+ /**
+ * Sets the isComposite.
+ * @param isComposite The isComposite to set
+ */
+ public void setIsComposite(boolean isComposite)
+ {
+ mIsComposite = isComposite;
+ }
+
+ public void addChild(GraphableVertex graphableVertex, GraphPoint g)
+ {
+ getChildGraphModel().addVertexAndCreateId(graphableVertex, g);
+ graphableVertex.setParent(this);
+ }
+ /**
+ * Returns the childrenGraph.
+ * @return GraphModel
+ */
+ public GraphModel getChildrenGraphModel()
+ {
+ return mChildrenGraphModel;
+ }
+ /**
+ * Sets the childrenGraph.
+ * @param childrenGraph The childrenGraph to set
+ */
+ public void setChildrenGraphModel(GraphModel childrenGraph)
+ {
+ mChildrenGraphModel = childrenGraph;
+ DirectedEdge[] edges = mChildrenGraphModel.getEdges();
+ GraphableVertex[] graphables = this.getLayoutableChildren();
+ if (graphables != null)
+ for (GraphableVertex graphable : graphables)
+ graphable.setParent(this);
+ if (edges != null)
+ for (DirectedEdge edge : edges)
+ ((GraphableEdge) edge).setParent(this);
+ childrenGraph.setContainingVertex(this);
+ }
+
+ /**
+ * @see org.cristalise.kernel.graph.model.Vertex#getCentrePoint()
+ */
+ @Override
+ public GraphPoint getCentrePoint()
+ {
+ if (!getIsLayoutable())
+ return null;
+ return super.getCentrePoint();
+ }
+ /**
+ * @see org.cristalise.kernel.graph.model.Vertex#getInEdgeIds()
+ */
+ @Override
+ public int[] getInEdgeIds()
+ {
+ if (!getIsLayoutable())
+ return null;
+ return super.getInEdgeIds();
+ }
+ /**
+ * @see org.cristalise.kernel.graph.model.Vertex#getOutEdgeIds()
+ */
+ @Override
+ public int[] getOutEdgeIds()
+ {
+ if (!getIsLayoutable())
+ return null;
+ return super.getOutEdgeIds();
+ }
+ /**
+ * @see org.cristalise.kernel.graph.model.Vertex#getOutlinePoints()
+ */
+ @Override
+ public GraphPoint[] getOutlinePoints()
+ {
+ if (!getIsLayoutable())
+ return null;
+ return super.getOutlinePoints();
+ }
+ public String getPath()
+ {
+ if (getName() != null && !getName().equals(""))
+ return getParent().getPath() + "/" + getName();
+ return getParent().getPath() + "/" + getID();
+ }
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/graph/model/TypeNameAndConstructionInfo.java b/src/main/java/org/cristalise/kernel/graph/model/TypeNameAndConstructionInfo.java new file mode 100644 index 0000000..a9b5572 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/TypeNameAndConstructionInfo.java @@ -0,0 +1,43 @@ +/**
+ * 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.graph.model;
+
+
+
+public class TypeNameAndConstructionInfo
+{
+ public String mName = null;
+ public Object mInfo = null;
+
+
+ public TypeNameAndConstructionInfo(String name, Object info)
+ {
+ mName = name;
+ mInfo = info;
+ }
+
+
+ @Override
+ public String toString()
+ {
+ return mName;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/model/Vertex.java b/src/main/java/org/cristalise/kernel/graph/model/Vertex.java new file mode 100644 index 0000000..122bbdd --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/Vertex.java @@ -0,0 +1,327 @@ +/**
+ * 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.graph.model;
+
+import java.awt.Polygon;
+import java.util.Vector;
+
+
+public class Vertex
+{
+ private int mId = -1;
+ private String mName = "";
+ private GraphPoint mCentrePoint = new GraphPoint(0, 0);
+ private int mHeight = 0;
+ private int mWidth = 0;
+ private Vector<Integer> mInEdgeIdVector = new Vector<Integer>();
+ private Vector<Integer> mOutEdgeIdVector = new Vector<Integer>();
+ private final Vector<Object> mTags = new Vector<Object>();
+
+ // The Java Polygon class is used to determine if a point
+ // lies within the outline of a vertex. Unfortunately
+ // both the polygon and the set of outline points need to
+ // kept in memory because a polygon never has 0 points
+ // which is required by Castor's unmarshall object mechanism
+ private Polygon mOutlinePolygon = new Polygon();
+ private GraphPoint[] mOutlinePoints = new GraphPoint[0];
+
+
+ private GraphModel graphModel;
+
+ public void setID(int id)
+ {
+ mId = id;
+ }
+
+
+ public int getID()
+ {
+ return mId;
+ }
+
+
+ public void setName(String n)
+ {
+ mName = n;
+ }
+
+
+ public String getName()
+ {
+ return mName;
+ }
+
+
+ public void setCentrePoint(GraphPoint p)
+ {
+ mCentrePoint = p;
+ }
+
+
+ public GraphPoint getCentrePoint()
+ {
+ return mCentrePoint;
+ }
+
+
+ public void setHeight(int h)
+ {
+ mHeight = h;
+ }
+
+
+ public int getHeight()
+ {
+ return mHeight;
+ }
+
+
+ public void setWidth(int w)
+ {
+ mWidth = w;
+ }
+
+
+ public int getWidth()
+ {
+ return mWidth;
+ }
+
+
+ // Sets the outline points and re-calculates the
+ // height and width
+ public void setOutlinePoints(GraphPoint[] outline)
+ {
+ int topLeftX = outline[0].x;
+ int topLeftY = outline[0].y;
+ int bottomRightX = 0;
+ int bottomRightY = 0;
+ int i = 0;
+
+ mOutlinePoints = outline;
+
+ // Construct a polygon in the outline of the vertex
+ // and calculate the top left and bottom right corners
+ mOutlinePolygon = new Polygon();
+
+ for(i=0; i<outline.length; i++)
+ {
+ mOutlinePolygon.addPoint(outline[i].x, outline[i].y);
+
+ if(outline[i].x < topLeftX)
+ {
+ topLeftX = outline[i].x;
+ }
+
+ if(outline[i].y < topLeftY)
+ {
+ topLeftY = outline[i].y;
+ }
+
+ if(outline[i].x > bottomRightX)
+ {
+ bottomRightX = outline[i].x;
+ }
+
+
+ if(outline[i].y > bottomRightY)
+ {
+ bottomRightY = outline[i].y;
+ }
+ }
+
+ // Set the height and width
+ mHeight = bottomRightY - topLeftY;
+ mWidth = bottomRightX - topLeftX;
+ }
+
+
+ public GraphPoint[] getOutlinePoints()
+ {
+ return mOutlinePoints;
+ }
+
+ public void moveAbsolute(GraphPoint p)
+ {
+ int deltaX = p.x - mCentrePoint.x;
+ int deltaY = p.y - mCentrePoint.y;
+ int i = 0;
+
+ // Update the outline points and the polygon
+ for(i=0; i<mOutlinePoints.length; i++)
+ {
+ mOutlinePoints[i].x += deltaX;
+ mOutlinePoints[i].y += deltaY;
+ }
+
+ mOutlinePolygon.translate(deltaX, deltaY);
+
+ mCentrePoint.x = p.x;
+ mCentrePoint.y = p.y;
+ }
+
+
+ public boolean containsPoint(GraphPoint p)
+ {
+ return mOutlinePolygon.contains(p.x, p.y);
+ }
+
+
+ public void setInEdgeIds(int[] ids)
+ {
+ int i = 0;
+
+ mInEdgeIdVector = new Vector<Integer>(10, 10);
+ for(i=0; i<ids.length; i++)
+ mInEdgeIdVector.add(Integer.valueOf(ids[i]));
+ }
+
+
+ public int[] getInEdgeIds()
+ {
+ return integerVectorToIntArray(mInEdgeIdVector);
+ }
+
+
+ public void setOutEdgeIds(int[] ids)
+ {
+ int i = 0;
+
+ mOutEdgeIdVector = new Vector<Integer>(10, 10);
+ for(i=0; i<ids.length; i++)
+ mOutEdgeIdVector.add(Integer.valueOf(ids[i]));
+ }
+
+
+ public int[] getOutEdgeIds()
+ {
+ return integerVectorToIntArray(mOutEdgeIdVector);
+ }
+
+
+ private static int[] integerVectorToIntArray(Vector<Integer> vector)
+ {
+ int[] array = new int[vector.size()];
+ Integer integer = null;
+ int i = 0;
+
+ for(i=0; i<array.length; i++)
+ {
+ integer = vector.elementAt(i);
+ array[i] = integer.intValue();
+ }
+
+ return array;
+ }
+
+
+ public void addInEdgeId(int id)
+ {
+ mInEdgeIdVector.add(Integer.valueOf(id));
+ }
+
+
+ public void removeInEdgeId(int id)
+ {
+ Integer integer = null;
+ int i = 0;
+
+ for(i=0; i<mInEdgeIdVector.size(); i++)
+ {
+ integer = mInEdgeIdVector.elementAt(i);
+
+ if(integer.intValue() == id)
+ {
+ mInEdgeIdVector.removeElementAt(i);
+ return;
+ }
+ }
+ }
+
+
+ public void addOutEdgeId(int id)
+ {
+ mOutEdgeIdVector.add(Integer.valueOf(id));
+ }
+
+
+ public void removeOutEdgeId(int id)
+ {
+ Integer integer = null;
+ int i = 0;
+
+ for(i=0; i<mOutEdgeIdVector.size(); i++)
+ {
+ integer = mOutEdgeIdVector.elementAt(i);
+
+ if(integer.intValue() == id)
+ {
+ mOutEdgeIdVector.removeElementAt(i);
+ return;
+ }
+ }
+ }
+
+
+ public void setTag(Object o)
+ {
+ mTags.add(o);
+ }
+
+
+ public boolean hasTag(Object o)
+ {
+ return mTags.contains(o);
+ }
+
+ public void clearTag(Object o)
+ {
+ mTags.remove(o);
+ }
+
+
+ public GraphModel getChildGraphModel() {
+ return null;
+ }
+
+ public Object getCreationContext() {
+ return null;
+ }
+
+
+ public GraphModel getGraphModel()
+ {
+ return graphModel;
+ }
+
+ public void setGraphModel(GraphModel graphModel)
+ {
+ this.graphModel = graphModel;
+ }
+
+ public boolean isJoin() {
+ return false;
+ }
+ public boolean isLoop() {
+ return false;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/model/VertexFactory.java b/src/main/java/org/cristalise/kernel/graph/model/VertexFactory.java new file mode 100644 index 0000000..5c5234e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/VertexFactory.java @@ -0,0 +1,33 @@ +/**
+ * 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.graph.model;
+
+public interface VertexFactory
+{
+ public void create
+ (
+ GraphModelManager graphModelManager,
+ GraphPoint location,
+ TypeNameAndConstructionInfo typeNameAndConstructionInfo
+ ) throws Exception;
+
+ public void setCreationContext(Object newContext);
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/model/VertexOutlineCreator.java b/src/main/java/org/cristalise/kernel/graph/model/VertexOutlineCreator.java new file mode 100644 index 0000000..f4cb96c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/model/VertexOutlineCreator.java @@ -0,0 +1,30 @@ +/**
+ * 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.graph.model;
+
+
+
+// Classes that implement this interface must
+// have a parameter less constructor
+public interface VertexOutlineCreator
+{
+ public void setOutline(Vertex vertex);
+}
diff --git a/src/main/java/org/cristalise/kernel/graph/package-info.java b/src/main/java/org/cristalise/kernel/graph/package-info.java new file mode 100644 index 0000000..5a1d5a6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/package-info.java @@ -0,0 +1,29 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+/**
+ * The GraphModel framework is used by the Workflow and Aggregation collection
+ * for their layout. Although the cristal-gui module uses the java.2d graphics
+ * framework to draw graphs, the Graph package itself contains no UI information
+ * beyond x, y, width and height.
+ *
+ */
+
+package org.cristalise.kernel.graph;
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/graph/traversal/GraphTraversal.java b/src/main/java/org/cristalise/kernel/graph/traversal/GraphTraversal.java new file mode 100644 index 0000000..4cc5013 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/graph/traversal/GraphTraversal.java @@ -0,0 +1,106 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.graph.traversal;
+
+
+import java.util.Vector;
+
+import org.cristalise.kernel.graph.model.GraphModel;
+import org.cristalise.kernel.graph.model.Vertex;
+
+
+
+public class GraphTraversal
+{
+ public static final int kUp = 1;
+ public static final int kDown = 2;
+
+
+ private GraphTraversal()
+ {
+ }
+
+
+ public static Vertex[] getTraversal(GraphModel graphModel, Vertex startVertex, int direction, boolean ignoreBackLinks)
+ {
+ Vector<Vertex> path = new Vector<Vertex>(10, 10);
+
+ graphModel.clearTags(startVertex);
+ visitVertex(startVertex, graphModel, path, direction, startVertex, ignoreBackLinks);
+
+ return vectorToVertexArray(path);
+ }
+
+
+ private static void visitVertex(Vertex vertex, GraphModel graphModel, Vector<Vertex> path, int direction, Object tag, boolean ignoreBackLinks)
+ {
+ Vertex[] children = null;
+ int i = 0;
+
+ if(direction == kDown)
+ {
+ children = graphModel.getOutVertices(vertex);
+ }
+ else
+ {
+ children = graphModel.getInVertices(vertex);
+ }
+
+ vertex.setTag(tag);
+ path.add(vertex);
+
+ for(i=0; i<children.length; i++)
+ {
+ if(!(children[i].hasTag(tag)))
+ {
+ boolean skipBackLink = false;
+ if ( ignoreBackLinks &&
+ ((vertex.isJoin() && direction == kUp) ||
+ (vertex.isLoop() && direction == kDown))) {
+ Vertex[] following = getTraversal(graphModel, children[i], direction, false);
+ for (Vertex element : following) {
+ if (element == vertex) {
+ skipBackLink = true;
+ break;
+ }
+ }
+ }
+ if (!skipBackLink)
+ visitVertex(children[i], graphModel, path, direction, tag, ignoreBackLinks);
+ }
+ }
+ }
+
+
+ private static Vertex[] vectorToVertexArray(Vector<Vertex> vector)
+ {
+ Vertex[] vertices = new Vertex[vector.size()];
+ int i = 0;
+
+
+ for(i=0; i<vertices.length; i++)
+ {
+ vertices[i] = vector.elementAt(i);
+ }
+
+ return vertices;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/ActivityDef.java b/src/main/java/org/cristalise/kernel/lifecycle/ActivityDef.java new file mode 100644 index 0000000..536fd3b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/ActivityDef.java @@ -0,0 +1,163 @@ +/**
+ * 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.lifecycle;
+import java.util.Vector;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.lifecycle.instance.Activity;
+import org.cristalise.kernel.lifecycle.instance.WfVertex;
+import org.cristalise.kernel.utils.DescriptionObject;
+import org.cristalise.kernel.utils.FileStringUtility;
+
+/**
+ * @version $Revision: 1.45 $ $Date: 2005/10/05 07:39:36 $
+ * @author $Author: abranson $
+ */
+public class ActivityDef extends WfVertexDef implements C2KLocalObject, DescriptionObject
+{
+ private int mId = -1;
+ private String mName = "";
+ private int mVersion = -1;
+ public boolean changed = false;
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public ActivityDef()
+ {
+ mErrors = new Vector<String>(0, 1);
+ setProperties(new WfCastorHashMap());
+ setIsLayoutable(false);
+ }
+ /**
+ * @see org.cristalise.kernel.graph.model.Vertex#setID(int)
+ */
+ @Override
+ public void setID(int id)
+ {
+ mId = id;
+ if (mName.equals(""))
+ setName(String.valueOf(id));
+ }
+ /**
+ * @see org.cristalise.kernel.graph.model.Vertex#getID()
+ */
+ @Override
+ public int getID()
+ {
+ return mId;
+ }
+ /**
+ * @see org.cristalise.kernel.graph.model.Vertex#setName(java.lang.String)
+ */
+ @Override
+ public void setName(String n)
+ {
+ mName = n;
+ }
+ /**
+ * @see org.cristalise.kernel.graph.model.Vertex#getName()
+ */
+ @Override
+ public String getName()
+ {
+ return mName;
+ }
+
+ @Override
+ public void setVersion(int v)
+ {
+ mVersion = v;
+ }
+ /**
+ * @see org.cristalise.kernel.graph.model.Vertex#getName()
+ */
+ @Override
+ public int getVersion()
+ {
+ return mVersion;
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.WfVertexDef#getErrors()
+ */
+ @Override
+ public String getErrors()
+ {
+ return super.getErrors();
+ }
+ /**
+ * Method linkToSlot.
+ *
+ * @param actSl
+ * @param name
+ */
+ public void linkToSlot(ActivitySlotDef actSl, String name, String name2)
+ {
+ actSl.setActivityDef(FileStringUtility.convert(name));
+ actSl.getProperties().put("Name", name2.replace('/', '_'));
+ actSl.setName(name+" slot");
+ setName(FileStringUtility.convert(name));
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.WfVertexDef#verify()
+ */
+ @Override
+ public boolean verify()
+ {
+ return true;
+ }
+ /**
+ * @see org.cristalise.kernel.entity.C2KLocalObject#getClusterType()
+ */
+ @Override
+ public String getClusterType()
+ {
+ return null;
+ }
+ public String getActName()
+ {
+ return getName();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.cristalise.kernel.lifecycle.commonInterface.ActType#getDescName()
+ */
+ public String getDescName()
+ {
+ return getName();
+ }
+
+ @Override
+ public WfVertex instantiate() throws ObjectNotFoundException, InvalidDataException{
+ return instantiate(getName());
+ }
+ public WfVertex instantiate(String name) throws ObjectNotFoundException, InvalidDataException
+ {
+ Activity act = new Activity();
+ configureInstance(act);
+ act.setName(name);
+ act.setType(getName());
+ return act;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/ActivitySlotDef.java b/src/main/java/org/cristalise/kernel/lifecycle/ActivitySlotDef.java new file mode 100644 index 0000000..89ddb86 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/ActivitySlotDef.java @@ -0,0 +1,201 @@ +/**
+ * 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.lifecycle;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.graph.model.Vertex;
+import org.cristalise.kernel.graph.traversal.GraphTraversal;
+import org.cristalise.kernel.lifecycle.instance.Activity;
+import org.cristalise.kernel.lifecycle.instance.WfVertex;
+import org.cristalise.kernel.utils.KeyValuePair;
+import org.cristalise.kernel.utils.LocalObjectLoader;
+
+/**
+ * @version $Revision: 1.46 $ $Date: 2005/10/05 07:39:36 $
+ * @author $Author: abranson $
+ */
+public class ActivitySlotDef extends WfVertexDef
+{
+ private String activityDef;
+
+ /**
+ * Method setActivityDef.
+ *
+ * @param oActivityDef
+ */
+ public void setActivityDef(String oActivityDef)
+ {
+ activityDef = oActivityDef;
+ }
+ /**
+ * Method getActivityDef.
+ *
+ * @return String
+ */
+ public String getActivityDef()
+ {
+ return activityDef;
+ }
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public ActivitySlotDef()
+ {
+ getProperties().put("Name", "");
+ getProperties().put("Version", 0);
+ }
+
+ public ActivityDef getTheActivityDef() throws ObjectNotFoundException, InvalidDataException
+ {
+ ActivityDef actDef = LocalObjectLoader.getActDef(getActivityDef(), getVersionNumberProperty("Version"));
+ if (actDef instanceof CompositeActivityDef)
+ mIsComposite = true;
+ return actDef;
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.WfVertexDef#verify()
+ */
+ /** launch the verification of the ActivityDef */
+ @Override
+ public boolean verify()
+ {
+ mErrors.removeAllElements();
+ boolean err = true;
+ int nbInEdgres = getInEdges().length;
+ int nbOutEdges = getOutEdges().length;
+ if (nbInEdgres == 0 && this.getID() != getParent().getChildrenGraphModel().getStartVertexId())
+ {
+ mErrors.add("Unreachable");
+ err = false;
+ }
+ if (nbInEdgres > 1)
+ {
+ mErrors.add("Bad nb of previous");
+ err = false;
+ }
+ if (nbOutEdges > 1)
+ {
+ mErrors.add("too many next");
+ err = false;
+ }
+ if (nbOutEdges == 0)
+ {
+ if (!((CompositeActivityDef) getParent()).hasGoodNumberOfActivity())
+ {
+ mErrors.add("too many endpoints");
+ err = false;
+ }
+ }
+
+ Vertex[] allSiblings = getParent().getChildGraphModel().getVertices();
+ String thisName = (String)getProperties().get("Name");
+ if (thisName == null || thisName.length()==0) mErrors.add("Slot name is empty");
+ else for (Vertex v : allSiblings) {
+ if (v instanceof ActivitySlotDef && v.getID()!=getID()) {
+ ActivitySlotDef otherSlot = (ActivitySlotDef)v;
+ String otherName = (String)otherSlot.getProperties().get("Name");
+ if (otherName != null && otherName.equals(thisName)) {
+ mErrors.add("Duplicate slot name");
+ err = false;
+ }
+ }
+ }
+
+ KeyValuePair[] props;
+ try {
+ props = getTheActivityDef().getProperties().getKeyValuePairs();
+ for (KeyValuePair prop : props) {
+ if (prop.isAbstract() && !getProperties().containsKey(prop.getKey())) {
+ mErrors.add("Abstract property '"+prop.getKey()+"' not defined in slot");
+ err = false;
+ }
+ }
+ } catch (Exception ex) { }
+
+
+ // Loop check
+ Vertex[] outV = getOutGraphables();
+ Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ boolean errInLoop = false;
+ for (Vertex element : outV) {
+ for (Vertex anteVertice : anteVertices)
+ if (!loop() && element.getID() == anteVertice.getID())
+ errInLoop = true;
+ }
+ if (errInLoop)
+ {
+ mErrors.add("Problem in Loop");
+ err = false;
+ }
+ return err;
+ }
+ /**
+ * Method getNextWfVertices.
+ *
+ * @return WfVertexDef[]
+ */
+ public WfVertexDef[] getNextWfVertices()
+ {
+ return (WfVertexDef[]) getOutGraphables();
+ }
+ /**
+ * @see org.cristalise.kernel.graph.model.GraphableVertex#isLayoutable()
+ */
+ /**
+ * @see org.cristalise.kernel.graph.model.GraphableVertex#getIsLayoutable()
+ */
+ public boolean isLayoutable()
+ {
+ return true;
+ }
+ /**
+ * Method getInfo.
+ *
+ * @return CastorHashMap
+ */
+ private void configureInstance(Activity act)
+ {
+ KeyValuePair[] k = getProperties().getKeyValuePairs();
+ for (KeyValuePair element : k)
+ act.getProperties().put(element.getKey(), element.getValue(), element.isAbstract());
+ act.setCentrePoint(getCentrePoint());
+ act.setOutlinePoints(getOutlinePoints());
+ act.setInEdgeIds(getInEdgeIds());
+ act.setOutEdgeIds(getOutEdgeIds());
+ act.setName(getActName());
+ act.setID(getID());
+ }
+
+ public String getActName()
+ {
+ return (String) getProperties().get("Name");
+ }
+
+ @Override
+ public WfVertex instantiate() throws ObjectNotFoundException, InvalidDataException {
+ Activity newActivity = (Activity)getTheActivityDef().instantiate();
+ configureInstance(newActivity);
+ if (newActivity.getProperties().getAbstract().size() > 0) {
+ throw new InvalidDataException("Abstract properties not overridden: "+newActivity.getProperties().getAbstract().toString());
+ }
+ return newActivity;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/AndSplitDef.java b/src/main/java/org/cristalise/kernel/lifecycle/AndSplitDef.java new file mode 100644 index 0000000..6d6856a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/AndSplitDef.java @@ -0,0 +1,135 @@ +/**
+ * 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.lifecycle;
+
+import java.util.Vector;
+
+import org.cristalise.kernel.graph.model.Vertex;
+import org.cristalise.kernel.graph.traversal.GraphTraversal;
+import org.cristalise.kernel.lifecycle.instance.AndSplit;
+import org.cristalise.kernel.lifecycle.instance.WfVertex;
+
+/**
+ * @version $Revision: 1.19 $ $Date: 2005/09/29 10:18:31 $
+ * @author $Author: abranson $
+ */
+
+public class AndSplitDef extends WfVertexDef
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public AndSplitDef()
+ {
+ mErrors = new Vector<String>(0, 1);
+ getProperties().put("RoutingScriptName", "");
+ getProperties().put("RoutingScriptVersion", "");
+ }
+
+ /**
+ * @see org.cristalise.kernel.lifecycle.WfVertexDef#verify()
+ */
+ @Override
+ public boolean verify()
+ {
+ mErrors.removeAllElements();
+ boolean err = true;
+ int nbInEdges = getInEdges().length;
+ if (nbInEdges == 0 && this.getID() != getParent().getChildrenGraphModel().getStartVertexId())
+ {
+ mErrors.add("Unreachable");
+ err = false;
+ }
+ else if (nbInEdges > 1)
+ {
+ mErrors.add("Bad nb of previous");
+ err = false;
+ }
+ else
+ {
+ if (getOutEdges().length <= 1)
+ {
+ mErrors.add("not enough next");
+ err = false;
+ }
+ else if (!(this instanceof LoopDef))
+ {
+ Vertex[] outV = getOutGraphables();
+ Vertex[] anteVertices =
+ GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ boolean loop = false;
+ boolean errInLoop = true;
+ for (int i = 0; i < outV.length; i++)
+ {
+ for (int j = 0; j < anteVertices.length; j++)
+ if (!loop && outV[i].getID() == anteVertices[j].getID())
+ {
+ if (outV[i] instanceof LoopDef)
+ {
+ loop = true;
+ j = anteVertices.length;
+ i = outV.length;
+ }
+ else
+ {
+ errInLoop = false;
+ }
+ }
+ }
+ if (errInLoop && loop)
+ {
+ mErrors.add("Problem in Loop");
+ err = false;
+ }
+ }
+ }
+ return err;
+ }
+
+ @Override
+ public boolean loop()
+ {
+ boolean loop2 = false;
+ if (!loopTested)
+ {
+ loopTested = true;
+ if (getOutGraphables().length != 0)
+ {
+ Vertex[] outVertices = getOutGraphables();
+ for (int i = 0; i < outVertices.length; i++)
+ {
+ WfVertexDef tmp = (WfVertexDef) getOutGraphables()[i];
+ loop2 = loop2 || tmp.loop();
+ }
+ }
+ }
+ loopTested = false;
+ return loop2;
+ }
+
+ @Override
+ public WfVertex instantiate() {
+ AndSplit newSplit = new AndSplit();
+ configureInstance(newSplit);
+ return newSplit;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/CompositeActivityDef.java b/src/main/java/org/cristalise/kernel/lifecycle/CompositeActivityDef.java new file mode 100644 index 0000000..4341fbf --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/CompositeActivityDef.java @@ -0,0 +1,266 @@ +/**
+ * 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.lifecycle;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.graph.model.GraphModel;
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.graph.model.GraphableVertex;
+import org.cristalise.kernel.graph.model.TypeNameAndConstructionInfo;
+import org.cristalise.kernel.lifecycle.instance.CompositeActivity;
+import org.cristalise.kernel.lifecycle.instance.Next;
+import org.cristalise.kernel.lifecycle.instance.WfVertex;
+import org.cristalise.kernel.utils.Language;
+import org.cristalise.kernel.utils.Logger;
+
+/**
+ * @version $Revision: 1.93 $ $Date: 2005/10/05 07:39:36 $
+ * @author $Author: abranson $
+ */
+public class CompositeActivityDef extends ActivityDef
+{
+ private final TypeNameAndConstructionInfo[] mVertexTypeNameAndConstructionInfo =
+ {
+ new TypeNameAndConstructionInfo(Language.translate("Activity"), "Atomic"),
+ new TypeNameAndConstructionInfo(Language.translate("Composite"), "Composite"),
+ new TypeNameAndConstructionInfo(Language.translate("AND Split"), "And"),
+ new TypeNameAndConstructionInfo(Language.translate("OR Split"), "Or"),
+ new TypeNameAndConstructionInfo(Language.translate("XOR Split"), "XOr"),
+ new TypeNameAndConstructionInfo(Language.translate("Join"), "Join"),
+ new TypeNameAndConstructionInfo(Language.translate("Loop"), "Loop"),
+ };
+ private final TypeNameAndConstructionInfo[] mEdgeTypeNameAndConstructionInfo =
+ {
+ new TypeNameAndConstructionInfo(Language.translate("Next Edge"), "Next")
+ };
+ public TypeNameAndConstructionInfo[] getVertexTypeNameAndConstructionInfo()
+ {
+ return mVertexTypeNameAndConstructionInfo;
+ }
+ public TypeNameAndConstructionInfo[] getEdgeTypeNameAndConstructionInfo()
+ {
+ return mEdgeTypeNameAndConstructionInfo;
+ }
+
+ public CompositeActivityDef()
+ {
+ super();
+ setChildrenGraphModel(new GraphModel(new WfVertexDefOutlineCreator()));
+ setIsComposite(true);
+ }
+
+ /**
+ * Method addNextDef.
+ *
+ * @param origin
+ * @param terminus
+ * @return NextDef
+ */
+ public NextDef addNextDef(WfVertexDef origin, WfVertexDef terminus)
+ {
+ NextDef returnNxt = new NextDef(origin, terminus);
+ getChildrenGraphModel().addEdgeAndCreateId(returnNxt, origin, terminus);
+ return returnNxt;
+ }
+ /**
+ * Method addExistingActivityDef.
+ *
+ * @param actDef
+ * @param point
+ */
+ public ActivitySlotDef addExistingActivityDef(String name, ActivityDef actDef, GraphPoint point)
+ {
+ changed = true;
+ ActivitySlotDef child = new ActivitySlotDef();
+ addChild(child, point);
+ actDef.linkToSlot(child, actDef.getName(), name);
+ return child;
+ }
+ /**
+ * Method newChild.
+ *
+ * @param Name
+ * @param Type
+ * @param location
+ * @return WfVertexDef
+ */
+ public WfVertexDef newChild(String Name, String Type, GraphPoint location)
+ {
+ changed = true;
+ WfVertexDef child;
+ if (Type.equals("Or"))
+ {
+ child = new OrSplitDef();
+ addChild(child, location);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else if (Type.equals("XOr"))
+ {
+ child = new XOrSplitDef();
+ addChild(child, location);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else if (Type.equals("And"))
+ {
+ child = new AndSplitDef();
+ addChild(child, location);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else if (Type.equals("Loop"))
+ {
+ child = new LoopDef();
+ addChild(child, location);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else if (Type.equals("Atomic"))
+ {
+ child = new ActivitySlotDef();
+ ActivityDef act = new ActivityDef();
+ act.changed = true;
+ addChild(child, location);
+ act.linkToSlot((ActivitySlotDef) child, Name, Name);
+ act.getProperties().put("Description", Name);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else if (Type.equals("Join"))
+ {
+ child = new JoinDef();
+ child.getProperties().put("Type", "Join");
+ addChild(child, location);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else if (Type.equals("Route"))
+ {
+ child = new JoinDef();
+ child.getProperties().put("Type", "Route");
+ addChild(child, location);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ else
+ {
+ child = new ActivitySlotDef();
+ CompositeActivityDef act = new CompositeActivityDef();
+ act.changed = true;
+ addChild(child, location);
+ act.linkToSlot((ActivitySlotDef) child, Name, Name);
+ Logger.msg(5, Type + " " + child.getID() + " added to " + this.getID());
+ }
+ return child;
+ }
+ /**
+ * Method instantiateAct.
+ *
+ * @return CompositeActivity
+ */
+ @Override
+ public WfVertex instantiate() throws ObjectNotFoundException, InvalidDataException {
+ return instantiate(getName());
+ }
+
+ @Override
+ public WfVertex instantiate(String name) throws ObjectNotFoundException, InvalidDataException
+ {
+ CompositeActivity cAct = new CompositeActivity();
+ configureInstance(cAct);
+ cAct.setType(getName());
+ cAct.setName(name);
+ GraphableVertex[] vertexDefs = getLayoutableChildren();
+ WfVertex[] wfVertices = new WfVertex[vertexDefs.length];
+ for (int i = 0; i < vertexDefs.length; i++)
+ {
+ WfVertexDef vertDef = (WfVertexDef)vertexDefs[i];
+ wfVertices[i] = vertDef.instantiate();
+ wfVertices[i].setParent(cAct);
+ }
+ Next[] nexts = new Next[getChildrenGraphModel().getEdges().length];
+ for (int i = 0; i < getChildrenGraphModel().getEdges().length; i++)
+ {
+ NextDef nextDef = (NextDef) getChildrenGraphModel().getEdges()[i];
+ nexts[i] = nextDef.instantiate();
+ nexts[i].setParent(cAct);
+ }
+ cAct.getChildrenGraphModel().setStartVertexId(getChildrenGraphModel().getStartVertexId());
+ cAct.getChildrenGraphModel().setEdges(nexts);
+ cAct.getChildrenGraphModel().setVertices(wfVertices);
+ cAct.getChildrenGraphModel().setNextId(getChildrenGraphModel().getNextId());
+ cAct.getChildrenGraphModel().resetVertexOutlines();
+ return cAct;
+ }
+
+ /**
+ * Method hasGoodNumberOfActivity.
+ *
+ * @return boolean
+ */
+
+ public boolean hasGoodNumberOfActivity()
+ {
+ int endingAct = 0;
+ GraphableVertex[] graphableVertices = this.getLayoutableChildren();
+ if (graphableVertices != null)
+ for (GraphableVertex graphableVertice : graphableVertices) {
+ WfVertexDef vertex = (WfVertexDef) graphableVertice;
+ if (getChildrenGraphModel().getOutEdges(vertex).length == 0)
+ endingAct++;
+ }
+ if (endingAct > 1)
+ return false;
+ return true;
+ }
+
+ /**
+ * @see org.cristalise.kernel.graph.model.GraphableVertex#getPath()
+ */
+ @Override
+ public String getPath()
+ {
+ if (getParent() == null)
+ return getName();
+ return super.getPath();
+ }
+ @Override
+ public void setChildrenGraphModel(GraphModel childrenGraph) {
+ super.setChildrenGraphModel(childrenGraph);
+ childrenGraph.setVertexOutlineCreator(new WfVertexDefOutlineCreator());
+ }
+ //deprecated
+ public String[] getCastorNonLayoutableChildren() {
+ return new String[0];
+ }
+
+ public void setCastorNonLayoutableChildren(String[] dummy) { }
+
+ @Override
+ public boolean verify() {
+ boolean err = super.verify();
+ GraphableVertex[] vChildren = getChildren();
+ for (int i = 0; i < vChildren.length; i++)
+ {
+ WfVertexDef wfvChild = (WfVertexDef)vChildren[i];
+ if (!(wfvChild.verify()))
+ {
+ mErrors.add(wfvChild.getName()+": "+wfvChild.getErrors());
+ err = false;
+ }
+ }
+ return err;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/JoinDef.java b/src/main/java/org/cristalise/kernel/lifecycle/JoinDef.java new file mode 100644 index 0000000..a198453 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/JoinDef.java @@ -0,0 +1,88 @@ +/**
+ * 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.lifecycle;
+
+import org.cristalise.kernel.lifecycle.instance.Join;
+import org.cristalise.kernel.lifecycle.instance.WfVertex;
+
+/**
+ * @version $Revision: 1.18 $ $Date: 2005/09/29 10:18:31 $
+ * @author $Author: abranson $
+ */
+public class JoinDef extends WfVertexDef
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public JoinDef()
+ {
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.WfVertexDef#verify()
+ */
+ @Override
+ public boolean verify()
+ {
+ mErrors.removeAllElements();
+ int nbOutEdges = getOutEdges().length;
+ int nbInEdges = getInEdges().length;
+ String type = (String) getProperties().get("Type");
+ if (nbInEdges < 1)
+ {
+ mErrors.add("not enough previous");
+ return false;
+ }
+ if (type != null && type.equals("Route"))
+ {
+ if (nbInEdges > 1)
+ {
+ mErrors.add("Bad nb of previous");
+ return false;
+ }
+ }
+ if (nbOutEdges > 1)
+ {
+ mErrors.add("too many next");
+ return false;
+ }
+ if (nbOutEdges == 0)
+ {
+ if (!((CompositeActivityDef) getParent()).hasGoodNumberOfActivity())
+ {
+ mErrors.add("too many endpoints");
+ return false;
+ }
+ }
+ return true;
+ }
+ @Override
+ public boolean isJoin()
+ {
+ return true;
+ }
+
+ @Override
+ public WfVertex instantiate() {
+ Join newJoin = new Join();
+ configureInstance(newJoin);
+ return newJoin;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/LoopDef.java b/src/main/java/org/cristalise/kernel/lifecycle/LoopDef.java new file mode 100644 index 0000000..96a6f3f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/LoopDef.java @@ -0,0 +1,98 @@ +/**
+ * 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.lifecycle;
+
+import org.cristalise.kernel.graph.model.Vertex;
+import org.cristalise.kernel.graph.traversal.GraphTraversal;
+import org.cristalise.kernel.lifecycle.instance.Loop;
+import org.cristalise.kernel.lifecycle.instance.WfVertex;
+
+/**
+ * @version $Revision: 1.19 $ $Date: 2005/09/29 10:18:31 $
+ * @author $Author: abranson $
+ */
+
+public class LoopDef extends XOrSplitDef
+{
+ public boolean hasLoop = false;
+ public int isNext = 0;
+
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public LoopDef()
+ {
+ super();
+ }
+
+ /**
+ * @see org.cristalise.kernel.lifecycle.WfVertexDef#loop()
+ */
+ @Override
+ public boolean loop()
+ {
+ return true;
+ }
+
+ /**
+ * @see org.cristalise.kernel.lifecycle.WfVertexDef#verify()
+ */
+ @Override
+ public boolean verify()
+ {
+ if (!super.verify()) return false;
+ Vertex[] nexts = getOutGraphables();
+ Vertex[] anteVertices =
+ GraphTraversal.getTraversal(this.getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ int k = 0;
+ int l = 0;
+ Vertex[] brothers = getParent().getChildren();
+ for (Vertex brother : brothers)
+ if (brother instanceof LoopDef) l++;
+ for (Vertex next : nexts)
+ for (Vertex anteVertice : anteVertices)
+ if (next.equals(anteVertice))
+ k++;
+ if (k != 1 && !(l>1))
+ {
+ mErrors.add("bad number of pointing back nexts");
+ return false;
+ }
+// if (nexts.length>2) {
+// mErrors.add("you must only have 2 nexts");
+// return false;
+// }
+ return true;
+ }
+
+ @Override
+ public boolean isLoop() {
+ return true;
+ }
+
+ @Override
+ public WfVertex instantiate() {
+ Loop newLoop = new Loop();
+ configureInstance(newLoop);
+ return newLoop;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/NextDef.java b/src/main/java/org/cristalise/kernel/lifecycle/NextDef.java new file mode 100644 index 0000000..463e7a4 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/NextDef.java @@ -0,0 +1,115 @@ +/**
+ * 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.lifecycle;
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.graph.model.GraphableEdge;
+import org.cristalise.kernel.lifecycle.instance.Next;
+/**
+ * @version $Revision: 1.32 $ $Date: 2006/03/03 13:52:21 $
+ * @author $Author: abranson $
+ */
+public class NextDef extends GraphableEdge
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public NextDef()
+ {
+ }
+ /**
+ * Method verify.
+ *
+ * @return boolean
+ */
+ public boolean verify()
+ {
+ return true;
+ }
+ /**
+ * Method NextDef.
+ *
+ * @param pre
+ * @param nex
+ */
+ /** create and initialize a link between an Activities */
+ public NextDef(WfVertexDef pre, WfVertexDef nex)
+ {
+ setParent(pre.getParent());
+ if (pre instanceof OrSplitDef || pre instanceof XOrSplitDef)
+ {
+ int num = pre.getOutGraphables().length;
+ try
+ {
+ num = Integer.parseInt((String) pre.getProperties().get("LastNum"));
+ }
+ catch (Exception e)
+ {
+ }
+ getProperties().put("Alias", String.valueOf(num));
+ pre.getProperties().put("LastNum", String.valueOf(num + 1));
+ }
+ }
+ @Override
+ public boolean containsPoint(GraphPoint p)
+ {
+ GraphPoint originPoint = getOriginPoint();
+ GraphPoint terminusPoint = getTerminusPoint();
+ GraphPoint midPoint = new GraphPoint();
+ if (("Broken +".equals(getProperties().get("Type"))))
+ {
+ midPoint.x = (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = (originPoint.y + terminusPoint.y) / 2;
+ }
+ else if (("Broken -".equals(getProperties().get("Type"))))
+ {
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? terminusPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : originPoint.y;
+ }
+ else if (("Broken |".equals(getProperties().get("Type"))))
+ {
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? originPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : terminusPoint.y;
+ }
+ else
+ {
+ midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x) / 2;
+ midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y) / 2;
+ }
+ int minX = midPoint.x - 10;
+ int minY = midPoint.y - 10;
+ int maxX = midPoint.x + 10;
+ int maxY = midPoint.y + 10;
+ return (p.x >= minX) && (p.x <= maxX) && (p.y >= minY) && (p.y <= maxY);
+ }
+
+ public Next instantiate() {
+ Next next = new Next();
+ next.setID(getID());
+ next.setOriginVertexId(getOriginVertexId());
+ next.setTerminusVertexId(getTerminusVertexId());
+ next.setProperties(getProperties());
+ next.setOriginPoint(getOriginPoint());
+ next.setTerminusPoint(getTerminusPoint());
+ return next;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/OrSplitDef.java b/src/main/java/org/cristalise/kernel/lifecycle/OrSplitDef.java new file mode 100644 index 0000000..c51c5fa --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/OrSplitDef.java @@ -0,0 +1,44 @@ +/**
+ * 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.lifecycle;
+import org.cristalise.kernel.lifecycle.instance.OrSplit;
+import org.cristalise.kernel.lifecycle.instance.WfVertex;
+/**
+ * @version $Revision: 1.13 $ $Date: 2005/12/01 14:23:15 $
+ * @author $Author: abranson $
+ */
+public class OrSplitDef extends AndSplitDef
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public OrSplitDef()
+ {
+ super();
+ }
+
+ @Override
+ public WfVertex instantiate() {
+ OrSplit newSplit = new OrSplit();
+ configureInstance(newSplit);
+ return newSplit;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/WfCastorHashMap.java b/src/main/java/org/cristalise/kernel/lifecycle/WfCastorHashMap.java new file mode 100644 index 0000000..e30e9c3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/WfCastorHashMap.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.lifecycle;
+import org.cristalise.kernel.utils.CastorHashMap;
+/**
+ * @version $Revision: 1.29 $ $Date: 2005/05/20 13:07:13 $
+ * @author $Author: abranson $
+ */
+public class WfCastorHashMap extends CastorHashMap
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public WfCastorHashMap()
+ {
+ put("Show time", true);
+ put("Breakpoint", false);
+ put("Description", "");
+ put("Agent Role", "");
+ put("Agent Name", "");
+ put("SchemaType", "");
+ put("SchemaVersion", "");
+ put("ScriptName", "");
+ put("ScriptVersion", "");
+ put("StateMachineName", "Default");
+ put("StateMachineVersion", 0);
+ put("Viewpoint", "");
+ put("OutcomeInit", "");
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/WfVertexDef.java b/src/main/java/org/cristalise/kernel/lifecycle/WfVertexDef.java new file mode 100644 index 0000000..939423a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/WfVertexDef.java @@ -0,0 +1,112 @@ +/**
+ * 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.lifecycle;
+
+import java.util.Vector;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.graph.model.GraphableVertex;
+import org.cristalise.kernel.lifecycle.instance.WfVertex;
+import org.cristalise.kernel.utils.KeyValuePair;
+
+
+/**
+ * @version $Revision: 1.22 $ $Date: 2005/11/15 15:56:38 $
+ * @author $Author: abranson $
+ */
+public abstract class WfVertexDef extends GraphableVertex
+{
+ public Vector<String> mErrors;
+
+ protected boolean loopTested;
+
+ /**
+ * @see java.lang.Object#Object()
+ */
+ /** @label wf */
+ public WfVertexDef()
+ {
+ mErrors = new Vector<String>(0, 1);
+ setIsLayoutable(true);
+ }
+
+ public abstract WfVertex instantiate() throws ObjectNotFoundException, InvalidDataException;
+
+ public void configureInstance(WfVertex newVertex) {
+ KeyValuePair[] k = getProperties().getKeyValuePairs();
+ for (KeyValuePair element : k)
+ newVertex.getProperties().put(element.getKey(), element.getValue(), element.isAbstract());
+ newVertex.setID(getID());
+ if (getIsLayoutable()) {
+ newVertex.setInEdgeIds(getInEdgeIds());
+ newVertex.setOutEdgeIds(getOutEdgeIds());
+ newVertex.setCentrePoint(getCentrePoint());
+ newVertex.setOutlinePoints(getOutlinePoints());
+ }
+ }
+
+ /**
+ * Method verify.
+ *
+ * @return boolean
+ */
+ public abstract boolean verify();
+
+ /**
+ * Method getErrors.
+ *
+ * @return String
+ */
+ public String getErrors()
+ {
+ if (mErrors.size() == 0)
+ return "No error";
+ else if (mErrors.size() == 1)
+ return mErrors.elementAt(0);
+ else {
+ StringBuffer errorBuffer = new StringBuffer();
+ for (String error : mErrors) {
+ if (errorBuffer.length() > 0) errorBuffer.append("\n");
+ errorBuffer.append(error);
+ }
+ return errorBuffer.toString();
+ }
+ }
+
+ /**
+ * Method loop.
+ *
+ * @return boolean
+ */
+ public boolean loop()
+ {
+ boolean loop2 = false;
+ if (!loopTested)
+ {
+ loopTested = true;
+ if (getOutGraphables().length != 0)
+ loop2 = ((WfVertexDef) getOutGraphables()[0]).loop();
+ }
+ loopTested = false;
+ return loop2;
+ }
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/WfVertexDefOutlineCreator.java b/src/main/java/org/cristalise/kernel/lifecycle/WfVertexDefOutlineCreator.java new file mode 100644 index 0000000..1bb8e2e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/WfVertexDefOutlineCreator.java @@ -0,0 +1,70 @@ +/**
+ * 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.lifecycle;
+
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.graph.model.Vertex;
+import org.cristalise.kernel.graph.model.VertexOutlineCreator;
+
+public class WfVertexDefOutlineCreator implements VertexOutlineCreator
+{
+ private static final int mActivityWidth = 130;
+ private static final int mActivityHeight = 60;
+ private static final int mSplitJoinWidth = 60;
+ private static final int mSplitJoinHeight = 25;
+
+ @Override
+ public void setOutline(Vertex vertex)
+ {
+ GraphPoint centrePoint = vertex.getCentrePoint();
+ GraphPoint[] outlinePoints = new GraphPoint[ 4 ];
+ int vertexWidth = 0;
+ int vertexHeight = 0;
+
+
+ if ( vertex instanceof ActivitySlotDef )
+ {
+ vertexWidth = mActivityWidth;
+ vertexHeight = mActivityHeight;
+ }
+ else
+ {
+ vertexWidth = mSplitJoinWidth;
+ vertexHeight = mSplitJoinHeight;
+ }
+
+ outlinePoints[ 0 ] = new GraphPoint();
+ outlinePoints[ 0 ].x = centrePoint.x - vertexWidth / 2;
+ outlinePoints[ 0 ].y = centrePoint.y - vertexHeight / 2;
+ outlinePoints[ 1 ] = new GraphPoint();
+ outlinePoints[ 1 ].x = centrePoint.x + vertexWidth / 2;
+ outlinePoints[ 1 ].y = centrePoint.y - vertexHeight / 2;
+ outlinePoints[ 2 ] = new GraphPoint();
+ outlinePoints[ 2 ].x = centrePoint.x + vertexWidth / 2;
+ outlinePoints[ 2 ].y = centrePoint.y + vertexHeight / 2;
+ outlinePoints[ 3 ] = new GraphPoint();
+ outlinePoints[ 3 ].x = centrePoint.x - vertexWidth / 2;
+ outlinePoints[ 3 ].y = centrePoint.y + vertexHeight / 2;
+
+ vertex.setOutlinePoints( outlinePoints );
+ }
+}
+
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/XOrSplitDef.java b/src/main/java/org/cristalise/kernel/lifecycle/XOrSplitDef.java new file mode 100644 index 0000000..7754c52 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/XOrSplitDef.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.lifecycle;
+
+import org.cristalise.kernel.lifecycle.instance.WfVertex;
+import org.cristalise.kernel.lifecycle.instance.XOrSplit;
+
+
+/**
+ * @version $Revision: 1.14 $ $Date: 2005/09/29 10:18:31 $
+ * @author $Author: abranson $
+ */
+
+public class XOrSplitDef extends AndSplitDef
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public XOrSplitDef()
+ {
+ super();
+ }
+
+ @Override
+ public WfVertex instantiate() {
+ XOrSplit newSplit = new XOrSplit();
+ configureInstance(newSplit);
+ return newSplit;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/Activity.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/Activity.java new file mode 100644 index 0000000..f04a7a9 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/Activity.java @@ -0,0 +1,573 @@ +/**
+ * 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.lifecycle.instance;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Vector;
+
+import org.cristalise.kernel.common.AccessRightsException;
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.GTimeStamp;
+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.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.agent.Job;
+import org.cristalise.kernel.events.Event;
+import org.cristalise.kernel.events.History;
+import org.cristalise.kernel.graph.model.Vertex;
+import org.cristalise.kernel.lifecycle.WfCastorHashMap;
+import org.cristalise.kernel.lifecycle.instance.stateMachine.State;
+import org.cristalise.kernel.lifecycle.instance.stateMachine.StateMachine;
+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.ItemPath;
+import org.cristalise.kernel.lookup.Path;
+import org.cristalise.kernel.lookup.RolePath;
+import org.cristalise.kernel.persistency.outcome.Outcome;
+import org.cristalise.kernel.persistency.outcome.Schema;
+import org.cristalise.kernel.persistency.outcome.Viewpoint;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.DateUtility;
+import org.cristalise.kernel.utils.LocalObjectLoader;
+import org.cristalise.kernel.utils.Logger;
+
+/**
+ * @version $Revision: 1.222 $ $Date: 2005/10/05 07:39:37 $
+ * @author $Author: abranson $
+ */
+public class Activity extends WfVertex
+{
+ /**
+ * vector of errors (Strings) that is constructed each time verify() is launched
+ */
+ protected Vector<String> mErrors;
+ /** @associates a State machine engine */
+ private StateMachine machine;
+ protected int state = -1;
+ /** true is available to be executed */
+ public boolean active = false;
+ /** used in verify() */
+ private boolean loopTested;
+ private GTimeStamp mStateDate;
+ private String mType;
+
+ public Activity()
+ {
+ super();
+ setProperties(new WfCastorHashMap());
+ getProperties().put("StateMachineName", getDefaultSMName());
+ mErrors = new Vector<String>(0, 1);
+ mStateDate = new GTimeStamp();
+ DateUtility.setToNow(mStateDate);
+ }
+
+ protected String getDefaultSMName() {
+ return "Default";
+ }
+
+ /** add the activity which id is idNext as next of the current one */
+ void addNext(String idNext)
+ {
+ new Next(this, (WfVertex) getParent().search(idNext));
+ }
+ /**
+ * adds a New link between the current Activity and the WfVertex passed in param
+ */
+ @Override
+ public Next addNext(WfVertex vertex)
+ {
+ return new Next(this, vertex);
+ }
+
+ public StateMachine getStateMachine() throws InvalidDataException {
+ if (machine == null) {
+ String name = (String)getProperties().get("StateMachineName");
+ int version = getVersionNumberProperty("StateMachineVersion");
+ try {
+ machine = LocalObjectLoader.getStateMachine(name, version);
+ } catch (ObjectNotFoundException ex) {
+ if (name.equals(getDefaultSMName()) && version == 0) { // default state machine not imported yet. Fake it.
+ try {
+ String marshalledSM = Gateway.getResource().getTextResource(null, "boot/SM/"+getDefaultSMName()+".xml");
+ StateMachine bootstrap = (StateMachine)Gateway.getMarshaller().unmarshall(marshalledSM);
+ bootstrap.validate();
+ machine = bootstrap;
+ return bootstrap;
+ } catch (Exception ex2) {
+ Logger.error(ex2);
+ throw new InvalidDataException("Could not bootstrap default state machine from resources.");
+ }
+ }
+ Logger.error(ex);
+ throw new InvalidDataException("Error loading state machine '"+name+"' v"+version);
+ }
+ }
+ return machine;
+ }
+
+ /** return the current State of the State machine (Used in Serialisation) */
+ public int getState() throws InvalidDataException
+ {
+ if (state == -1)
+ state = getStateMachine().getInitialStateCode();
+ return state;
+ }
+ public String getStateName() throws InvalidDataException
+ {
+ return getStateMachine().getState(getState()).getName();
+ }
+
+ /** Sets a new State */
+ public void setState(int state)
+ {
+ this.state = state;
+ }
+
+ public boolean isFinished() throws InvalidDataException {
+ return getStateMachine().getState(getState()).isFinished();
+ }
+
+
+ /** cf Item request
+ * @throws ObjectNotFoundException
+ * @throws PersistencyException
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectCannotBeUpdated
+ * @throws CannotManageException
+ * @throws InvalidCollectionModification */
+ public String request(AgentPath agent, ItemPath itemPath, int transitionID, String requestData) throws AccessRightsException, InvalidTransitionException, InvalidDataException, ObjectNotFoundException, PersistencyException, ObjectAlreadyExistsException, ObjectCannotBeUpdated, CannotManageException, InvalidCollectionModification
+ {
+
+ // Find requested transition
+ Transition transition = getStateMachine().getTransition(transitionID);
+
+ // Check if the transition is possible
+ String usedRole = transition.getPerformingRole(this, agent);
+
+ // Verify outcome
+ Schema schema = null;
+ String viewName = null;
+ boolean storeOutcome = false;
+ if (transition.hasOutcome(getProperties())) {
+ schema = transition.getSchema(getProperties());
+ viewName = (String)getProperties().get("Viewpoint");
+ if (requestData != null && requestData.length()>0)
+ storeOutcome = true;
+ else if (transition.getOutcome().isRequired())
+ throw new InvalidDataException("Transition requires outcome data, but none was given");
+ }
+
+ // Get new state
+ State newState = getStateMachine().traverse(this, transition, agent);
+
+ // Run extra logic in predefined steps here
+ String outcome = runActivityLogic(agent, itemPath, transitionID, requestData);
+
+ // set new state and reservation
+ setState(newState.getId());
+ getProperties().put("Agent Name", transition.getReservation(this, agent));
+
+ // store new event
+ Event newEvent = null;
+ try {
+ History hist = getWf().getHistory();
+ if (storeOutcome)
+ newEvent = hist.addEvent(agent, usedRole, getName(), getPath(), getType(), schema.docType, schema.docVersion,
+ getStateMachine().getName(), getStateMachine().getVersion(), transition, viewName);
+ else
+ newEvent = hist.addEvent(agent, usedRole, getName(), getPath(), getType(),
+ getStateMachine().getName(), getStateMachine().getVersion(), transition);
+
+ Logger.msg(7, "Activity::auditEvent() - Event:" + newEvent.getName() + " was added to the AuditTrail");
+
+ if (storeOutcome) {
+ Outcome newOutcome = new Outcome(newEvent.getID(), outcome, schema.docType, schema.docVersion);
+ Gateway.getStorage().put(itemPath, newOutcome, getWf());
+
+ // update specific view if defined
+ if (viewName != null && !viewName.equals("")) {
+ Viewpoint currentView = new Viewpoint(itemPath, schema.docType, viewName, schema.docVersion, newEvent.getID());
+ Gateway.getStorage().put(itemPath, currentView, getWf());
+ }
+ // update last view
+ Viewpoint currentView = new Viewpoint(itemPath, schema.docType, "last", schema.docVersion, newEvent.getID());
+ Gateway.getStorage().put(itemPath, currentView, getWf());
+ }
+ Gateway.getStorage().commit(getWf());
+ } catch (PersistencyException ex) {
+ Logger.error(ex);
+ Gateway.getStorage().abort(getWf());
+ throw ex;
+ }
+
+ if (newState.isFinished()) {
+ if (!getProperties().get("Breakpoint").equals(Boolean.TRUE))
+ runNext(agent, itemPath);
+ }
+
+ DateUtility.setToNow(mStateDate);
+
+ //refresh all the job lists
+ String agentRole = getCurrentAgentRole();
+ if (agentRole != null && agentRole.length()>0) {
+ try {
+ RolePath myRole = Gateway.getLookup().getRolePath(agentRole);
+ pushJobsToAgents(itemPath, myRole);
+ } catch (ObjectNotFoundException ex) { // non-existent role
+ Logger.msg(7, "Activity.pushJobsToAgents() - Activity role '"+agentRole+" not found.");
+ }
+ }
+
+
+ return outcome;
+ }
+
+ protected String runActivityLogic(AgentPath agent, ItemPath itemPath,
+ int transitionID, String requestData) throws
+ InvalidDataException,
+ InvalidCollectionModification,
+ ObjectAlreadyExistsException,
+ ObjectCannotBeUpdated,
+ ObjectNotFoundException,
+ PersistencyException,
+ CannotManageException
+ {
+ // Overriden in predefined steps
+ return requestData;
+ }
+
+ @Override
+ public boolean verify()
+ {
+ mErrors.removeAllElements();
+ int nbInEdgres = getInEdges().length;
+ int nbOutEdges = getOutEdges().length;
+ if (nbInEdgres == 0 && this.getID() != getParent().getChildrenGraphModel().getStartVertexId())
+ {
+ mErrors.add("Unreachable");
+ return false;
+ }
+ else if (nbInEdgres > 1)
+ {
+ mErrors.add("Bad nb of previous");
+ return false;
+ }
+ else if (nbOutEdges > 1)
+ {
+ mErrors.add("too many next");
+ return false;
+ }
+ else if (nbOutEdges == 0)
+ {
+ if (!((CompositeActivity) getParent()).hasGoodNumberOfActivity())
+ {
+ mErrors.add("too many endpoints");
+ return false;
+ }
+ }
+// else
+// {
+// Vertex[] outV = getOutGraphables();
+// Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+// boolean errInLoop = false;
+// for (int i = 0; i < outV.length; i++)
+// {
+// for (int j = 0; j < anteVertices.length; j++)
+// if (!loop() && outV[i].getID() == anteVertices[j].getID())
+// errInLoop = true;
+// }
+// if (errInLoop)
+// {
+// mErrors.add("Error In Loop");
+// return false;
+// }
+// }
+ return true;
+ }
+ /** Used in verify() */
+ @Override
+ public boolean loop()
+ {
+ boolean loop2 = false;
+ if (!loopTested)
+ {
+ loopTested = true;
+ if (getOutGraphables().length != 0)
+ loop2 = ((WfVertex) getOutGraphables()[0]).loop();
+ }
+ loopTested = false;
+ return loop2;
+ }
+ /** sets the next activity available if possible
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws PersistencyException
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectCannotBeUpdated */
+ @Override
+ public void runNext(AgentPath agent, ItemPath itemPath) throws InvalidDataException
+ {
+ setActive(false);
+ try
+ {
+ Vertex[] outVertices = getOutGraphables();
+ Vertex[] outVertices2 = getOutGraphables();
+ boolean hasNoNext = false;
+ boolean out = false;
+ while (!out)
+ if (outVertices2.length > 0)
+ {
+ if (outVertices2[0] instanceof Join)
+ outVertices2 = ((WfVertex) outVertices2[0]).getOutGraphables();
+ else
+ out = true;
+ }
+ else
+ {
+ hasNoNext = true;
+ out = true;
+ }
+ Logger.debug(8, Arrays.toString(outVertices) + " " + Arrays.toString(outVertices2));
+ if (!hasNoNext)
+ ((WfVertex) outVertices[0]).run(agent, itemPath);
+ else
+ {
+ if (getParent() != null && getParent().getName().equals("domain")) // workflow
+ // finished
+ setActive(true);
+ else
+ {
+ CompositeActivity parent = (CompositeActivity) getParent();
+ if (parent != null)
+ parent.runNext(agent, itemPath);
+ }
+ }
+ }
+ catch (InvalidDataException s)
+ {
+ setActive(true);
+ throw s;
+ }
+ }
+ /** @return the only Next of the Activity */
+ public Next getNext()
+ {
+ if (getOutEdges().length > 0)
+ return (Next) getOutEdges()[0];
+ else
+ return null;
+ }
+ /** reinitialises the Activity and propagate (for Loop)
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException */
+ @Override
+ public void reinit(int idLoop) throws InvalidDataException
+ {
+ Vertex[] outVertices = getOutGraphables();
+ setState(getStateMachine().getInitialState().getId());
+ if (outVertices.length > 0)
+ {
+ WfVertex nextAct = (WfVertex) outVertices[0];
+ nextAct.reinit(idLoop);
+ }
+ }
+ /** return the String that identifies the errors found in th activity */
+ @Override
+ public String getErrors()
+ {
+ if (mErrors.size() == 0)
+ return "No error";
+ return mErrors.elementAt(0);
+ }
+ /**
+ * called by precedent Activity runNext() for setting the activity able to be executed
+ * @throws InvalidDataException
+ * @throws ObjectAlreadyExistsException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws ObjectNotFoundException
+ * @throws PersistencyException
+ * @throws ObjectCannotBeUpdated
+ */
+ @Override
+ public void run(AgentPath agent, ItemPath itemPath) throws InvalidDataException
+ {
+ Logger.debug(8, getPath() + " run " + getState());
+
+ if (!getActive()) setActive(true);
+ boolean finished = getStateMachine().getState(getState()).isFinished();
+ if (finished)
+ {
+ runNext(agent, itemPath);
+ }
+ else
+ {
+ DateUtility.setToNow(mStateDate);
+ pushJobsToAgents(itemPath);
+ }
+ }
+ /**
+ * sets the activity available to be executed on start of Workflow or composite activity (when it is the first one of the (sub)process
+ * @throws InvalidDataException
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws PersistencyException
+ * @throws ObjectCannotBeUpdated
+ */
+ @Override
+ public void runFirst(AgentPath agent, ItemPath itemPath) throws InvalidDataException
+ {
+ Logger.debug(8, getPath() + " runfirst");
+ run(agent, itemPath);
+ }
+ /** @return the current ability to be executed */
+ public boolean getActive()
+ {
+ return active;
+ }
+ /** sets the ability to be executed */
+ public void setActive(boolean acti)
+ {
+ active = acti;
+ }
+ /** @return the Description field of properties */
+ public String getDescription()
+ {
+ if (getProperties().containsKey("Description"))
+ return (String) (getProperties().get("Description"));
+ return "No description";
+ }
+ public String getCurrentAgentName()
+ {
+ return (String) getProperties().get("Agent Name");
+ }
+ public String getCurrentAgentRole()
+ {
+ return (String) getProperties().get("Agent Role");
+ }
+
+ /**
+ * returns the lists of jobs for the activity and children (cf org.cristalise.kernel.entity.Job)
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ * @throws InvalidAgentPathException
+ */
+ public ArrayList<Job> calculateJobs(AgentPath agent, ItemPath itemPath, boolean recurse) throws InvalidAgentPathException, ObjectNotFoundException, InvalidDataException
+ {
+ return calculateJobsBase(agent, itemPath, false);
+ } //
+ public ArrayList<Job> calculateAllJobs(AgentPath agent, ItemPath itemPath, boolean recurse) throws InvalidAgentPathException, ObjectNotFoundException, InvalidDataException
+ {
+ return calculateJobsBase(agent, itemPath, true);
+ }
+ private ArrayList<Job> calculateJobsBase(AgentPath agent, ItemPath itemPath, boolean includeInactive) throws ObjectNotFoundException, InvalidDataException, InvalidAgentPathException
+ {
+ Logger.msg(7, "calculateJobs - " + getPath());
+ ArrayList<Job> jobs = new ArrayList<Job>();
+ Map<Transition, String> transitions;
+ if ((includeInactive || getActive()) && !getName().equals("domain")) {
+ transitions = getStateMachine().getPossibleTransitions(this, agent);
+ Logger.msg(7, "Activity.calculateJobs() - Got " + transitions.size() + " transitions.");
+ for (Transition transition : transitions.keySet()) {
+ Logger.msg(7, "Creating Job object for transition " + transition);
+ jobs.add(new Job(this, itemPath, transition, agent, transitions.get(transition)));
+ }
+ }
+ return jobs;
+ }
+
+
+ public void pushJobsToAgents(ItemPath itemPath) {
+ String agentRole = getCurrentAgentRole();
+ if (agentRole != null && agentRole.length()>0) {
+ try {
+ RolePath myRole = Gateway.getLookup().getRolePath(agentRole);
+ pushJobsToAgents(itemPath, myRole);
+ } catch (ObjectNotFoundException ex) { // non-existent role
+ Logger.msg(7, "Activity.pushJobsToAgents() - Activity role '"+agentRole+" not found.");
+ }
+ }
+ }
+
+ public void pushJobsToAgents(ItemPath itemPath, RolePath role)
+ {
+ if (role.hasJobList())
+ new JobPusher(this, itemPath, role).start();
+ Iterator<Path> childRoles = role.getChildren();
+ while (childRoles.hasNext()) {
+ RolePath childRole = (RolePath)childRoles.next();
+ pushJobsToAgents(itemPath, childRole);
+ }
+ }
+
+ /**
+ * Returns the startDate.
+ *
+ * @return GTimeStamp
+ */
+ public GTimeStamp getStateDate()
+ {
+ return mStateDate;
+ }
+ public void setStateDate(GTimeStamp startDate)
+ {
+ mStateDate = startDate;
+ }
+
+ @Deprecated
+ public void setActiveDate(GTimeStamp date)
+ { }
+ @Deprecated
+ public void setStartDate(GTimeStamp date)
+ {
+ setStateDate(date);
+ }
+
+ /**
+ * Returns the type.
+ *
+ * @return String
+ */
+ public String getType()
+ {
+ return mType;
+ } /**
+ * Sets the type.
+ *
+ * @param type
+ * The type to set
+ */
+ public void setType(String type)
+ {
+ mType = type;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/AdvancementCalculator.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/AdvancementCalculator.java new file mode 100644 index 0000000..f040181 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/AdvancementCalculator.java @@ -0,0 +1,243 @@ +/**
+ * 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
+ */
+/* Created on 11 mars 2004 */
+package org.cristalise.kernel.lifecycle.instance;
+import java.util.Hashtable;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.graph.model.Vertex;
+
+//import org.cristalise.kernel.utils.Logger;
+/** @author XSeb74 */
+public class AdvancementCalculator
+{
+ private CompositeActivity activity;
+ private Hashtable<Vertex, Object> isMarked;
+ private Hashtable<Vertex, Vertex> HasNextMarked;
+ public Hashtable<String, Vertex> hasprevActive;
+ private long mCurrentNbActExp = 0;
+ private long mMaximuNbActexp = 0;
+ private long mNbActpassed = 0;
+ private long mNbActpassedWithCurrent = 0;
+ private long mNbActLeftWithCurrent = 0;
+ private long mNbActLeftWithoutCurrent = 0;
+ private boolean mIsbranchActive = false;
+ private boolean mIsbranchFinished = true;
+ private boolean mHasPrevActive = false;
+ public AdvancementCalculator()
+ {
+ isMarked = new Hashtable<Vertex, Object>();
+ HasNextMarked = new Hashtable<Vertex, Vertex>();
+ hasprevActive = new Hashtable<String, Vertex>();
+ }
+ public void calculate(CompositeActivity act) throws InvalidDataException
+ {
+// Logger.debug(0, act.getName()+" >>>>>>>>>");
+ if (act instanceof Workflow)
+ {
+ calculate((CompositeActivity) act.search("workflow/domain"));
+ return;
+ }
+ activity = act;
+ Vertex v = activity.getChildGraphModel().getStartVertex();
+ check(v, this);
+ isMarked = new Hashtable<Vertex, Object>();
+ calc(v, this);
+// Logger.debug(0, act.getName()+" <<<<<<<<<");
+ }
+ private void check(Vertex v, AdvancementCalculator current)
+ {
+ current.isMarked.put(v, "");
+ Vertex[] nexts = current.activity.getChildGraphModel().getOutVertices(v);
+ for (Vertex next : nexts)
+ if (current.isMarked.get(next) != null)
+ current.HasNextMarked.put(v, next);
+ else
+ check(next, current);
+ int j=0;
+ for (Vertex next : nexts)
+ if (current.HasNextMarked.get(next) != null)
+ j++;
+ if (j != 0 && j==nexts.length) current.HasNextMarked.put(v, nexts[0]);
+ }
+ private void calc(Vertex v, AdvancementCalculator current) throws InvalidDataException
+ {
+ if (current.isMarked.get(v) != null && !(v instanceof Join))
+ return;
+ if (v instanceof Activity)
+ {
+ current.isMarked.put(v, current);
+ Activity act = (Activity) v;
+ if (v instanceof CompositeActivity)
+ {
+ CompositeActivity cact = (CompositeActivity) v;
+ AdvancementCalculator adv = new AdvancementCalculator();
+ adv.isMarked = current.isMarked;
+ adv.HasNextMarked = current.HasNextMarked;
+ adv.calculate(cact);
+ current.mCurrentNbActExp += adv.mCurrentNbActExp;
+ current.mMaximuNbActexp += adv.mMaximuNbActexp;
+ current.mNbActpassed += adv.mNbActpassed;
+ current.mNbActpassedWithCurrent += adv.mNbActpassedWithCurrent;
+ current.mIsbranchActive = current.mIsbranchActive || adv.mIsbranchActive || act.getActive();
+ current.mNbActLeftWithCurrent += adv.mNbActLeftWithCurrent;
+ current.mNbActLeftWithoutCurrent += adv.mNbActLeftWithoutCurrent;
+ current.mHasPrevActive |= adv.mHasPrevActive || act.getActive() || adv.hasprevActive.size()!=0;
+ }
+ else
+ {
+ current.mCurrentNbActExp += 1;
+ current.mMaximuNbActexp += 1;
+ if (act.isFinished())
+ {
+ current.mNbActpassed += 1;
+ current.mNbActpassedWithCurrent += 1;
+ }
+ else if (act.getActive())
+ {
+ current.mIsbranchActive = true;
+ current.mIsbranchFinished = false;
+ current.mHasPrevActive = true;
+ current.mNbActpassedWithCurrent += 1;
+ current.mNbActLeftWithCurrent += 1;
+ }
+ else
+ {
+ current.mIsbranchFinished = false;
+ current.mNbActLeftWithCurrent += 1;
+ current.mNbActLeftWithoutCurrent += 1;
+ }
+ }
+ }
+ Vertex[] nexts = current.activity.getChildGraphModel().getOutVertices(v);
+ if (v instanceof Split)
+ {
+ current.isMarked.put(v, current);
+ AdvancementCalculator[] advs = new AdvancementCalculator[nexts.length];
+ for (int i = 0; i < nexts.length; i++)
+ {
+ advs[i] = new AdvancementCalculator();
+ advs[i].mHasPrevActive = current.mHasPrevActive;
+ advs[i].isMarked = current.isMarked;
+ advs[i].HasNextMarked = current.HasNextMarked;
+ advs[i].activity = current.activity;
+ if ((v instanceof Loop) && (current.HasNextMarked.get(nexts[i]) != null))
+// Logger.debug(0, v.getID() + " " + nexts[i].getID() + " HasNextMarked")
+ ;
+ else
+ calc(nexts[i], advs[i]);
+ }
+ long maximuNbActexp = 0;
+ long currentNbActExp = 0;
+ long NbActpassed = 0;
+ long NbActpassedWithCurrent = 0;
+ long NbActLeftWithCurrent = 0;
+ long NbActLeftWithoutCurrent = 0;
+ boolean hasNobranchFinished = true;
+ boolean hasNoBranchActive = true;
+ for (AdvancementCalculator adv : advs) {
+ if (adv.mIsbranchActive)
+ hasNoBranchActive = false;
+ if (adv.mIsbranchFinished)
+ hasNobranchFinished = false;
+ }
+ for (AdvancementCalculator adv : advs) {
+
+ if (maximuNbActexp < adv.mMaximuNbActexp)
+ maximuNbActexp = adv.mMaximuNbActexp;
+ if (adv.mIsbranchActive || adv.mIsbranchFinished || (hasNoBranchActive && hasNobranchFinished))
+ {
+ if (NbActpassed < adv.mNbActpassed)
+ NbActpassed = adv.mNbActpassed;
+ if (NbActpassedWithCurrent < adv.mNbActpassedWithCurrent)
+ NbActpassedWithCurrent = adv.mNbActpassedWithCurrent;
+ if (NbActLeftWithCurrent < adv.mNbActLeftWithCurrent)
+ NbActLeftWithCurrent = adv.mNbActLeftWithCurrent;
+ if (NbActLeftWithoutCurrent < adv.mNbActLeftWithoutCurrent)
+ NbActLeftWithoutCurrent += adv.mNbActLeftWithoutCurrent;
+ if (currentNbActExp < adv.mCurrentNbActExp)
+ currentNbActExp = adv.mCurrentNbActExp;
+ }
+ }
+ current.mCurrentNbActExp += currentNbActExp;
+ current.mNbActpassedWithCurrent += NbActpassedWithCurrent;
+ current.mMaximuNbActexp += maximuNbActexp;
+ current.mNbActpassed += NbActpassed;
+ current.mIsbranchActive = current.mIsbranchActive || !hasNoBranchActive;
+ current.mNbActLeftWithCurrent += NbActLeftWithCurrent;
+ current.mNbActLeftWithoutCurrent += NbActLeftWithoutCurrent;
+ return;
+ }
+ if (v instanceof Join)
+ {
+ AdvancementCalculator adv;
+ if (current.isMarked.get(v) == null)
+ {
+ adv = new AdvancementCalculator();
+ adv.isMarked = current.isMarked;
+ adv.HasNextMarked = current.HasNextMarked;
+ adv.activity = current.activity;
+ adv.mHasPrevActive = current.mHasPrevActive;
+ current.isMarked.put(v, adv);
+ if (nexts.length == 1)
+ calc(nexts[0], adv);
+ }
+ else
+ adv = (AdvancementCalculator) current.isMarked.get(v);
+ current.mCurrentNbActExp += adv.mCurrentNbActExp;
+ current.mMaximuNbActexp += adv.mMaximuNbActexp;
+ current.mNbActpassed += adv.mNbActpassed;
+ current.mNbActpassedWithCurrent += adv.mNbActpassedWithCurrent;
+ current.mIsbranchActive = current.mIsbranchActive || (current.mMaximuNbActexp == 0 && adv.mIsbranchActive);
+ if (current.mHasPrevActive)
+ hasprevActive.put(String.valueOf(v.getID()), v);
+ current.mNbActLeftWithCurrent += adv.mNbActLeftWithCurrent;
+ current.mNbActLeftWithoutCurrent += adv.mNbActLeftWithoutCurrent;
+ return;
+ }
+ if (nexts.length != 0)
+ calc(nexts[0], current);
+ }
+ public long getLongestWayInAct()
+ {
+ return mMaximuNbActexp;
+ }
+ public long getCurrentLongestWayInAct()
+ {
+ return mCurrentNbActExp;
+ }
+ public long getNbActLeftWithActive()
+ {
+ return mNbActLeftWithCurrent;
+ }
+ public long getNbActLeftWithoutActive()
+ {
+ return mNbActLeftWithoutCurrent;
+ }
+ public long getNbActPassedWithoutActive()
+ {
+ return mNbActpassed;
+ }
+ public long getNbActPassedWithActive()
+ {
+ return mNbActpassedWithCurrent;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/AndSplit.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/AndSplit.java new file mode 100644 index 0000000..98e9afb --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/AndSplit.java @@ -0,0 +1,49 @@ +/**
+ * 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.lifecycle.instance;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.graph.model.Vertex;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+
+/**
+ * @version $Revision: 1.16 $ $Date: 2005/05/10 15:14:54 $
+ * @author $Author: abranson $
+ */
+public class AndSplit extends Split
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public AndSplit()
+ {
+ super();
+ }
+ @Override
+ public void runNext(AgentPath agent, ItemPath item) throws InvalidDataException
+ {
+ AdvancementCalculator adv = new AdvancementCalculator();
+ adv.calculate((CompositeActivity) getParent());
+ Vertex[] outVertices = getOutGraphables();
+ for (Vertex outVertice : outVertices)
+ ((WfVertex) outVertice).run(agent, item);
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/CompositeActivity.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/CompositeActivity.java new file mode 100644 index 0000000..1bdfbe8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/CompositeActivity.java @@ -0,0 +1,469 @@ +/**
+ * 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.lifecycle.instance;
+
+import java.util.ArrayList;
+
+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.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.agent.Job;
+import org.cristalise.kernel.graph.model.GraphModel;
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.graph.model.GraphableVertex;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.InvalidAgentPathException;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**
+ * @version $Revision: 1.86 $ $Date: 2005/10/05 07:39:37 $
+ * @author $Author: abranson $
+ */
+public class CompositeActivity extends Activity
+{
+
+
+ /*
+ * --------------------------------------------
+ * ----------------CONSTRUCTOR-----------------
+ * --------------------------------------------
+ */
+ public CompositeActivity()
+ {
+ super();
+ setChildrenGraphModel(new GraphModel(new WfVertexOutlineCreator()));
+ setIsComposite(true);
+ }
+
+ // State machine
+ public static final int START = 0;
+ public static final int COMPLETE = 1;
+ @Override
+ protected String getDefaultSMName() {
+ return "CompositeActivity";
+ }
+
+ @Override
+ public void setChildrenGraphModel(GraphModel childrenGraph) {
+ super.setChildrenGraphModel(childrenGraph);
+ childrenGraph.setVertexOutlineCreator(new WfVertexOutlineCreator());
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#verify()
+ */
+ /*
+ * -------------------------------------------- --------------Other
+ * Functions--------------- --------------------------------------------
+ */
+ /** launch the verification of the subprocess() */
+ @Override
+ public boolean verify()
+ {
+ boolean err = super.verify();
+ GraphableVertex[] vChildren = getChildren();
+ for (int i = 0; i < vChildren.length; i++)
+ {
+ if (!((WfVertex) vChildren[i]).verify())
+ {
+ mErrors.add("error in children");
+ return false;
+ }
+ }
+ return err;
+ }
+
+ /**
+ * Method initChild.
+ *
+ * @param act
+ * @param first
+ * @param point
+ */
+ /**
+ * Create an initialize a Activity attached to the current activity
+ *
+ * @param first :
+ * if true, the activity Waiting will be one of the first
+ * launched by the parent activity
+ */
+ public void initChild(Activity act, boolean first, GraphPoint point)
+ {
+ this.addChild(act, new GraphPoint(point.x, point.y));
+ if (first)
+ {
+ getChildrenGraphModel().setStartVertexId(act.getID());
+ Logger.msg(5, "org.cristalise.kernel.lifecycle.CompositeActivity :: " + getID() + " is first");
+ }
+ }
+
+ /**
+ * Method newChild.
+ *
+ * @param Name
+ * @param Type
+ * @param point
+ * @return WfVertex
+ */
+ public WfVertex newExistingChild(Activity child, String Name, GraphPoint point)
+ {
+ child.setName(Name);
+ addChild(child, new GraphPoint(point.x, point.y));
+ return child;
+ }
+
+ /**
+ * Method newChild.
+ *
+ * @param Name
+ * @param Type
+ * @param point
+ * @return WfVertex
+ */
+ public WfVertex newChild(String Name, String Type, GraphPoint point)
+ {
+ WfVertex v = newChild(Type, point);
+ v.setName(Name);
+ return v;
+ }
+
+ /**
+ * Method newChild.
+ *
+ * @param vertexTypeId
+ * @param point
+ * @return WfVertex
+ */
+ public WfVertex newChild(String vertexTypeId, GraphPoint point)
+ {
+ WfVertex wfVertex = null;
+ if (vertexTypeId.equals("Atomic"))
+ {
+ wfVertex = newAtomChild("False id", false, point);
+ } else if (vertexTypeId.equals("Composite"))
+ {
+ wfVertex = newCompChild("False id", false, point);
+ } else if (vertexTypeId.endsWith("Split"))
+ {
+ if (vertexTypeId.startsWith("Or"))
+ {
+ wfVertex = newSplitChild("Or", point);
+ } else if (vertexTypeId.startsWith("XOr"))
+ {
+ wfVertex = newSplitChild("XOr", point);
+ } else if (vertexTypeId.startsWith("Loop"))
+ {
+ wfVertex = newSplitChild("Loop", point);
+ } else
+ {
+ wfVertex = newSplitChild("And", point);
+ }
+ } else if (vertexTypeId.equals("Join"))
+ {
+ wfVertex = newJoinChild(point);
+ } else if (vertexTypeId.equals("Route"))
+ {
+ wfVertex = newRouteChild(point);
+ }
+ return wfVertex;
+ }
+
+ /**
+ * Method newCompChild.
+ *
+ * @param id
+ * @param first
+ * @param point
+ * @return CompositeActivity Create an initialize a composite Activity
+ * attached to the current activity
+ */
+ public CompositeActivity newCompChild(String id, boolean first, GraphPoint point)
+ {
+ CompositeActivity act = new CompositeActivity();
+ initChild(act, first, point);
+ act.setName(id);
+ return act;
+ }
+
+ /**
+ * Method newAtomChild.
+ *
+ * @param id
+ * @param first
+ * @param point
+ * @return Activity Create an initialize an Atomic Activity attached to the
+ * current activity
+ *
+ */
+ public Activity newAtomChild(String id, boolean first, GraphPoint point)
+ {
+ Activity act = new Activity();
+ initChild(act, first, point);
+ act.setName(id);
+ return act;
+ }
+
+ /**
+ * Method newSplitChild.
+ *
+ * @param Type
+ * @param point
+ * @return Split
+ */
+ public Split newSplitChild(String Type, GraphPoint point)
+ {
+ Split split;
+ if (Type.equals("Or"))
+ {
+ split = new OrSplit();
+ } else if (Type.equals("XOr"))
+ {
+ split = new XOrSplit();
+ } else if (Type.equals("Loop"))
+ {
+ split = new Loop();
+ } else
+ {
+ split = new AndSplit();
+ }
+ addChild(split, new GraphPoint(point.x, point.y));
+ return split;
+ }
+
+ /**
+ * Method newJoinChild.
+ *
+ * @param point
+ * @return Join
+ */
+ public Join newJoinChild(GraphPoint point)
+ {
+ Join join = new Join();
+ join.getProperties().put("Type", "Join");
+ addChild(join, new GraphPoint(point.x, point.y));
+ return join;
+ }
+
+ public Join newRouteChild(GraphPoint point)
+ {
+ Join join = new Join();
+ join.getProperties().put("Type", "Route");
+ addChild(join, new GraphPoint(point.x, point.y));
+ return join;
+ }
+
+ /**
+ * Method search.
+ *
+ * @param ids
+ * @return WfVertex
+ */
+ WfVertex search(int ids)
+ {
+ for (int i = 0; i < getChildren().length; i++)
+ {
+ WfVertex ver = (WfVertex) getChildren()[i];
+ if (ver instanceof Split)
+ {
+ if (ver.getID() == ids)
+ {
+ return ver;
+ }
+ }
+ if (ver instanceof Join)
+ {
+ if (ver.getID() == ids)
+ {
+ return ver;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws PersistencyException
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectCannotBeUpdated
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#run()
+ */
+ @Override
+ public void run(AgentPath agent, ItemPath itemPath) throws InvalidDataException
+ {
+ super.run(agent, itemPath);
+ if (getChildrenGraphModel().getStartVertex() != null && !getStateMachine().getState(state).isFinished())
+ {
+ WfVertex first = (WfVertex) getChildrenGraphModel().getStartVertex();
+ first.run(agent, itemPath);
+ }
+ }
+
+ @Override
+ public void runNext(AgentPath agent, ItemPath itemPath) throws InvalidDataException
+ {
+ if (!getStateMachine().getState(state).isFinished())
+ try {
+ request(agent, itemPath, CompositeActivity.COMPLETE, null);
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ Logger.error(e); // current agent couldn't complete the composite, so leave it
+ }
+ super.runNext(agent, itemPath);
+ }
+
+ + /**
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ * @throws InvalidAgentPathException
+ * @see org.cristalise.kernel.lifecycle.instance.Activity#calculateJobs()
+ */
+ @Override
+ public ArrayList<Job> calculateJobs(AgentPath agent, ItemPath itemPath, boolean recurse) throws InvalidAgentPathException, ObjectNotFoundException, InvalidDataException
+ {
+ ArrayList<Job> jobs = new ArrayList<Job>();
+ boolean childActive = false;
+ if (recurse)
+ for (int i = 0; i < getChildren().length; i++)
+ if (getChildren()[i] instanceof Activity)
+ {
+ Activity child = (Activity) getChildren()[i];
+ jobs.addAll(child.calculateJobs(agent, itemPath, recurse));
+ childActive |= child.active;
+ }
+ if (!childActive)
+ jobs.addAll(super.calculateJobs(agent, itemPath, recurse));
+ return jobs;
+ }
+
+ @Override
+ public ArrayList<Job> calculateAllJobs(AgentPath agent, ItemPath itemPath, boolean recurse) throws InvalidAgentPathException, ObjectNotFoundException, InvalidDataException
+ {
+ ArrayList<Job> jobs = new ArrayList<Job>();
+ if (recurse)
+ for (int i = 0; i < getChildren().length; i++)
+ if (getChildren()[i] instanceof Activity)
+ {
+ Activity child = (Activity) getChildren()[i];
+ jobs.addAll(child.calculateAllJobs(agent, itemPath, recurse));
+ }
+ jobs.addAll(super.calculateAllJobs(agent, itemPath, recurse));
+ return jobs;
+ }
+
+ /**
+ * Method addNext.
+ *
+ * @param origin
+ * @param terminus
+ * @return Next
+ */
+ public Next addNext(WfVertex origin, WfVertex terminus)
+ {
+ return new Next(origin, terminus);
+ }
+
+ /**
+ * Method addNext.
+ *
+ * @param originID
+ * @param terminusID
+ * @return Next
+ */
+ public Next addNext(int originID, int terminusID)
+ {
+ Next n = new Next();
+ n.setParent(this);
+ getChildrenGraphModel().addEdgeAndCreateId(n, originID, terminusID);
+ return n;
+ }
+
+ /**
+ * Method hasGoodNumberOfActivity.
+ *
+ * @return boolean
+ */
+ public boolean hasGoodNumberOfActivity()
+ {
+ int endingAct = 0;
+ for (int i = 0; i < getChildren().length; i++)
+ {
+ WfVertex vertex = (WfVertex) getChildren()[i];
+ if (getChildrenGraphModel().getOutEdges(vertex).length == 0)
+ endingAct++;
+ }
+ if (endingAct > 1)
+ return false;
+ return true;
+ }
+
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.Activity#getType()
+ */
+ @Override
+ public String getType()
+ {
+ return super.getType();
+ }
+
+ /**
+ * @throws InvalidDataException
+ *
+ */
+ @Override
+ public void reinit(int idLoop) throws InvalidDataException
+ {
+ super.reinit(idLoop);
+ if (getChildrenGraphModel().getStartVertex() != null && !getStateMachine().getState(state).isFinished())
+ ((WfVertex) getChildrenGraphModel().getStartVertex()).reinit(idLoop);
+ }
+
+ @Override
+ public String request(AgentPath agent, ItemPath itemPath, int transitionID, String requestData) throws AccessRightsException, InvalidTransitionException, InvalidDataException, ObjectNotFoundException, PersistencyException, ObjectAlreadyExistsException, ObjectCannotBeUpdated, CannotManageException, InvalidCollectionModification
+ {
+ if (getChildrenGraphModel().getStartVertex() != null && !getStateMachine().getState(state).isFinished() && transitionID == CompositeActivity.START)
+ ((WfVertex) getChildrenGraphModel().getStartVertex()).run(agent, itemPath);
+
+ return super.request(agent, itemPath, transitionID, requestData);
+ }
+
+ public void refreshJobs(ItemPath itemPath)
+ {
+ GraphableVertex[] children = getChildren();
+ for (GraphableVertex element : children)
+ if (element instanceof CompositeActivity)
+ ((CompositeActivity) element).refreshJobs(itemPath);
+ else if (element instanceof Activity)
+ ((Activity) element).pushJobsToAgents(itemPath);
+ }
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/JobPusher.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/JobPusher.java new file mode 100644 index 0000000..9aeca42 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/JobPusher.java @@ -0,0 +1,81 @@ +/**
+ * 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.lifecycle.instance;
+
+import java.util.Iterator;
+
+import org.cristalise.kernel.entity.Agent;
+import org.cristalise.kernel.entity.AgentHelper;
+import org.cristalise.kernel.entity.agent.JobArrayList;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.lookup.Path;
+import org.cristalise.kernel.lookup.RolePath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+final class JobPusher extends Thread {
+ private final Activity activity;
+ private final RolePath myRole;
+ private final ItemPath itemPath;
+
+ JobPusher(Activity activity, ItemPath itemPath, RolePath role) {
+ this.activity = activity;
+ this.itemPath = itemPath;
+ this.myRole = role;
+ }
+
+ @Override
+ public void run()
+ {
+ Thread.currentThread().setName("Agent job pusher for "+itemPath+":"+activity.getName()+" to role "+myRole);
+ for (Iterator<Path> e = myRole.getChildren(); e.hasNext();)
+ {
+ AgentPath nextAgent = (AgentPath)e.next();
+ Logger.msg(7, "Activity.pushJobsToAgents() - Calculating jobs for " + nextAgent);
+ try
+ {
+ // get joblist for user
+ JobArrayList jobList = new JobArrayList(this.activity.calculateJobs(nextAgent, itemPath, false));
+ Logger.msg(7, "Activity.pushJobsToAgents() - User will receive " + jobList.list.size() + " jobs");
+ String stringJobs = Gateway.getMarshaller().marshall(jobList);
+ // push it to the agent
+ org.omg.CORBA.Object agentIOR = nextAgent.getIOR();
+ Agent thisAgent = AgentHelper.narrow(agentIOR);
+ Logger.msg(7, "Calling agent "+thisAgent.getSystemKey()+" from "+activity.getPath());
+ thisAgent.refreshJobList(itemPath.getSystemKey(), activity.getPath(), stringJobs);
+ }
+ catch (Exception ex)
+ {
+ Logger.error(
+ "Agent "
+ + nextAgent
+ + " of role "
+ + myRole
+ + " could not be found to be informed of a change in "
+ + itemPath);
+ Logger.error(ex);
+ }
+ }
+
+ }
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/Join.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/Join.java new file mode 100644 index 0000000..2d1f05c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/Join.java @@ -0,0 +1,233 @@ +/**
+ * 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.lifecycle.instance;
+import java.util.Vector;
+
+import org.cristalise.kernel.common.AccessRightsException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.InvalidTransitionException;
+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.graph.model.Vertex;
+import org.cristalise.kernel.graph.traversal.GraphTraversal;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+
+/**
+ * @version $Revision: 1.52 $ $Date: 2005/05/10 15:14:54 $
+ * @author $Author: abranson $
+ */
+public class Join extends WfVertex
+{
+ public Vector<String> mErrors;
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public Join()
+ {
+ super();
+ mErrors = new Vector<String>(0, 1);
+ }
+ private boolean loopTested;
+ public int counter = 0;
+
+ /**
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws PersistencyException
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectCannotBeUpdated
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#runNext()
+ */
+ @Override
+ public void runNext(AgentPath agent, ItemPath item) throws InvalidDataException
+ {
+ AdvancementCalculator adv = new AdvancementCalculator();
+ adv.calculate((CompositeActivity) getParent());
+ if (adv.hasprevActive.get(String.valueOf(getID())) == null)
+ {
+ Vertex[] outVertices = getOutGraphables();
+ if (outVertices.length > 0)
+ {
+ WfVertex nextAct = (WfVertex) outVertices[0];
+ nextAct.run(agent, item);
+ }
+ else
+ super.runNext(agent, item);
+ }
+ }
+ /**
+ * Method addNext.
+ *
+ * @param idNext
+ */
+ public void addNext(String idNext)
+ {
+ new Next(this, (WfVertex) getParent().search(idNext));
+ }
+ /**
+ * @throws InvalidDataException
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#reinit(int)
+ */
+ @Override
+ public void reinit(int idLoop) throws InvalidDataException
+ {
+ Vertex[] outVertices = getOutGraphables();
+ if (outVertices.length == 1)
+ {
+ WfVertex nextAct = (WfVertex) outVertices[0];
+ nextAct.reinit(idLoop);
+ }
+ }
+
+ @Override
+ public boolean verify()
+ {
+ mErrors.removeAllElements();
+ int nbOutEdges = getOutEdges().length;
+ int nbInEdges = getInEdges().length;
+ String type = (String) getProperties().get("Type");
+ if (nbInEdges < 1)
+ {
+ mErrors.add("not enough previous");
+ return false;
+ }
+ if (type != null && type.equals("Route"))
+ {
+ if (nbInEdges > 1)
+ {
+ mErrors.add("Bad nb of previous");
+ return false;
+ }
+ }
+ if (nbOutEdges > 1)
+ {
+ mErrors.add("too many next");
+ return false;
+ }
+ if (nbOutEdges == 0)
+ {
+ if (!((CompositeActivity) getParent()).hasGoodNumberOfActivity())
+ {
+ mErrors.add("too many endpoints");
+ return false;
+ }
+ }
+ Vertex[] outV = getOutGraphables();
+ Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ boolean loop = false;
+ boolean errInLoop = false;
+ for (int i = 0; i < outV.length; i++)
+ {
+ for (int j = 0; j < anteVertices.length; j++)
+ if (!loop && outV[i].getID() == anteVertices[j].getID())
+ {
+ if (outV[i] instanceof Loop)
+ {
+ loop = true;
+ j = anteVertices.length;
+ i = outV.length;
+ }
+ else
+ {
+ errInLoop = true;
+ }
+ }
+ }
+ if (errInLoop && loop)
+ {
+ mErrors.add("Problem in Loop");
+ return false;
+ }
+ return true;
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#getErrors()
+ */
+ @Override
+ public String getErrors()
+ {
+ if (mErrors.size() == 0)
+ return "No error";
+ else
+ return mErrors.elementAt(0);
+ }
+ /**
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws PersistencyException
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectCannotBeUpdated
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#run()
+ */
+ @Override
+ public void run(AgentPath agent, ItemPath item) throws InvalidDataException
+ {
+ runNext(agent, item);
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#addNext(org.cristalise.kernel.lifecycle.instance.WfVertex)
+ */
+ @Override
+ public Next addNext(WfVertex vertex)
+ {
+ return new Next(this, vertex);
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#loop()
+ */
+ @Override
+ public boolean loop()
+ {
+ boolean loop2 = false;
+ if (!loopTested)
+ {
+ loopTested = true;
+ if (getOutGraphables().length != 0)
+ loop2 = ((WfVertex) getOutGraphables()[0]).loop();
+ }
+ else
+ loop2 = true;
+ loopTested = false;
+ return loop2;
+ }
+ @Override
+ public void runFirst(AgentPath agent, ItemPath item) throws InvalidDataException
+ {
+ runNext(agent, item);
+ }
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.cristalise.kernel.graph.model.Vertex#isJoin()
+ */
+ @Override
+ public boolean isJoin()
+ {
+ return true;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/Loop.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/Loop.java new file mode 100644 index 0000000..d6a660e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/Loop.java @@ -0,0 +1,130 @@ +/**
+ * 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.lifecycle.instance;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.graph.model.Vertex;
+import org.cristalise.kernel.graph.traversal.GraphTraversal;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.utils.Logger;
+
+/**
+ * @version $Revision: 1.35 $ $Date: 2005/05/10 15:14:54 $
+ * @author $Author: abranson $
+ */
+public class Loop extends XOrSplit
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public Loop()
+ {
+ super();
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#loop()
+ */
+ @Override
+ public boolean loop()
+ {
+ return true;
+ }
+ @Override
+ public void followNext(Next activeNext, AgentPath agent, ItemPath itemPath) throws InvalidDataException
+ {
+ WfVertex v = activeNext.getTerminusVertex();
+ if (!isInPrev(v))
+ v.run(agent, itemPath);
+ else
+ {
+ v.reinit(getID());
+ v.run(agent, itemPath);
+ }
+ }
+ /**
+ * @throws InvalidDataException
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#reinit(int)
+ */
+ @Override
+ public void reinit(int idLoop) throws InvalidDataException
+ {
+ Logger.msg(8, "Loop.reinit");
+ if (idLoop == getID())
+ return;
+ else
+ {
+ Vertex[] outVertices = getOutGraphables();
+ for (int j = 0; j < outVertices.length; j++)
+ {
+ if (!isInPrev(outVertices[j]))
+ ((WfVertex) outVertices[j]).reinit(idLoop);
+ }
+ }
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#verify()
+ */
+ @Override
+ public boolean verify()
+ {
+ boolean err = super.verify();
+ Vertex[] nexts = getOutGraphables();
+ Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ int k = 0;
+ int l = 0;
+ Vertex[] brothers = getParent().getChildren();
+ for (Vertex brother : brothers)
+ if (brother instanceof Loop)
+ l++;
+ for (Vertex next : nexts) {
+ for (Vertex anteVertice : anteVertices)
+ if (next.getID() == anteVertice.getID())
+ k++;
+ }
+ if (k != 1 && !(l > 1))
+ {
+ mErrors.add("bad number of pointing back nexts");
+ return false;
+ }
+ // if (nexts.length>2) {
+ // mErrors.add("you must only have 2 nexts");
+ // return false;
+ // }
+ return err;
+ }
+ private boolean isInPrev(Vertex vertex)
+ {
+ int id = vertex.getID();
+ Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ for (Vertex anteVertice : anteVertices) {
+ if (anteVertice.getID() == id)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ @Override
+ public boolean isLoop()
+ {
+ return true;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/Next.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/Next.java new file mode 100644 index 0000000..e0df1e6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/Next.java @@ -0,0 +1,103 @@ +/**
+ * 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.lifecycle.instance;
+
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.graph.model.GraphableEdge;
+
+/**
+ * @version $Revision: 1.58 $ $Date: 2005/05/10 15:14:54 $
+ * @author $Author: abranson $
+ */
+/** this class represents the link between 2 successive activities */
+public class Next extends GraphableEdge
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public Next()
+ {
+ super();
+ }
+
+ /**
+ * Method Next.
+ * @param pre
+ * @param nex
+ */
+ /** create and initialize a link between an Activities */
+ public Next(WfVertex pre, WfVertex nex)
+ {
+ super(pre, nex);
+ getProperties().put("Alias","");
+ getProperties().put("Type","Straight");
+ }
+
+ /**
+ * Method verify.
+ * @return boolean
+ */
+ public boolean verify()
+ {
+ return true;
+ }
+ public WfVertex getTerminusVertex()
+ {
+ return (WfVertex)((CompositeActivity)getParent()).getWf().search(getParent().getPath()+"/"+this.getTerminusVertexId());
+ }
+ @Override
+ public boolean containsPoint(GraphPoint p)
+ {
+ GraphPoint originPoint = getOriginPoint();
+ GraphPoint terminusPoint = getTerminusPoint();
+ GraphPoint midPoint = new GraphPoint();
+
+ if (("Broken +".equals(getProperties().get("Type"))))
+ {
+ midPoint.x = (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = (originPoint.y + terminusPoint.y) / 2;
+ }
+ else if (("Broken -".equals(getProperties().get("Type"))))
+ {
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? terminusPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : originPoint.y;
+ }
+ else if (("Broken |".equals(getProperties().get("Type"))))
+ {
+ boolean arrowOnY = !(originPoint.y - terminusPoint.y < 60 && originPoint.y - terminusPoint.y > -60);
+ midPoint.x = arrowOnY ? originPoint.x : (originPoint.x + terminusPoint.x) / 2;
+ midPoint.y = arrowOnY ? (originPoint.y + terminusPoint.y) / 2 : terminusPoint.y;
+ }
+ else
+ {
+ midPoint.x = originPoint.x + (terminusPoint.x - originPoint.x) / 2;
+ midPoint.y = originPoint.y + (terminusPoint.y - originPoint.y) / 2;
+ }
+
+ int minX = midPoint.x - 10;
+ int minY = midPoint.y - 10;
+ int maxX = midPoint.x + 10;
+ int maxY = midPoint.y + 10;
+
+ return (p.x >= minX) && (p.x <= maxX) && (p.y >= minY) && (p.y <= maxY);
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/OrSplit.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/OrSplit.java new file mode 100644 index 0000000..12c7f46 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/OrSplit.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.lifecycle.instance;
+import java.util.StringTokenizer;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.graph.model.DirectedEdge;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.scripting.ScriptingEngineException;
+import org.cristalise.kernel.utils.Logger;
+
+/**
+ * @version $Revision: 1.22 $ $Date: 2005/05/10 15:14:54 $
+ * @author $Author: abranson $
+ */
+public class OrSplit extends Split
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public OrSplit()
+ {
+ super();
+ }
+ @Override
+ public void runNext(AgentPath agent, ItemPath itemPath) throws InvalidDataException
+ {
+ String nexts;
+ String scriptName = (String) getProperties().get("RoutingScriptName");
+ Integer scriptVersion = getVersionNumberProperty("RoutingScriptVersion");
+ try {
+ nexts = this.evaluateScript(scriptName, scriptVersion, itemPath).toString();
+ } catch (ScriptingEngineException e) {
+ Logger.error(e);
+ throw new InvalidDataException("Error running routing script "+scriptName+" v"+scriptVersion);
+ }
+ StringTokenizer tok = new StringTokenizer(nexts, ",");
+ Logger.msg(7, tok.countTokens() + " nexts to activate:" + nexts);
+ int active = 0;
+ try
+ {
+ DirectedEdge[] outEdges = getOutEdges();
+ AdvancementCalculator adv = new AdvancementCalculator();
+ adv.calculate((CompositeActivity)getParent());
+ while (tok.hasMoreTokens())
+ {
+ String thisNext = tok.nextToken();
+ Logger.msg(7, "Finding next " + thisNext);
+ for (DirectedEdge outEdge : outEdges) {
+ Next nextEdge = (Next) outEdge;
+ if (thisNext != null && thisNext.equals(nextEdge.getProperties().get("Alias")))
+ {
+ WfVertex term = nextEdge.getTerminusVertex();
+ term.run(agent, itemPath);
+ Logger.msg(7, "Running " + nextEdge.getProperties().get("Alias"));
+ active++;
+ }
+ }
+ }
+ // if no active nexts throw exception
+ }
+ catch (Exception e)
+ {
+ Logger.error(e);
+ }
+ if (active == 0)
+ throw new InvalidDataException("No nexts were activated!");
+ }
+
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/Split.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/Split.java new file mode 100644 index 0000000..ac3afbd --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/Split.java @@ -0,0 +1,239 @@ +/**
+ * 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.lifecycle.instance;
+
+import java.util.Vector;
+
+import org.cristalise.kernel.common.AccessRightsException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.InvalidTransitionException;
+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.graph.model.Vertex;
+import org.cristalise.kernel.graph.traversal.GraphTraversal;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+
+
+/**
+ * @version $Revision: 1.47 $ $Date: 2006/05/29 13:17:45 $
+ * @author $Author: abranson $
+ */
+public abstract class Split extends WfVertex
+{
+ public Vector<String> mErrors;
+
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public Split()
+ {
+ mErrors = new Vector<String>(0, 1);
+ getProperties().put("RoutingScriptName", "");
+ getProperties().put("RoutingScriptVersion", "");
+ }
+
+ private boolean loopTested;
+
+ /**
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws PersistencyException
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectCannotBeUpdated
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#runNext()
+ */
+ @Override
+ public abstract void runNext(AgentPath agent, ItemPath itemPath) throws InvalidDataException;
+
+ /**
+ * Method addNext.
+ *
+ * @param idNext
+ */
+ void addNext(String idNext)
+ {
+ new Next(this, (WfVertex) getParent().search(idNext));
+ }
+
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#addNext(org.cristalise.kernel.lifecycle.instance.WfVertex)
+ */
+ @Override
+ public Next addNext(WfVertex vertex)
+ {
+ Next nxt = new Next(this, vertex);
+ int num = getOutGraphables().length;
+ try
+ {
+ num = Integer.parseInt((String) getProperties().get("LastNum"));
+ } catch (Exception e)
+ {
+ }
+ nxt.getProperties().put("Alias", String.valueOf(num));
+ getProperties().put("LastNum", String.valueOf(num + 1));
+ return nxt;
+ }
+
+ @Override
+ public void reinit(int idLoop) throws InvalidDataException
+ {
+ Vertex[] outVertices = getOutGraphables();
+ for (Vertex outVertice : outVertices)
+ ((WfVertex) outVertice).reinit(idLoop);
+ }
+
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#verify()
+ */
+ @Override
+ public boolean verify()
+ {
+ mErrors.removeAllElements();
+ int nbInEdgres = getParent().getChildrenGraphModel().getInEdges(this).length;
+ if (nbInEdgres == 0 && this.getID() != getParent().getChildrenGraphModel().getStartVertexId())
+ {
+ mErrors.add("not enough previous");
+ return false;
+ }
+ if (nbInEdgres > 1)
+ {
+ mErrors.add("Bad nb of previous");
+ return false;
+ }
+ if (getOutEdges().length <= 1 && !(this instanceof Loop))
+ {
+ mErrors.add("not enough next");
+ return false;
+ }
+ if (!(this instanceof Loop))
+ {
+ Vertex[] outV = getOutGraphables();
+ Vertex[] anteVertices = GraphTraversal.getTraversal(getParent().getChildrenGraphModel(), this, GraphTraversal.kUp, false);
+ boolean loop = false;
+ boolean errInLoop = true;
+ for (int i = 0; i < outV.length; i++)
+ {
+ for (int j = 0; j < anteVertices.length; j++)
+ if (!loop && outV[i].getID() == anteVertices[j].getID())
+ {
+ if (outV[i] instanceof Loop)
+ {
+ loop = true;
+ j = anteVertices.length;
+ i = outV.length;
+ } else
+ {
+ errInLoop = false;
+ }
+ }
+ }
+ if (errInLoop && loop)
+ {
+ mErrors.add("Problem in Loop");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#getErrors()
+ */
+ @Override
+ public String getErrors()
+ {
+ if (mErrors.size() == 0)
+ return "No error";
+ else
+ return mErrors.elementAt(0);
+ }
+
+ /**
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws PersistencyException
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectCannotBeUpdated
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#run()
+ */
+ @Override
+ public void run(AgentPath agent, ItemPath itemPath) throws InvalidDataException
+ {
+ runNext(agent, itemPath);
+ }
+
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#loop()
+ */
+ @Override
+ public boolean loop()
+ {
+ boolean loop2 = false;
+ if (!loopTested)
+ {
+ loopTested = true;
+ if (getOutGraphables().length != 0)
+ {
+ Vertex[] outVertices = getOutGraphables();
+ for (int i = 0; i < outVertices.length; i++)
+ {
+ WfVertex tmp = (WfVertex) getOutGraphables()[i];
+ loop2 = loop2 || tmp.loop();
+ }
+ }
+ }
+ loopTested = false;
+ return loop2;
+ }
+
+ public String[] nextNames()
+ {
+ Vertex[] vs = getOutGraphables();
+ String[] result = new String[vs.length];
+ for (int i = 0; i < vs.length; i++)
+ result[i] = vs[i].getName();
+ return result;
+ }
+
+ protected boolean isInTable(String test, String[] list)
+ {
+ if (test == null)
+ return false;
+ for (String element : list)
+ if (test.equals(element))
+ return true;
+ return false;
+ }
+
+ @Override
+ public void runFirst(AgentPath agent, ItemPath itemPath) throws InvalidDataException
+ {
+ runNext(agent, itemPath);
+ }
+
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertex.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertex.java new file mode 100644 index 0000000..d241aca --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertex.java @@ -0,0 +1,223 @@ +/**
+ * 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.lifecycle.instance;
+
+
+
+import java.util.HashMap;
+
+import org.cristalise.kernel.common.AccessRightsException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.InvalidTransitionException;
+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.graph.model.GraphableVertex;
+import org.cristalise.kernel.lifecycle.routingHelpers.ViewpointDataHelper;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.scripting.Script;
+import org.cristalise.kernel.scripting.ScriptingEngineException;
+import org.cristalise.kernel.utils.KeyValuePair;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**
+ * @version $Revision: 1.38 $ $Date: 2005/09/07 13:46:31 $
+ * @author $Author: abranson $
+ */
+public abstract class WfVertex extends GraphableVertex
+{
+ /**sets the activity available to be executed on start of Workflow or composite activity (when it is the first one of the
+ * (sub)process
+ * @throws InvalidDataException
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws PersistencyException
+ * @throws ObjectCannotBeUpdated */
+ public abstract void runFirst(AgentPath agent, ItemPath itemPath) throws InvalidDataException;
+
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public WfVertex()
+ {
+ super();
+ setIsLayoutable(true);
+ setIsComposite(false);
+ }
+
+ /**
+ * Method runNext.
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws PersistencyException
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectCannotBeUpdated
+ */
+ public void runNext(AgentPath agent, ItemPath itemPath) throws InvalidDataException
+ {
+ try
+ {
+ ((CompositeActivity)getParent()).request(agent, itemPath, CompositeActivity.COMPLETE, null);
+ }
+ catch (Exception e)
+ {
+ //Logger.error(e);
+ }
+
+ }
+
+ /**
+ * Method reinit.
+ * @param idLoop
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ */
+ public abstract void reinit( int idLoop ) throws InvalidDataException;
+
+ /**
+ * Method verify.
+ * @return boolean
+ */
+ public abstract boolean verify();
+
+ /**
+ * Method getErrors.
+ * @return String
+ */
+ public abstract String getErrors();
+
+ /**
+ * Method run.
+ * @throws InvalidDataException
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws PersistencyException
+ * @throws ObjectCannotBeUpdated
+ */
+ public abstract void run(AgentPath agent, ItemPath itemPath) throws InvalidDataException;
+
+ /**
+ * Method loop.
+ * @return boolean
+ */
+ public abstract boolean loop();
+
+ /**
+ * Method addNext.
+ * @param vertex
+ */
+ public abstract Next addNext(WfVertex vertex);
+
+ protected Object evaluateScript(String scriptName, Integer scriptVersion, ItemPath itemPath) throws ScriptingEngineException
+ {
+
+ try
+ {
+ Script script = getScript(scriptName, scriptVersion);
+
+ KeyValuePair[] k = getProperties().getKeyValuePairs();
+ HashMap<?, ?> requiredInput = script.getAllInputParams();
+ for (KeyValuePair element : k) {
+ if (requiredInput.containsKey(element.getKey()))
+ {
+ String value = element.getStringValue();
+ Object inputParam = value;
+
+ if (value.startsWith("viewpoint//"))
+ {
+ value = value.substring(11);
+ if (value.startsWith("."))
+ value = itemPath.getUUID() + value.substring(1);
+ try {
+ inputParam = ViewpointDataHelper.get(value)[0];
+ } catch (ArrayIndexOutOfBoundsException ex) {
+ throw new InvalidDataException("Could not retrieve data from viewpoint: "+value);
+ }
+ }
+ if (value.startsWith("property//"))
+ {
+ value = value.substring(10);
+ try {
+ inputParam = Gateway.getStorage().get(itemPath, ClusterStorage.PROPERTY+"/"+value, null);
+ } catch (ObjectNotFoundException ex) {
+ inputParam = null;
+ }
+ }
+ Logger.msg(5, "Split.evaluateScript() - Setting param " + element.getKey() + " to " + inputParam);
+ script.setInputParamValue(element.getKey(), inputParam);
+ }
+ }
+
+ //TODO: is this right?
+ if (requiredInput.containsKey("item")) {
+ script.setInputParamValue("item", Gateway.getProxyManager().getProxy(itemPath));
+ }
+ if (requiredInput.containsKey("agent")) {
+ AgentPath systemAgent = Gateway.getLookup().getAgentPath("system");
+ script.setInputParamValue("agent", Gateway.getProxyManager().getProxy(systemAgent));
+ }
+ Object retVal = script.execute();
+ Logger.msg(2, "Split.evaluateScript() - Script returned "+retVal);
+ if (retVal == null) retVal = "";
+ return retVal;
+ }
+ catch (Exception e)
+ {
+ Logger.msg(1, "Split.evaluateScript() - Error: Script " + scriptName);
+ Logger.error(e);
+ throw new ScriptingEngineException();
+ }
+ }
+
+ private static Script getScript(String name, Integer version) throws ScriptingEngineException
+ {
+ if (name == null || name.length() == 0)
+ throw new ScriptingEngineException("Script name is empty");
+ Script script;
+ if (version!=null) {
+ script = new Script(name, version);
+ }
+ else { // empty version: try expression
+ int split = name.indexOf(":");
+ script = new Script(name.substring(0, split), name.substring(split + 1));
+ }
+
+ return script;
+ }
+
+
+ public Workflow getWf()
+ {
+ return ((CompositeActivity)getParent()).getWf();
+ }
+}
+
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertexOutlineCreator.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertexOutlineCreator.java new file mode 100644 index 0000000..286ba64 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/WfVertexOutlineCreator.java @@ -0,0 +1,69 @@ +/**
+ * 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.lifecycle.instance;
+
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.graph.model.Vertex;
+import org.cristalise.kernel.graph.model.VertexOutlineCreator;
+
+public class WfVertexOutlineCreator implements VertexOutlineCreator
+{
+ private static final int mActivityWidth = 130;
+ private static final int mActivityHeight = 60;
+ private static final int mSplitJoinWidth = 60;
+ private static final int mSplitJoinHeight = 25;
+
+ @Override
+ public void setOutline(Vertex vertex)
+ {
+ GraphPoint centrePoint = vertex.getCentrePoint();
+ GraphPoint[] outlinePoints = new GraphPoint[ 4 ];
+ int vertexWidth = 0;
+ int vertexHeight = 0;
+
+ if(vertex instanceof Activity)
+ {
+ vertexWidth = mActivityWidth;
+ vertexHeight = mActivityHeight;
+ }
+ else
+ {
+ vertexWidth = mSplitJoinWidth;
+ vertexHeight = mSplitJoinHeight;
+ }
+
+ outlinePoints[ 0 ] = new GraphPoint();
+ outlinePoints[ 0 ].x = centrePoint.x - vertexWidth / 2;
+ outlinePoints[ 0 ].y = centrePoint.y - vertexHeight / 2;
+ outlinePoints[ 1 ] = new GraphPoint();
+ outlinePoints[ 1 ].x = centrePoint.x + vertexWidth / 2;
+ outlinePoints[ 1 ].y = centrePoint.y - vertexHeight / 2;
+ outlinePoints[ 2 ] = new GraphPoint();
+ outlinePoints[ 2 ].x = centrePoint.x + vertexWidth / 2;
+ outlinePoints[ 2 ].y = centrePoint.y + vertexHeight / 2;
+ outlinePoints[ 3 ] = new GraphPoint();
+ outlinePoints[ 3 ].x = centrePoint.x - vertexWidth / 2;
+ outlinePoints[ 3 ].y = centrePoint.y + vertexHeight / 2;
+
+ vertex.setOutlinePoints( outlinePoints );
+ }
+}
+
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/Workflow.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/Workflow.java new file mode 100644 index 0000000..c2f632a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/Workflow.java @@ -0,0 +1,266 @@ +/**
+ * 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.lifecycle.instance;
+import java.util.ArrayList;
+
+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.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.entity.agent.Job;
+import org.cristalise.kernel.events.History;
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.graph.model.TypeNameAndConstructionInfo;
+import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStepContainer;
+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.utils.Language;
+import org.cristalise.kernel.utils.Logger;
+
+/**
+ * @version $Revision: 1.64 $ $Date: 2005/09/30 07:09:48 $
+ * @author $Author: abranson $
+ */
+public class Workflow extends CompositeActivity implements C2KLocalObject
+{
+ public History history;
+ private ItemPath itemPath = null;
+
+ /** TypeNameAndConstructionInfo[] variables added by Steve */
+ private final TypeNameAndConstructionInfo[] mVertexTypeNameAndConstructionInfo =
+ {
+ new TypeNameAndConstructionInfo(Language.translate("AND Split"), "AndSplit"),
+ new TypeNameAndConstructionInfo(Language.translate("OR Split"), "OrSplit"),
+ new TypeNameAndConstructionInfo(Language.translate("XOR Split"), "XOrSplit"),
+ new TypeNameAndConstructionInfo(Language.translate("Join"), "Join"),
+ new TypeNameAndConstructionInfo(Language.translate("Loop"), "LoopSplit"),
+ new TypeNameAndConstructionInfo(Language.translate("Activity"), "Atomic"),
+ new TypeNameAndConstructionInfo(Language.translate("Composite"), "Composite")
+ };
+ private final TypeNameAndConstructionInfo[] mEdgeTypeNameAndConstructionInfo =
+ {
+ new TypeNameAndConstructionInfo(Language.translate("Next"), "Next")
+ };
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public Workflow()
+ {
+ }
+
+ public Workflow(CompositeActivity domain, PredefinedStepContainer predef) {
+ this();
+ domain.setName("domain");
+ initChild(domain, true, new GraphPoint(150, 100));
+ addChild(predef, new GraphPoint(300, 100));
+ }
+
+ public History getHistory() throws InvalidDataException {
+ if (history == null) {
+ if (itemPath == null)
+ throw new InvalidDataException("Workflow not initialized.");
+ history = new History(itemPath, this);
+ }
+ return history;
+ }
+
+ /**
+ * Method getVertexTypeNameAndConstructionInfo.
+ *
+ * @return TypeNameAndConstructionInfo[]
+ */
+ /** getVertexTypeNameAndConstructionInfo() added by Steve */
+ public TypeNameAndConstructionInfo[] getVertexTypeNameAndConstructionInfo()
+ {
+ return mVertexTypeNameAndConstructionInfo;
+ }
+ /**
+ * Method getEdgeTypeNameAndConstructionInfo.
+ *
+ * @return TypeNameAndConstructionInfo[]
+ */
+ /** getVertexTypeNameAndConstructionInfo() added by Steve */
+ public TypeNameAndConstructionInfo[] getEdgeTypeNameAndConstructionInfo()
+ {
+ return mEdgeTypeNameAndConstructionInfo;
+ }
+ /**
+ * Method requestAction.
+ *
+ * @param agentInfo
+ * @param stepPath
+ * @param transitionID
+ * @param reguestData
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws InvalidDataException
+ * @throws PersistencyException
+ * @throws ObjectCannotBeUpdated
+ * @throws CannotManageException
+ * @throws InvalidCollectionModification
+ */
+ //requestData is xmlstring
+ public String requestAction(AgentPath agent, String stepPath, ItemPath itemPath, int transitionID, String requestData)
+ throws ObjectNotFoundException, AccessRightsException, InvalidTransitionException, InvalidDataException, ObjectAlreadyExistsException, PersistencyException, ObjectCannotBeUpdated, CannotManageException, InvalidCollectionModification
+ {
+ Logger.msg(3, "Action: " + transitionID + " " + stepPath + " by " + agent);
+ if (search(stepPath) != null)
+ return ((Activity) search(stepPath)).request(agent, itemPath, transitionID, requestData);
+ else
+ throw new ObjectNotFoundException(stepPath + " not found");
+ }
+
+ /**
+ * @see org.cristalise.kernel.graph.model.GraphableVertex#getPath()
+ */
+ @Override
+ public String getPath()
+ {
+ return "workflow";
+ }
+ /**
+ * @see org.cristalise.kernel.graph.model.Vertex#getName()
+ */
+ @Override
+ public String getName()
+ {
+ return "workflow";
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.Activity#getType()
+ */
+ @Override
+ public String getType()
+ {
+ return "workflow";
+ }
+ /**
+ * @see org.cristalise.kernel.graph.model.Vertex#setName(java.lang.String)
+ */
+ @Override
+ public void setName(String name)
+ {
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.WfVertex#verify()
+ */
+ @Override
+ public boolean verify()
+ {
+ for (int i = 0; i < getChildren().length; i++)
+ {
+ if (!((WfVertex) getChildren()[i]).verify())
+ {
+ mErrors.add("error in children");
+ return false;
+ }
+ }
+ return true;
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.Activity#getWf()
+ */
+ @Override
+ public Workflow getWf()
+ {
+ return this;
+ }
+ /**
+ * Method initialise.
+ *
+ * @param systemKey
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ * @throws AccessRightsException
+ * @throws InvalidTransitionException
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectCannotBeUpdated
+ */
+ public void initialise(ItemPath itemPath, AgentPath agent) throws InvalidDataException
+ {
+ setItemPath(itemPath);
+ runFirst(agent, itemPath);
+ }
+
+ public ItemPath getItemPath() {
+ return itemPath;
+ }
+
+ public void setItemPath(ItemPath itemPath) {
+ this.itemPath = itemPath;
+ }
+
+ public void setItemUUID( String uuid ) throws InvalidItemPathException
+ {
+ setItemPath(new ItemPath(uuid));
+ }
+
+ public String getItemUUID() {
+ return getItemPath().getUUID().toString();
+ }
+
+ /**
+ * if type = 0 only domain steps will be queried if type = 1 only predefined steps will be queried else both will be queried
+ * @param agent
+ * @param itemSysKey
+ * @param type
+ * @return
+ * @throws ObjectNotFoundException
+ * @throws InvalidDataException
+ * @throws InvalidAgentPathException
+ */
+ public ArrayList<Job> calculateJobs(AgentPath agent, ItemPath itemPath, int type) throws InvalidAgentPathException, ObjectNotFoundException, InvalidDataException
+ {
+ ArrayList<Job> jobs = new ArrayList<Job>();
+ if (type != 1)
+ jobs.addAll(((CompositeActivity) search("workflow/domain")).calculateJobs(agent, itemPath, true));
+ if (type != 0)
+ jobs.addAll(((CompositeActivity) search("workflow/predefined")).calculateJobs(agent, itemPath, true));
+ return jobs;
+ }
+ /**
+ * @see org.cristalise.kernel.lifecycle.instance.CompositeActivity#hasGoodNumberOfActivity()
+ */
+ @Override
+ public boolean hasGoodNumberOfActivity()
+ {
+ return true;
+ }
+ /**
+ * @see org.cristalise.kernel.entity.C2KLocalObject#getClusterType()
+ */
+ @Override
+ public String getClusterType()
+ {
+ return ClusterStorage.LIFECYCLE;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/XOrSplit.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/XOrSplit.java new file mode 100644 index 0000000..91719cd --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/XOrSplit.java @@ -0,0 +1,84 @@ +/**
+ * 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.lifecycle.instance;
+
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.graph.model.DirectedEdge;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.scripting.ScriptingEngineException;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**
+ * @version $Revision: 1.23 $ $Date: 2006/03/03 13:52:21 $
+ * @author $Author: abranson $
+ */
+public class XOrSplit extends Split
+{
+ /**
+ * @see java.lang.Object#Object()
+ */
+ public XOrSplit()
+ {
+ super();
+ }
+
+ @Override
+ public void runNext(AgentPath agent, ItemPath itemPath) throws InvalidDataException
+ {
+ ArrayList<DirectedEdge> nextsToFollow = new ArrayList<DirectedEdge>();
+ String nexts;
+ String scriptName = (String) getProperties().get("RoutingScriptName");
+ Integer scriptVersion = getVersionNumberProperty("RoutingScriptVersion");
+ try {
+ nexts = this.evaluateScript(scriptName, scriptVersion, itemPath).toString();
+ } catch (ScriptingEngineException e) {
+ Logger.error(e);
+ throw new InvalidDataException("Error running routing script "+scriptName+" v"+scriptVersion);
+ }
+
+ StringTokenizer tok = new StringTokenizer(nexts,",");
+ String[] nextsTab = new String[tok.countTokens()];
+ for (int i=0;i<nextsTab.length;i++)
+ nextsTab[i] = tok.nextToken();
+
+ DirectedEdge[] outEdges = getOutEdges();
+ for (DirectedEdge outEdge : outEdges) {
+ if (isInTable((String)((Next)outEdge).getProperties().get("Alias"), nextsTab))
+ nextsToFollow.add(outEdge);
+ }
+// Logger.debug(0, getID()+" following "+nexts);
+ if (nextsToFollow.size() != 1)
+ throw new InvalidDataException("not good number of active next");
+
+ followNext((Next)nextsToFollow.get(0), agent, itemPath);
+
+ }
+
+ public void followNext(Next activeNext, AgentPath agent, ItemPath itemPath) throws InvalidDataException {
+ activeNext.getTerminusVertex().run(agent, itemPath);
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddC2KObject.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddC2KObject.java new file mode 100644 index 0000000..20abbad --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddC2KObject.java @@ -0,0 +1,67 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.lifecycle.instance.predefined;
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $
+ * @version $Revision: 1.31 $
+ **************************************************************************/
+public class AddC2KObject extends PredefinedStep
+{
+ /**************************************************************************
+ * Constructor for Castror
+ **************************************************************************/
+ public AddC2KObject()
+ {
+ super();
+ getProperties().put("Agent Role", "Admin");
+ }
+
+ //requestdata is xmlstring
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, PersistencyException {
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "AddC2KObject: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ if (params.length != 1) throw new InvalidDataException("AddC2KObject: Invalid parameters "+Arrays.toString(params));
+ C2KLocalObject obj;
+ try {
+ obj = (C2KLocalObject)Gateway.getMarshaller().unmarshall(params[0]);
+ } catch (Exception e) {
+ throw new InvalidDataException("AddC2KObject: Could not unmarshall new object: "+params[0]);
+ }
+ Gateway.getStorage().put(item, obj, null );
+ return requestData;
+ }
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddDomainPath.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddDomainPath.java new file mode 100644 index 0000000..8f68d22 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddDomainPath.java @@ -0,0 +1,62 @@ +/**
+ * 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.lifecycle.instance.predefined;
+
+
+
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectAlreadyExistsException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.DomainPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.lookup.LookupManager;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class AddDomainPath extends PredefinedStep
+{
+ public AddDomainPath()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectCannotBeUpdated, ObjectAlreadyExistsException, CannotManageException {
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "AddDomainPath: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ if (params.length != 1) throw new InvalidDataException("AddDomainPath: Invalid parameters "+Arrays.toString(params));
+
+ LookupManager lookupManager = Gateway.getLookupManager();
+
+ DomainPath domainPath = new DomainPath(params[0], item);
+ lookupManager.add(domainPath);
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddMemberToCollection.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddMemberToCollection.java new file mode 100644 index 0000000..ac6004c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddMemberToCollection.java @@ -0,0 +1,105 @@ +/**
+ * 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.lifecycle.instance.predefined;
+
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.collection.Dependency;
+import org.cristalise.kernel.common.InvalidCollectionModification;
+import org.cristalise.kernel.common.InvalidDataException;
+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.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.CastorHashMap;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $
+ * @version $Revision: 1.8 $
+ **************************************************************************/
+public class AddMemberToCollection extends PredefinedStep
+{
+ /**************************************************************************
+ * Constructor for Castor
+ **************************************************************************/
+ public AddMemberToCollection()
+ {
+ super();
+ }
+
+
+ /**
+ * Generates a new slot in a Dependency for the given item
+ *
+ * Params:
+ * 0 - collection name
+ * 1 - target entity key
+ * @throws ObjectAlreadyExistsException
+ * @throws PersistencyException
+ * @throws ObjectNotFoundException
+ * @throws InvalidCollectionModification
+ */
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectAlreadyExistsException, PersistencyException, ObjectNotFoundException, InvalidCollectionModification {
+
+ String collName;
+ ItemPath newChild;
+ Dependency dep;
+ CastorHashMap props = null;
+
+ // extract parameters
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "AddMemberToCollection: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ try {
+ collName = params[0];
+ newChild = new ItemPath(params[1]);
+ if (params.length > 2)
+ props = (CastorHashMap)Gateway.getMarshaller().unmarshall(params[2]);
+
+ } catch (Exception e) {
+ throw new InvalidDataException("AddMemberToCollection: Invalid parameters "+Arrays.toString(params));
+ }
+
+ // load collection
+ C2KLocalObject collObj;
+ collObj = Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null);
+ if (!(collObj instanceof Dependency)) throw new InvalidDataException("AddMemberToCollection: AddMemberToCollection operates on Dependency collections only.");
+ dep = (Dependency)collObj;
+
+ // find member and assign entity
+ if (props == null)
+ dep.addMember(newChild);
+ else
+ dep.addMember(newChild, props, null);
+
+ Gateway.getStorage().put(newChild, dep, null);
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewCollectionDescription.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewCollectionDescription.java new file mode 100644 index 0000000..b230284 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewCollectionDescription.java @@ -0,0 +1,110 @@ +/**
+ * 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.lifecycle.instance.predefined;
+
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.collection.AggregationDescription;
+import org.cristalise.kernel.collection.CollectionDescription;
+import org.cristalise.kernel.collection.DependencyDescription;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectAlreadyExistsException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $
+ * @version $Revision: 1.8 $
+ **************************************************************************/
+public class AddNewCollectionDescription extends PredefinedStep
+{
+ /**************************************************************************
+ * Constructor for Castor
+ **************************************************************************/
+ public AddNewCollectionDescription()
+ {
+ super();
+ }
+
+
+ /**
+ * Generates a new empty collection description. Collection instances should
+ * be added by an Admin, who can do so using AddC2KObject.
+ *
+ * Params:
+ * 0 - collection name
+ * 1 - collection type (Aggregation, Dependency)
+ * @throws PersistencyException
+ */
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectAlreadyExistsException, PersistencyException {
+
+ String collName;
+ String collType;
+
+ // extract parameters
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "AddNewCollectionDescription: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ if (params.length != 2)
+ throw new InvalidDataException("AddNewCollectionDescription: Invalid parameters "+Arrays.toString(params));
+
+ collName = params[0];
+ collType = params[1];
+
+ // check if collection already exists
+ try {
+ Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null);
+ throw new ObjectAlreadyExistsException("Collection '"+collName+"' already exists");
+ } catch (ObjectNotFoundException ex) {
+ // collection doesn't exist
+ } catch (PersistencyException ex) {
+ Logger.error(ex);
+ throw new PersistencyException("AddNewCollectionDescription: Error checking for collection '"+collName+"': "+ex.getMessage());
+ }
+
+
+ CollectionDescription<?> newCollDesc;
+
+ if (collType.equals("Aggregation"))
+ newCollDesc = new AggregationDescription(collName);
+ if (collType.equals("Dependency"))
+ newCollDesc = new DependencyDescription(collName);
+ else
+ throw new InvalidDataException("AddNewCollectionDescription: Invalid collection type specified: '"+collType+"'. Must be Aggregation or Dependency.");
+
+ // store it
+ try {
+ Gateway.getStorage().put(item, newCollDesc, null);
+ } catch (PersistencyException e) {
+ throw new PersistencyException("AddNewCollectionDescription: Error saving new collection '"+collName+"': "+e.getMessage());
+ }
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewSlot.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewSlot.java new file mode 100644 index 0000000..f3acdf3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AddNewSlot.java @@ -0,0 +1,128 @@ +/**
+ * 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.lifecycle.instance.predefined;
+
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.collection.Aggregation;
+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.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+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.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $
+ * @version $Revision: 1.8 $
+ **************************************************************************/
+public class AddNewSlot extends PredefinedStep
+{
+ /**************************************************************************
+ * Constructor for Castor
+ **************************************************************************/
+ public AddNewSlot()
+ {
+ super();
+ }
+
+
+ /**
+ * Creates a new slot in the given aggregation, that holds instances of the given item description
+ *
+ * Params:
+ * <ol><li>Collection name</li>
+ * <li>Item Description key (optional)</li>
+ * <li>Item Description version (optional)</li>
+ * </ol>
+ *
+ * @throws InvalidDataException Then the parameters were incorrect
+ * @throws PersistencyException There was a problem loading or saving the collection from persistency
+ * @throws ObjectNotFoundException A required object, such as the collection or a PropertyDescription outcome, wasn't found
+ */
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, PersistencyException, ObjectNotFoundException {
+
+ String collName;
+ ItemPath descKey = null;
+ String descVer = "last";
+ Aggregation agg;
+
+ // extract parameters
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "AddNewSlot: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+
+ // resolve desc item path and version
+ try {
+ collName = params[0];
+ if (params.length > 1 && params[1].length() > 0) descKey = new ItemPath(params[1]);
+ if (params.length > 2 && params[2].length() > 0) descVer = params[2];
+ } catch (Exception e) {
+ throw new InvalidDataException("AddNewSlot: Invalid parameters "+Arrays.toString(params));
+ }
+
+ // load collection
+ C2KLocalObject collObj;
+ try {
+ collObj = Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null);
+ } catch (PersistencyException ex) {
+ Logger.error(ex);
+ throw new PersistencyException("AddNewSlot: Error loading collection '\"+collName+\"': "+ex.getMessage());
+ }
+ if (!(collObj instanceof Aggregation)) throw new InvalidDataException("AddNewSlot: AddNewSlot operates on Aggregation collections only.");
+ agg = (Aggregation)collObj;
+
+ // get props
+ CastorHashMap props = new CastorHashMap();
+ StringBuffer classProps = new StringBuffer();
+ if (descKey != null) {
+ PropertyDescriptionList propList;
+ propList = PropertyUtility.getPropertyDescriptionOutcome(descKey, descVer);
+ for (PropertyDescription pd : propList.list) {
+ props.put(pd.getName(), pd.getDefaultValue());
+ if (pd.getIsClassIdentifier())
+ classProps.append((classProps.length()>0?",":"")).append(pd.getName());
+ }
+ }
+
+ agg.addSlot(props, classProps.toString());
+
+ try {
+ Gateway.getStorage().put(item, agg, null);
+ } catch (PersistencyException e) {
+ Logger.error(e);
+ throw new PersistencyException("AddNewSlot: Error saving collection '"+collName+"': "+e.getMessage());
+ }
+
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AssignItemToSlot.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AssignItemToSlot.java new file mode 100644 index 0000000..c242500 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/AssignItemToSlot.java @@ -0,0 +1,121 @@ +/**
+ * 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.lifecycle.instance.predefined;
+
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.collection.Aggregation;
+import org.cristalise.kernel.collection.AggregationMember;
+import org.cristalise.kernel.common.InvalidCollectionModification;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $
+ * @version $Revision: 1.8 $
+ **************************************************************************/
+public class AssignItemToSlot extends PredefinedStep
+{
+ /**************************************************************************
+ * Constructor for Castor
+ **************************************************************************/
+ public AssignItemToSlot()
+ {
+ super();
+ }
+
+
+ /**
+ * Params:
+ * 0 - collection name
+ * 1 - slot number
+ * 2 - target entity key
+ * @throws ObjectNotFoundException
+ * @throws PersistencyException
+ * @throws ObjectCannotBeUpdated
+ * @throws InvalidCollectionModification
+ */
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, PersistencyException, ObjectCannotBeUpdated, InvalidCollectionModification {
+
+ String collName;
+ int slotNo;
+ ItemPath childItem;
+ Aggregation agg;
+
+ // extract parameters
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "AssignItemToSlot: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+
+ try {
+ collName = params[0];
+ slotNo = Integer.parseInt(params[1]);
+ childItem = new ItemPath(params[2]);
+ } catch (Exception e) {
+ throw new InvalidDataException("AssignItemToSlot: Invalid parameters "+Arrays.toString(params));
+ }
+
+ // load collection
+ C2KLocalObject collObj;
+ try {
+ collObj = Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null);
+ } catch (PersistencyException ex) {
+ Logger.error(ex);
+ throw new PersistencyException("AssignItemToSlot: Error loading collection '\"+collName+\"': "+ex.getMessage());
+ }
+ if (!(collObj instanceof Aggregation)) throw new InvalidDataException("AssignItemToSlot: AssignItemToSlot operates on Aggregation collections only.");
+ agg = (Aggregation)collObj;
+
+ // find member and assign entity
+ boolean stored = false;
+ for (AggregationMember member : agg.getMembers().list) {
+ if (member.getID() == slotNo) {
+ if (member.getItemPath() != null)
+ throw new ObjectCannotBeUpdated("AssignItemToSlot: Member slot "+slotNo+" not empty");
+ member.assignItem(childItem);
+ stored = true;
+ break;
+ }
+ }
+ if (!stored) {
+ throw new ObjectNotFoundException("AssignItemToSlot: Member slot "+slotNo+" not found.");
+ }
+
+ try {
+ Gateway.getStorage().put(item, agg, null);
+ } catch (PersistencyException e) {
+ throw new PersistencyException("AssignItemToSlot: Error saving collection '"+collName+"': "+e.getMessage());
+ }
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ClearSlot.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ClearSlot.java new file mode 100644 index 0000000..bd0fa19 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ClearSlot.java @@ -0,0 +1,114 @@ +/**
+ * 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.lifecycle.instance.predefined;
+
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.collection.Aggregation;
+import org.cristalise.kernel.collection.AggregationMember;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $
+ * @version $Revision: 1.8 $
+ **************************************************************************/
+public class ClearSlot extends PredefinedStep
+{
+ /**************************************************************************
+ * Constructor for Castor
+ **************************************************************************/
+ public ClearSlot()
+ {
+ super();
+ }
+
+
+ /**
+ * Params:
+ * 0 - collection name
+ * 1 - slot number
+ * @throws ObjectNotFoundException
+ * @throws PersistencyException
+ * @throws ObjectCannotBeUpdated
+ */
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, PersistencyException, ObjectCannotBeUpdated {
+
+ String collName;
+ int slotNo;
+ Aggregation agg;
+
+ // extract parameters
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "ClearSlot: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+
+ try {
+ collName = params[0];
+ slotNo = Integer.parseInt(params[1]);
+ } catch (Exception e) {
+ throw new InvalidDataException("ClearSlot: Invalid parameters "+Arrays.toString(params));
+ }
+
+ // load collection
+ try {
+ agg = (Aggregation)Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null);
+ } catch (PersistencyException ex) {
+ Logger.error(ex);
+ throw new PersistencyException("ClearSlot: Error loading collection '"+collName+"': "+ex.getMessage());
+ }
+
+ // find member and clear
+ boolean stored = false;
+ for (AggregationMember member : agg.getMembers().list) {
+ if (member.getID() == slotNo) {
+ if (member.getItemPath() != null)
+ throw new ObjectCannotBeUpdated("ClearSlot: Member slot "+slotNo+" already empty");
+ member.clearItem();
+ stored = true;
+ break;
+ }
+ }
+ if (!stored) {
+ throw new ObjectNotFoundException("ClearSlot: Member slot "+slotNo+" not found.");
+ }
+
+
+ try {
+ Gateway.getStorage().put(item, agg, null);
+ } catch (PersistencyException e) {
+ Logger.error(e);
+ throw new PersistencyException("ClearSlot: Error storing collection");
+ }
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/CreateNewCollectionVersion.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/CreateNewCollectionVersion.java new file mode 100644 index 0000000..a598044 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/CreateNewCollectionVersion.java @@ -0,0 +1,103 @@ +/**
+ * 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.lifecycle.instance.predefined;
+
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.collection.Collection;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $
+ * @version $Revision: 1.8 $
+ **************************************************************************/
+public class CreateNewCollectionVersion extends PredefinedStep
+{
+ /**************************************************************************
+ * Constructor for Castor
+ **************************************************************************/
+ public CreateNewCollectionVersion()
+ {
+ super();
+ }
+
+
+ /**
+ * Generates a new snapshot of a collection from its current state. The
+ * new version is given the next available number, starting at 0.
+ *
+ * Params:
+ * 0 - Collection name
+ * @throws InvalidDataException
+ * @throws PersistencyException
+ *
+ * @throws ObjectNotFoundException when there is no collection present with
+ * that name
+ */
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, PersistencyException, ObjectNotFoundException
+ {
+ String collName;
+
+ // extract parameters
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "CreateNewCollectionVersion: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ if (params.length != 1)
+ throw new InvalidDataException("CreateNewCollectionVersion: Invalid parameters "+Arrays.toString(params));
+
+ collName = params[0];
+ Collection<?> coll = (Collection<?>)Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null);
+
+ // find last numbered version
+ int lastVer = -1;
+ String[] versions = Gateway.getStorage().getClusterContents(item, ClusterStorage.COLLECTION+"/"+collName);
+ for (String thisVerStr : versions) {
+ try {
+ int thisVer = Integer.parseInt(thisVerStr);
+ if (thisVer > lastVer) lastVer = thisVer;
+ } catch (NumberFormatException ex) { } // ignore non-integer versions
+ }
+
+ // Remove it from the cache before we change it
+ Gateway.getStorage().clearCache(item, ClusterStorage.COLLECTION+"/"+collName+"/last");
+ // Set the version
+ coll.setVersion(lastVer+1);
+
+ // store it
+ try {
+ Gateway.getStorage().put(item, coll, null);
+ } catch (PersistencyException e) {
+ throw new PersistencyException("CreateNewCollectionVersion: Error saving new collection '"+collName+"': "+e.getMessage());
+ }
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/Import.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/Import.java new file mode 100644 index 0000000..26e015d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/Import.java @@ -0,0 +1,106 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.lifecycle.instance.predefined;
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.events.Event;
+import org.cristalise.kernel.events.History;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+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.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * $Revision: 1.21 $
+ * $Date: 2005/06/02 12:17:22 $
+ *
+ * Params: Schemaname_version:Viewpoint (optional), Outcome, Timestamp (optional
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class Import extends PredefinedStep
+{
+ public Import()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, PersistencyException {
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "Import: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+
+ int split1 = params[0].indexOf('_');
+ int split2 = params[0].indexOf(':');
+
+ if (split1 == -1)
+ throw new InvalidDataException("Import: Invalid parameters "+Arrays.toString(params));
+
+ requestData = params[1];
+
+ String schemaName = params[0].substring(0, split1);
+ String viewpoint = null;
+ int schemaVersion;
+ if (split2 > -1) {
+ schemaVersion = Integer.parseInt(params[0].substring(split1+1, split2));
+ viewpoint = params[0].substring(split2+1);
+ }
+ else
+ schemaVersion = Integer.parseInt(params[0].substring(split1+1));
+
+ String timestamp;
+ if (params.length == 3)
+ timestamp = params[2];
+ else
+ timestamp = Event.timeToString(Event.getGMT());
+
+ // write event, outcome and viewpoints to storage
+
+ TransactionManager storage = Gateway.getStorage();
+ Object locker = getWf();
+ History hist = getWf().getHistory();
+ Event event = hist.addEvent(agent, getCurrentAgentRole(), getName(), getPath(), getType(), schemaName, schemaVersion, getStateMachine().getName(), getStateMachine().getVersion(), getStateMachine().getTransition(transitionID), viewpoint, timestamp);
+
+ try {
+ storage.put(item, new Outcome(event.getID(), requestData, schemaName, schemaVersion), locker);
+ storage.put(item, new Viewpoint(item, schemaName, viewpoint, schemaVersion, event.getID()), locker);
+ if (!"last".equals(viewpoint))
+ storage.put(item, new Viewpoint(item, schemaName, "last", schemaVersion, event.getID()), locker);
+ } catch (PersistencyException e) {
+ storage.abort(locker);
+ throw e;
+ }
+ storage.commit(locker);
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStep.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStep.java new file mode 100644 index 0000000..c8a293e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStep.java @@ -0,0 +1,191 @@ +/**
+ * 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.lifecycle.instance.predefined;
+import java.io.StringReader;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.cristalise.kernel.lifecycle.instance.Activity;
+import org.cristalise.kernel.lifecycle.instance.predefined.agent.AgentPredefinedStepContainer;
+import org.cristalise.kernel.lifecycle.instance.predefined.item.ItemPredefinedStepContainer;
+import org.cristalise.kernel.lifecycle.instance.predefined.server.ServerPredefinedStepContainer;
+import org.cristalise.kernel.persistency.outcome.Outcome;
+import org.cristalise.kernel.utils.Logger;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.InputSource;
+
+/***********************************************************************************************************************************************************************************************************************************************************************************************************
+ * @author $Author: sgaspard $ $Date: 2004/09/21 10:32:17 $
+ * @version $Revision: 1.14 $
+ **********************************************************************************************************************************************************************************************************************************************************************************************************/
+public abstract class PredefinedStep extends Activity
+{
+ /*******************************************************************************************************************************************************************************************************************************************************************************************************
+ * predefined Steps are always Active, and have only one transition subclasses could override this method (if necessary)
+ ******************************************************************************************************************************************************************************************************************************************************************************************************/
+
+ private boolean isPredefined = false;
+ public static final int DONE = 0;
+ public static final int AVAILABLE = 0;
+
+ public PredefinedStep() {
+ super();
+ getProperties().put("SchemaType", "PredefinedStepOutcome");
+ getProperties().put("SchemaVersion", "0");
+ }
+
+ @Override
+ public boolean getActive()
+ {
+ if (isPredefined)
+ return true;
+ else
+ return super.getActive();
+ }
+
+
+
+ @Override
+ protected String getDefaultSMName() {
+ return "PredefinedStep";
+ }
+
+ @Override
+ public String getErrors()
+ {
+ if (isPredefined)
+ return getName();
+ else
+ return super.getErrors();
+ }
+ @Override
+ public boolean verify()
+ {
+ if (isPredefined)
+ return true;
+ else
+ return super.verify();
+ }
+ /**
+ * Returns the isPredefined.
+ *
+ * @return boolean
+ */
+ public boolean getIsPredefined()
+ {
+ return isPredefined;
+ }
+ /**
+ * Sets the isPredefined.
+ *
+ * @param isPredefined
+ * The isPredefined to set
+ */
+ public void setIsPredefined(boolean isPredefined)
+ {
+ this.isPredefined = isPredefined;
+ }
+ @Override
+ public String getType()
+ {
+ return getName();
+ }
+
+ static public String getPredefStepSchemaName(String stepName) {
+ PredefinedStepContainer[] allSteps = { new ItemPredefinedStepContainer(), new AgentPredefinedStepContainer(), new ServerPredefinedStepContainer() };
+ for (PredefinedStepContainer thisContainer : allSteps) {
+ String stepPath = thisContainer.getName()+"/"+stepName;
+ Activity step = (Activity)thisContainer.search(stepPath);
+ if (step != null) {
+ return (String)step.getProperties().get("SchemaType");
+ }
+ }
+ return "PredefinedStepOutcome"; // default to standard if not found - server may be a newer version
+ }
+
+ // generic bundling of parameters
+ static public String bundleData(String[] data)
+ {
+ try
+ {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = factory.newDocumentBuilder();
+ Document dom = builder.newDocument();
+ Element root = dom.createElement("PredefinedStepOutcome");
+ dom.appendChild(root);
+ for (String element : data) {
+ Element param = dom.createElement("param");
+ Text t = dom.createTextNode(element);
+ param.appendChild(t);
+ root.appendChild(param);
+ }
+
+ return Outcome.serialize(dom, false);
+
+ }
+ catch (Exception e)
+ {
+ Logger.error(e);
+ StringBuffer xmlData = new StringBuffer().append("<PredefinedStepOutcome>");
+ for (String element : data)
+ xmlData.append("<param><![CDATA[").append(element).append("]]></param>");
+ xmlData.append("</PredefinedStepOutcome>");
+ return xmlData.toString();
+ }
+ }
+
+ // generic bundling of single parameter
+ static public String bundleData(String data)
+ {
+ return bundleData(new String[]{ data });
+ }
+
+ public static String[] getDataList(String xmlData)
+ {
+ try
+ {
+ Document scriptDoc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new StringReader(xmlData)));
+ NodeList nodeList = scriptDoc.getElementsByTagName("param");
+ String[] result = new String[nodeList.getLength()];
+ for (int i = 0; i < nodeList.getLength(); i++)
+ {
+ Node n = nodeList.item(i).getFirstChild();
+ if (n instanceof CDATASection)
+ result[i] = ((CDATASection) n).getData();
+ else if (n instanceof Text)
+ result[i] = ((Text) n).getData();
+ }
+ return result;
+ }
+ catch (Exception ex)
+ {
+ Logger.error("Exception::PredefinedStep::getDataList()");
+ Logger.error(ex);
+ }
+ return null;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStepContainer.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStepContainer.java new file mode 100644 index 0000000..74a86db --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/PredefinedStepContainer.java @@ -0,0 +1,79 @@ +/**
+ * 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.lifecycle.instance.predefined;
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.lifecycle.instance.CompositeActivity;
+public abstract class PredefinedStepContainer extends CompositeActivity
+{
+ protected int num = 0;
+
+ public PredefinedStepContainer()
+ {
+ super();
+ setName("predefined");
+ getProperties().put("Description", "Contains all predefined Steps");
+ createChildren();
+ }
+ public void createChildren()
+ {
+ predInit("AddDomainPath", "Adds a new path to this entity in the LDAP domain tree", new AddDomainPath());
+ predInit("RemoveDomainPath", "Removes an existing path to this Entity from the LDAP domain tree", new RemoveDomainPath());
+ predInit("ReplaceDomainWorkflow", "Replaces the domain CA with the supplied one. Used by the GUI to save new Wf layout", new ReplaceDomainWorkflow());
+ predInit("AddC2KObject", "Adds or overwrites a C2Kernel object for this Item", new AddC2KObject());
+ predInit("RemoveC2KObject", "Removes the named C2Kernel object from this Item.", new RemoveC2KObject());
+ predInit("WriteProperty", "Writes a property to the Item", new WriteProperty());
+ predInit("WriteViewpoint", "Writes a viewpoint to the Item", new WriteViewpoint());
+ predInit("AddNewCollectionDescription", "Creates a new collection description in this Item", new AddNewCollectionDescription());
+ predInit("CreateNewCollectionVersion", "Creates a new numbered collection version in this Item from the current one.", new CreateNewCollectionVersion());
+ predInit("AddNewSlot", "Creates a new slot in the given aggregation, that holds instances of the item description of the given key", new AddNewSlot());
+ predInit("AssignItemToSlot", "Assigns the referenced entity to a pre-existing slot in an aggregation", new AssignItemToSlot());
+ predInit("ClearSlot", "Clears an aggregation member slot, given a slot no or entity key", new ClearSlot());
+ predInit("RemoveSlotFromCollection", "Removed the given slot from the aggregation", new RemoveSlotFromCollection());
+ predInit("AddMemberToCollection", "Creates a new member slot for the given item in a dependency, and assigns the item", new AddMemberToCollection());
+ predInit("Import", "Imports an outcome into the Item, with a given schema and viewpoint", new Import());
+
+ }
+
+ public void predInit(String alias, String Description, PredefinedStep act)
+ {
+ act.setName(alias);
+ act.setType(alias);
+ act.getProperties().put("Description", Description);
+ act.setCentrePoint(new GraphPoint());
+ act.setIsPredefined(true);
+ addChild(act, new GraphPoint(100, 75 * ++num));
+ }
+ @Override
+ public boolean verify()
+ {
+ return true;
+ }
+ @Override
+ public String getErrors()
+ {
+ return "predefined";
+ }
+ @Override
+ public boolean getActive()
+ {
+ return true;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveC2KObject.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveC2KObject.java new file mode 100644 index 0000000..2f86274 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveC2KObject.java @@ -0,0 +1,70 @@ +/**
+ * 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.lifecycle.instance.predefined;
+
+
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2005/11/15 15:56:38 $
+ * @version $Revision: 1.28 $
+ **************************************************************************/
+public class RemoveC2KObject extends PredefinedStep
+{
+ public RemoveC2KObject()
+ {
+ super();
+ getProperties().put("Agent Role", "Admin");
+ }
+
+ //requestdata is xmlstring
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, PersistencyException {
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "RemoveC2KObject: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ if (params.length != 1)
+ throw new InvalidDataException("RemoveC2KObject: Invalid parameters "+Arrays.toString(params));
+ String path = params[0];
+
+ try
+ {
+ Gateway.getStorage().remove( item, path, null );
+ }
+ catch( PersistencyException ex )
+ {
+ throw new PersistencyException("RemoveC2KObject: Error removing object '"+path+"': "+ex.getMessage());
+ }
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveDomainPath.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveDomainPath.java new file mode 100644 index 0000000..0dc24bb --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveDomainPath.java @@ -0,0 +1,73 @@ +/**
+ * 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.lifecycle.instance.predefined;
+
+
+
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.DomainPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.lookup.LookupManager;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class RemoveDomainPath extends PredefinedStep
+{
+ public RemoveDomainPath()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException {
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "RemoveDomainPath: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ if (params.length != 1) throw new InvalidDataException("RemoveDomainPath: Invalid parameters "+Arrays.toString(params));
+
+ DomainPath domainPath = new DomainPath(params[0]);
+ if (!domainPath.exists())
+ throw new ObjectNotFoundException("RemoveDomainPath: Domain path "+domainPath.toString()+" does not exist.");
+
+ if (domainPath.getType()!=DomainPath.ENTITY)
+
+ try {
+ if (!domainPath.getItemPath().equals(item))
+ throw new InvalidDataException("RemoveDomainPath: Domain path "+domainPath.toString()+" is not an alias of the current Item "+item);
+ } catch (ObjectNotFoundException ex) {
+ throw new InvalidDataException("RemoveDomainPath: Domain path "+domainPath.toString()+" is a context.");
+ }
+
+ LookupManager lookupManager = Gateway.getLookupManager();
+ lookupManager.delete(domainPath);
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveSlotFromCollection.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveSlotFromCollection.java new file mode 100644 index 0000000..6522384 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/RemoveSlotFromCollection.java @@ -0,0 +1,131 @@ +/**
+ * 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.lifecycle.instance.predefined;
+
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.collection.Collection;
+import org.cristalise.kernel.collection.CollectionMember;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $
+ * @version $Revision: 1.8 $
+ **************************************************************************/
+public class RemoveSlotFromCollection extends PredefinedStep
+{
+ /**************************************************************************
+ * Constructor for Castor
+ **************************************************************************/
+ public RemoveSlotFromCollection()
+ {
+ super();
+ }
+
+
+ /**
+ * Params:
+ * 0 - collection name
+ * 1 - slot number OR if null:
+ * 2 - target entity key
+ * @throws ObjectNotFoundException
+ * @throws PersistencyException
+ */
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, PersistencyException {
+
+ String collName;
+ int slotNo = -1;
+ ItemPath currentChild = null;
+ Collection<? extends CollectionMember> coll;
+
+ // extract parameters
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "RemoveSlotFromCollection: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+
+ try {
+ collName = params[0];
+ if (params.length>1 && params[1].length()>0) slotNo = Integer.parseInt(params[1]);
+ if (params.length>2 && params[2].length()>0) currentChild = new ItemPath(params[2]);
+ } catch (Exception e) {
+ throw new InvalidDataException("RemoveSlotFromCollection: Invalid parameters "+Arrays.toString(params));
+ }
+
+ if (slotNo == -1 && currentChild == null)
+ throw new InvalidDataException("RemoveSlotFromCollection: Must give either slot number or entity key");
+
+ // load collection
+ try {
+ coll = (Collection<? extends CollectionMember>)Gateway.getStorage().get(item, ClusterStorage.COLLECTION+"/"+collName+"/last", null);
+ } catch (PersistencyException ex) {
+ Logger.error(ex);
+ throw new PersistencyException("RemoveSlotFromCollection: Error loading collection '\"+collName+\"': "+ex.getMessage());
+ }
+
+ // check the slot is there if it's given by id
+ CollectionMember slot = null;
+ if (slotNo > -1) {
+ slot = coll.getMember(slotNo);
+ }
+
+ // if both parameters are supplied, check the given item is actually in that slot
+ if (slot != null && currentChild != null && !slot.getItemPath().equals(currentChild)) {
+ throw new ObjectNotFoundException("RemoveSlotFromCollection: Item "+currentChild+" was not in slot "+slotNo);
+ }
+
+ if (slotNo == -1) { // find slot from entity key
+ for (CollectionMember member : coll.getMembers().list) {
+ if (member.getItemPath().equals(currentChild)) {
+ slotNo = member.getID();
+ break;
+ }
+ }
+ }
+ if (slotNo == -1) {
+ throw new ObjectNotFoundException("Could not find "+currentChild+" in collection "+coll.getName());
+ }
+
+ // Remove the slot
+ coll.removeMember(slotNo);
+
+ // Store the collection
+ try {
+ Gateway.getStorage().put(item, coll, null);
+ } catch (PersistencyException e) {
+ Logger.error(e);
+ throw new PersistencyException("Error storing collection");
+ }
+
+ return requestData;
+
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ReplaceDomainWorkflow.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ReplaceDomainWorkflow.java new file mode 100644 index 0000000..5ec7510 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/ReplaceDomainWorkflow.java @@ -0,0 +1,77 @@ +/**
+ * 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.lifecycle.instance.predefined;
+
+//Java
+import java.util.Arrays;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.graph.model.GraphPoint;
+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.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class ReplaceDomainWorkflow extends PredefinedStep
+{
+ public ReplaceDomainWorkflow()
+ {
+ super();
+ getProperties().put("Agent Role", "Admin");
+ }
+
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, PersistencyException {
+
+ Workflow lifeCycle = getWf();
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "AddC2KObject: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ if (params.length != 1) throw new InvalidDataException("AddC2KObject: Invalid parameters "+Arrays.toString(params));
+
+ lifeCycle.getChildGraphModel().removeVertex(lifeCycle.search("workflow/domain"));
+ CompositeActivity domain;
+ try {
+ domain = (CompositeActivity) Gateway.getMarshaller().unmarshall(params[0]);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new InvalidDataException("ReplaceDomainWorkflow: Could not unmarshall new workflow: "+e.getMessage());
+ }
+ domain.setName("domain");
+ lifeCycle.initChild(domain, true, new GraphPoint(150, 100));
+ // if new workflow, activate it, otherwise refresh the jobs
+ if (!domain.active) lifeCycle.run(agent, item);
+ else lifeCycle.refreshJobs(item);
+
+ // store new wf
+ try {
+ Gateway.getStorage().put(item, lifeCycle, null);
+ } catch (PersistencyException e) {
+ throw new PersistencyException("ReplaceDomainWorkflow: Could not write new workflow to storage: "+e.getMessage());
+ }
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteProperty.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteProperty.java new file mode 100644 index 0000000..c73bec8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteProperty.java @@ -0,0 +1,80 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.lifecycle.instance.predefined;
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.property.Property;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/21 08:02:19 $
+ * @version $Revision: 1.3 $
+ **************************************************************************/
+public class WriteProperty extends PredefinedStep
+{
+ /**************************************************************************
+ * Constructor for Castror
+ **************************************************************************/
+ public WriteProperty()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectCannotBeUpdated, ObjectNotFoundException, PersistencyException {
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "WriteProperty: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+
+ if (params.length != 2)
+ throw new InvalidDataException("WriteProperty: invalid parameters "+Arrays.toString(params));
+
+ String name = params[0];
+ String newValue = params[1];
+
+ Property prop;
+
+ try {
+ prop = (Property)Gateway.getStorage().get(item, ClusterStorage.PROPERTY+"/"+name, null);
+ if (!prop.isMutable() && !newValue.equals(prop.getValue()))
+ throw new ObjectCannotBeUpdated("WriteProperty: Property '"+name+"' is not mutable.");
+ prop.setValue(newValue);
+ Gateway.getStorage().put(item, prop, null);
+ } catch (ObjectNotFoundException e) {
+ throw new ObjectNotFoundException("WriteProperty: Property '"+name+"' not found.");
+ }
+
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteViewpoint.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteViewpoint.java new file mode 100644 index 0000000..d617b99 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/WriteViewpoint.java @@ -0,0 +1,88 @@ +/**
+ * 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.lifecycle.instance.predefined;
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.events.Event;
+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.utils.Logger;
+
+
+public class WriteViewpoint extends PredefinedStep {
+
+ public WriteViewpoint() {
+ super();
+ }
+
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, PersistencyException {
+
+ String schemaName;
+ String viewName;
+ int evId;
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "WriteViewpoint: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+
+ // outcometype, name and evId. Event and Outcome should be checked so schema version should be discovered.
+ if (params.length != 3)
+ throw new InvalidDataException("WriteViewpoint: Invalid parameters "+Arrays.toString(params));
+
+ schemaName = params[0];
+ viewName = params[1];
+
+ try {
+ evId = Integer.parseInt(params[2]);
+ } catch (NumberFormatException ex) {
+ throw new InvalidDataException("WriteViewpoint: Parameter 3 (EventId) must be an integer");
+ }
+
+ // Find event
+
+ Event ev;
+ try {
+ ev = (Event)Gateway.getStorage().get(item, ClusterStorage.HISTORY+"/"+evId, null);
+ } catch (PersistencyException e) {
+ Logger.error(e);
+ throw new PersistencyException("WriteViewpoint: Could not load event "+evId);
+ }
+
+ // Write new viewpoint
+ Viewpoint newView = new Viewpoint(item, schemaName, viewName, ev.getSchemaVersion(), evId);
+ try {
+ Gateway.getStorage().put(item, newView, null);
+ } catch (PersistencyException e) {
+ Logger.error(e);
+ throw new PersistencyException("WriteViewpoint: Could not store new viewpoint");
+ }
+ return requestData;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/AgentPredefinedStepContainer.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/AgentPredefinedStepContainer.java new file mode 100644 index 0000000..6ff3164 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/AgentPredefinedStepContainer.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.lifecycle.instance.predefined.agent;
+
+import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStepContainer;
+
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2005/06/02 10:19:33 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class AgentPredefinedStepContainer extends PredefinedStepContainer {
+
+
+ @Override
+ public void createChildren()
+ {
+ super.createChildren();
+ predInit("CreateAgentFromDescription", "Create a new item using this item as its description", new CreateAgentFromDescription());
+ predInit("RemoveAgent", "Deletes the Agent", new RemoveAgent());
+ predInit("SetAgentPassword", "Changes the Agent's password", new SetAgentPassword());
+ predInit("SetAgentRoles", "Sets the roles of the Agent", new SetAgentRoles());
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/CreateAgentFromDescription.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/CreateAgentFromDescription.java new file mode 100644 index 0000000..335fe2d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/CreateAgentFromDescription.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.lifecycle.instance.predefined.agent;
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.common.CannotManageException;
+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.CorbaServer;
+import org.cristalise.kernel.entity.agent.ActiveEntity;
+import org.cristalise.kernel.lifecycle.instance.predefined.item.CreateItemFromDescription;
+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.property.PropertyArrayList;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2005/10/13 08:13:58 $
+ * @version $Revision: 1.47 $
+ **************************************************************************/
+public class CreateAgentFromDescription extends CreateItemFromDescription
+{
+ public CreateAgentFromDescription()
+ {
+ super();
+ }
+
+ /**
+ * Params:
+ * <ol><li>New Agent name</li>
+ * <li>Description version to use</li>
+ * <li>Comma-delimited Role names to assign to the agent. Must already exist.</li>
+ * <li>Initial properties to set in the new Agent</li>
+ * </ol>
+ * @throws ObjectNotFoundException
+ * @throws InvalidDataException The input parameters were incorrect
+ * @throws ObjectAlreadyExistsException The Agent already exists
+ * @throws CannotManageException The Agent could not be created
+ * @throws ObjectCannotBeUpdated The addition of the new entries into the LookupManager failed
+ * @see org.cristalise.kernel.lifecycle.instance.predefined.item.CreateItemFromDescription#runActivityLogic(org.cristalise.kernel.lookup.AgentPath, int, int, java.lang.String)
+ */
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws ObjectNotFoundException, InvalidDataException, ObjectAlreadyExistsException, CannotManageException, ObjectCannotBeUpdated {
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "CreateAgentFromDescription: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ if (params.length < 3 || params.length > 4)
+ throw new InvalidDataException("CreateAgentFromDescription: Invalid parameters "+Arrays.toString(params));
+
+ String newName = params[0];
+ String descVer = params[1];
+ String roles = params[2];
+ PropertyArrayList initProps =
+ params.length > 3 ? getInitProperties(params[3]):new PropertyArrayList();
+
+ Logger.msg(1, "CreateAgentFromDescription::request() - Starting.");
+
+ // check if given roles exist
+ String[] roleArr = roles.split(",");
+ for(int i=0; i<roleArr.length; i++) {
+ RolePath thisRole = Gateway.getLookup().getRolePath(roleArr[i]);
+ }
+
+ // check if the path is already taken
+ try {
+ Gateway.getLookup().getAgentPath(newName);
+ throw new ObjectAlreadyExistsException("The agent name " +newName+ " exists already.");
+ } catch (ObjectNotFoundException ex) { }
+
+ // generate new entity key
+ Logger.msg(6, "CreateItemFromDescription - Requesting new agent path");
+ AgentPath newAgentPath = new AgentPath(new ItemPath(), newName);
+
+ // resolve the item factory
+ Logger.msg(6, "CreateItemFromDescription - Resolving item factory");
+
+ // create the Item object
+ Logger.msg(3, "CreateItemFromDescription - Creating Item");
+ CorbaServer factory = Gateway.getCorbaServer();
+ if (factory == null) throw new CannotManageException("This process cannot create new Items");
+ ActiveEntity newAgent = factory.createAgent(newAgentPath);
+ Gateway.getLookupManager().add(newAgentPath);
+
+ // initialise it with its properties and workflow
+
+ Logger.msg(3, "CreateItemFromDescription - Initializing Item");
+
+ try {
+ newAgent.initialise(
+ agent.getSystemKey(),
+ Gateway.getMarshaller().marshall(getNewProperties(item, descVer, initProps, newName, agent)),
+ Gateway.getMarshaller().marshall(getNewWorkflow(item, descVer)),
+ Gateway.getMarshaller().marshall(getNewCollections(item, descVer))
+ );
+ } catch (PersistencyException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (Exception e) {
+ throw new InvalidDataException("CreateAgentFromDescription: Problem initializing new Agent. See log: "+e.getMessage());
+ }
+
+ // add roles if given
+
+ for(int i=1; i<roleArr.length; i++) {
+ newAgent.addRole(roleArr[i]);
+ }
+
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/RemoveAgent.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/RemoveAgent.java new file mode 100644 index 0000000..db7e699 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/RemoveAgent.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.lifecycle.instance.predefined.agent;
+
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.InvalidAgentPathException;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.lookup.RolePath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class RemoveAgent extends PredefinedStep {
+
+ public RemoveAgent() {
+ super();
+ }
+
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath itemPath,
+ int transitionID, String requestData) throws InvalidDataException {
+
+ Logger.msg(1, "RemoveAgent::request() - Starting.");
+
+ AgentPath targetAgent;
+ try {
+ targetAgent = new AgentPath(itemPath);
+ } catch (InvalidAgentPathException ex) {
+ throw new InvalidDataException("Could not resolve "+itemPath+" as an Agent.");
+ }
+ String agentName = targetAgent.getAgentName();
+
+ //remove from roles
+ for (RolePath role: targetAgent.getRoles()) {
+ try {
+ Gateway.getLookupManager().removeRole(targetAgent, role);
+ } catch (ObjectCannotBeUpdated e) {
+ Logger.error(e);
+ throw new InvalidDataException("Error removing "+agentName+" from Role "+role.getName());
+ } catch (ObjectNotFoundException e) {
+ Logger.error(e);
+ throw new InvalidDataException("Tried to remove "+agentName+" from Role "+role.getName()+" that doesn't exist.");
+ } catch (CannotManageException e) {
+ throw new InvalidDataException("Tried to alter roles in a non-server process.");
+ }
+ }
+
+ //clear out all storages
+ try {
+ Gateway.getStorage().removeCluster(targetAgent, "", null);
+ } catch (PersistencyException e) {
+ Logger.error(e);
+ throw new InvalidDataException("Error deleting storage for "+agentName);
+ }
+
+ //remove entity path
+ try {
+ Gateway.getLookupManager().delete(targetAgent);
+ } catch (Exception e) {
+ throw new InvalidDataException("Error deleting AgentPath for "+agentName);
+ }
+ return requestData;
+
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/SetAgentPassword.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/SetAgentPassword.java new file mode 100644 index 0000000..3d14453 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/SetAgentPassword.java @@ -0,0 +1,70 @@ +/**
+ * 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.lifecycle.instance.predefined.agent;
+
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.InvalidItemPathException;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class SetAgentPassword extends PredefinedStep {
+
+ public SetAgentPassword() {
+ super();
+ }
+
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException {
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "SetAgentPassword: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ if (params.length != 1) throw new InvalidDataException("SetAgentPassword: Invalid parameters "+Arrays.toString(params));
+
+ AgentPath targetAgent;
+ try {
+ targetAgent = new AgentPath(item);
+ } catch (InvalidItemPathException ex) {
+ throw new InvalidDataException("Can only set password on an Agent. "+item+" is an Item.");
+ }
+
+ try {
+ Gateway.getLookupManager().setAgentPassword(targetAgent, params[0]);
+ } catch (NoSuchAlgorithmException e) {
+ Logger.error(e);
+ throw new InvalidDataException("Cryptographic libraries for password hashing not found.");
+ }
+
+ params[1] = "REDACTED"; // censor user's password from outcome
+ return bundleData(params);
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/SetAgentRoles.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/SetAgentRoles.java new file mode 100644 index 0000000..e267034 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/agent/SetAgentRoles.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.lifecycle.instance.predefined.agent;
+
+import java.util.ArrayList;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.InvalidItemPathException;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.lookup.RolePath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class SetAgentRoles extends PredefinedStep {
+
+ public SetAgentRoles() {
+ super();
+ }
+
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException {
+
+ Logger.msg(1, "SetAgentRoles::request() - Starting.");
+
+ String[] params = getDataList(requestData);
+ AgentPath targetAgent;
+ try {
+ targetAgent = new AgentPath(item);
+ } catch (InvalidItemPathException ex) {
+ throw new InvalidDataException("Could not resolve syskey "+item+" as an Agent.");
+ }
+
+ RolePath[] currentRoles = targetAgent.getRoles();
+ ArrayList<RolePath> requestedRoles = new ArrayList<RolePath>();
+ for (int i=0; i<params.length; i++)
+ try {
+ requestedRoles.add(Gateway.getLookup().getRolePath(params[i]));
+ } catch (ObjectNotFoundException e) {
+ throw new InvalidDataException("Role "+params[i]+" not found");
+ }
+
+ ArrayList<RolePath> rolesToRemove = new ArrayList<RolePath>();
+ for (RolePath existingRole : currentRoles) { //
+ if (requestedRoles.contains(existingRole)) // if we have it, and it's requested, then it will be kept
+ requestedRoles.remove(existingRole); // so remove it from request - this will be left with roles to be added
+ else
+ rolesToRemove.add(existingRole); // else this role will be removed
+ }
+
+ // remove roles not in new list
+ for (RolePath roleToRemove : rolesToRemove)
+ try {
+ Gateway.getLookupManager().removeRole(targetAgent, roleToRemove);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new InvalidDataException("Error removing role "+roleToRemove.getName());
+ }
+
+ // add requested roles we don't already have
+ for (RolePath roleToAdd : requestedRoles)
+ try {
+ Gateway.getLookupManager().addRole(targetAgent, roleToAdd);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new InvalidDataException("Error adding role "+roleToAdd.getName());
+ }
+
+ return requestData;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/CreateItemFromDescription.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/CreateItemFromDescription.java new file mode 100644 index 0000000..53e545e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/CreateItemFromDescription.java @@ -0,0 +1,195 @@ +/**
+ * 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.lifecycle.instance.predefined.item;
+
+import org.cristalise.kernel.collection.Collection;
+import org.cristalise.kernel.collection.CollectionArrayList;
+import org.cristalise.kernel.collection.CollectionDescription;
+import org.cristalise.kernel.collection.CollectionMember;
+import org.cristalise.kernel.common.CannotManageException;
+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.CorbaServer;
+import org.cristalise.kernel.entity.TraceableEntity;
+import org.cristalise.kernel.lifecycle.CompositeActivityDef;
+import org.cristalise.kernel.lifecycle.instance.CompositeActivity;
+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.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.property.Property;
+import org.cristalise.kernel.property.PropertyArrayList;
+import org.cristalise.kernel.property.PropertyDescriptionList;
+import org.cristalise.kernel.property.PropertyUtility;
+import org.cristalise.kernel.utils.LocalObjectLoader;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2005/10/13 08:13:58 $
+ * @version $Revision: 1.47 $
+ **************************************************************************/
+public class CreateItemFromDescription extends PredefinedStep
+{
+ public CreateItemFromDescription()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath itemPath,
+ int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, ObjectAlreadyExistsException, CannotManageException, ObjectCannotBeUpdated, PersistencyException {
+
+ String[] input = getDataList(requestData);
+ String newName = input[0];
+ String domPath = input[1];
+ String descVer = input.length > 2 ? input[2]:"last";
+ PropertyArrayList initProps =
+ input.length > 3?getInitProperties(input[3]):new PropertyArrayList();
+
+ Logger.msg(1, "CreateItemFromDescription - Starting.");
+
+ // check if the path is already taken
+ DomainPath context = new DomainPath(new DomainPath(domPath), newName);
+ //Logger.debug(8,"context "+context.getItemPath()+" "+context.getPath()+" "+context.getString());
+ if (context.exists())
+ throw new ObjectAlreadyExistsException("The path " +context+ " exists already.");
+
+ // get init objects
+
+ /* ITEM CREATION */
+
+ // generate new entity key
+ Logger.msg(6, "CreateItemFromDescription - Requesting new item path");
+ ItemPath newItemPath = new ItemPath();
+
+ // resolve the item factory
+ Logger.msg(6, "CreateItemFromDescription - Resolving item factory");
+
+ // create the Item object
+ Logger.msg(3, "CreateItemFromDescription - Creating Item");
+ CorbaServer factory = Gateway.getCorbaServer();
+ if (factory == null) throw new CannotManageException("This process cannot create new Items");
+ TraceableEntity newItem = factory.createItem(newItemPath);
+ Gateway.getLookupManager().add(newItemPath);
+
+
+ // initialise it with its properties and workflow
+
+ Logger.msg(3, "CreateItemFromDescription - Initializing Item");
+
+ try {
+ newItem.initialise(
+ agent.getSystemKey(),
+ Gateway.getMarshaller().marshall(getNewProperties(itemPath, descVer, initProps, newName, agent)),
+ Gateway.getMarshaller().marshall(getNewWorkflow(itemPath, descVer)),
+ Gateway.getMarshaller().marshall(getNewCollections(itemPath, descVer))
+ );
+ } catch (PersistencyException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new InvalidDataException("CreateAgentFromDescription: Problem initializing new Agent. See log: "+e.getMessage());
+ }
+ // add its domain path
+ Logger.msg(3, "CreateItemFromDescription - Creating "+context);
+ context.setItemPath(newItemPath);
+ Gateway.getLookupManager().add(context);
+ return requestData;
+ }
+
+ protected PropertyArrayList getInitProperties(String input) throws InvalidDataException {
+ try {
+ return (PropertyArrayList)Gateway.getMarshaller().unmarshall(input);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new InvalidDataException("Initial property parameter was not a marshalled PropertyArrayList: "+input);
+ }
+ }
+
+ protected PropertyArrayList getNewProperties(ItemPath itemPath, String descVer, PropertyArrayList initProps, String newName, AgentPath agent) throws ObjectNotFoundException, InvalidDataException {
+ // copy properties -- intend to create from propdesc
+ PropertyDescriptionList pdList = PropertyUtility.getPropertyDescriptionOutcome(itemPath, descVer);
+ PropertyArrayList props = pdList.instantiate(initProps);
+ // set Name prop or create if not present
+ boolean foundName = false;
+ for (Property prop : props.list) {
+ if (prop.getName().equals("Name")) {
+ foundName = true;
+ prop.setValue(newName);
+ }
+ }
+ if (!foundName) props.list.add(new Property("Name", newName, true));
+ props.list.add( new Property("Creator", agent.getAgentName(), false));
+ return props;
+ }
+
+ protected CompositeActivity getNewWorkflow(ItemPath itemPath, String descVer) throws ObjectNotFoundException, InvalidDataException, PersistencyException {
+ // find the workflow def for the given description version
+
+ String wfDefName = null; Integer wfDefVer = null;
+
+ Collection<? extends CollectionMember> thisCol = (Collection<? extends CollectionMember>)Gateway.getStorage().get(itemPath, ClusterStorage.COLLECTION+"/workflow/"+descVer, null);
+ CollectionMember wfMember = thisCol.getMembers().list.get(0);
+ wfDefName = wfMember.resolveItem().getName();
+ Object wfVerObj = wfMember.getProperties().get("Version");
+ try {
+ wfDefVer = Integer.parseInt(wfVerObj.toString());
+ } catch (NumberFormatException ex) {
+ throw new InvalidDataException("Invalid workflow version number: "+wfVerObj.toString());
+ }
+
+ // load workflow def
+ if (wfDefName == null)
+ throw new InvalidDataException("No workflow given or defined");
+ if (wfDefVer == null)
+ throw new InvalidDataException("No workflow def version given");
+
+ try {
+ CompositeActivityDef wfDef = (CompositeActivityDef)LocalObjectLoader.getActDef(wfDefName, wfDefVer);
+ return (CompositeActivity)wfDef.instantiate();
+ } catch (ObjectNotFoundException ex) {
+ throw new InvalidDataException("Workflow def '"+wfDefName+"'v"+wfDefVer+" not found");
+ } catch (ClassCastException ex) {
+ throw new InvalidDataException("Activity def '"+wfDefName+"' was not Composite");
+ }
+ }
+
+ protected CollectionArrayList getNewCollections(ItemPath itemPath, String descVer) throws ObjectNotFoundException, PersistencyException {
+ // loop through collections, collecting instantiated descriptions and finding the default workflow def
+ CollectionArrayList colls = new CollectionArrayList();
+ String[] collNames = Gateway.getStorage().getClusterContents(itemPath, ClusterStorage.COLLECTION);
+ for (String collName : collNames) {
+ Collection<? extends CollectionMember> thisCol = (Collection<? extends CollectionMember>)Gateway.getStorage().get(itemPath, ClusterStorage.COLLECTION+"/"+collName+"/"+descVer, null);
+ if (thisCol instanceof CollectionDescription) {
+ CollectionDescription<?> thisDesc = (CollectionDescription<?>)thisCol;
+ colls.put(thisDesc.newInstance());
+ }
+ }
+ return colls;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/Erase.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/Erase.java new file mode 100644 index 0000000..50a1bfd --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/Erase.java @@ -0,0 +1,80 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.lifecycle.instance.predefined.item;
+
+
+
+import java.util.Iterator;
+
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+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.ItemPath;
+import org.cristalise.kernel.lookup.Path;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2005/11/15 15:56:38 $
+ * @version $Revision: 1.10 $
+ **************************************************************************/
+public class Erase extends PredefinedStep
+{
+ public Erase()
+ {
+ super();
+ getProperties().put("Agent Role", "Admin");
+ }
+
+ //requestdata is xmlstring
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException, PersistencyException {
+
+ Logger.msg(1, "Erase::request() - Starting.");
+
+ Iterator<Path> domPaths = Gateway.getLookup().searchAliases(item);
+ while (domPaths.hasNext()) {
+ DomainPath path = (DomainPath)domPaths.next();
+ // delete them
+ if (path.getItemPath().equals(item))
+ Gateway.getLookupManager().delete(path);
+ }
+
+ //clear out all storages
+ Gateway.getStorage().removeCluster(item, "", null);
+
+ //remove entity path
+ Gateway.getLookupManager().delete(item);
+
+ Logger.msg(1, "Erase::request() - DONE.");
+ return requestData;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/ItemPredefinedStepContainer.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/ItemPredefinedStepContainer.java new file mode 100644 index 0000000..46a6feb --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/item/ItemPredefinedStepContainer.java @@ -0,0 +1,45 @@ +/**
+ * 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.lifecycle.instance.predefined.item;
+
+import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStepContainer;
+
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2005/06/02 10:19:33 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class ItemPredefinedStepContainer extends PredefinedStepContainer {
+
+
+ @Override
+ public void createChildren()
+ {
+ super.createChildren();
+ predInit("CreateItemFromDescription", "Create a new item using this item as its description", new CreateItemFromDescription());
+ predInit("Erase", "Deletes all objects and domain paths for this item.", new Erase());
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/AddDomainContext.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/AddDomainContext.java new file mode 100644 index 0000000..b225978 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/AddDomainContext.java @@ -0,0 +1,67 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.lifecycle.instance.predefined.server;
+
+import java.util.Arrays;
+import java.util.Stack;
+
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectAlreadyExistsException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+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.ItemPath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class AddDomainContext extends PredefinedStep {
+
+ public AddDomainContext() {
+ super();
+ }
+
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectCannotBeUpdated, ObjectAlreadyExistsException, CannotManageException {
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "AddDomainContext: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ if (params.length != 1) throw new InvalidDataException("AddDomainContext: Invalid parameters "+Arrays.toString(params));
+
+ DomainPath pathToAdd = new DomainPath(params);
+ if (pathToAdd.exists())
+ throw new ObjectAlreadyExistsException("Context "+pathToAdd+" already exists");
+ // collect parent paths if they don't exist
+ Stack<DomainPath> pathsToAdd = new Stack<DomainPath>();
+ while(pathToAdd!= null && !pathToAdd.exists()) {
+ pathsToAdd.push(pathToAdd);
+ pathToAdd = pathToAdd.getParent();
+ }
+ while(!pathsToAdd.empty()) {
+ pathToAdd = pathsToAdd.pop();
+ Gateway.getLookupManager().add(pathToAdd);
+ }
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewAgent.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewAgent.java new file mode 100644 index 0000000..65e56b5 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewAgent.java @@ -0,0 +1,68 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.lifecycle.instance.predefined.server;
+
+import org.cristalise.kernel.common.CannotManageException;
+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.entity.imports.ImportAgent;
+import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class CreateNewAgent extends PredefinedStep
+{
+ public CreateNewAgent()
+ {
+ super();
+ getProperties().put("SchemaType", "Agent");
+ }
+
+ //requestdata is xmlstring
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException, ObjectAlreadyExistsException {
+
+ String redactedRequestData;
+
+ ImportAgent newAgent;
+ try {
+ newAgent = (ImportAgent)Gateway.getMarshaller().unmarshall(requestData);
+ } catch (Exception e1) {
+ Logger.error(e1);
+ throw new InvalidDataException("CreateNewAgent: Couldn't unmarshall new Agent: "+requestData);
+ }
+ newAgent.create(agent, true);
+ newAgent.setPassword("REDACTED");
+ try {
+ redactedRequestData = Gateway.getMarshaller().marshall(newAgent);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new InvalidDataException("CreateNewAgent: Couldn't marshall new Agent for outcome: "+newAgent);
+ }
+ return redactedRequestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewItem.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewItem.java new file mode 100644 index 0000000..acd1fd1 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewItem.java @@ -0,0 +1,63 @@ +/**
+ * 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.lifecycle.instance.predefined.server;
+
+
+
+
+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.entity.imports.ImportItem;
+import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class CreateNewItem extends PredefinedStep
+{
+ public CreateNewItem()
+ {
+ super();
+ getProperties().put("SchemaType", "Item");
+ }
+
+ //requestdata is xmlstring
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectCannotBeUpdated, ObjectNotFoundException, CannotManageException, ObjectAlreadyExistsException, InvalidCollectionModification {
+
+ ImportItem newItem;
+ try {
+ newItem = (ImportItem)Gateway.getMarshaller().unmarshall(requestData);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new InvalidDataException("CreateNewAgent: Couldn't unmarshall new Agent: "+requestData);
+ }
+ newItem.create(agent, false);
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewRole.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewRole.java new file mode 100644 index 0000000..3771a7e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/CreateNewRole.java @@ -0,0 +1,60 @@ +/**
+ * 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.lifecycle.instance.predefined.server;
+
+import org.cristalise.kernel.common.CannotManageException;
+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.entity.imports.ImportRole;
+import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class CreateNewRole extends PredefinedStep
+{
+ public CreateNewRole()
+ {
+ super();
+ getProperties().put("SchemaType", "Role");
+ }
+
+ //requestdata is xmlstring
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectAlreadyExistsException, ObjectCannotBeUpdated, CannotManageException, ObjectNotFoundException {
+
+
+ ImportRole newRole;
+ try {
+ newRole = (ImportRole)Gateway.getMarshaller().unmarshall(requestData);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new InvalidDataException("CreateNewAgent: Couldn't unmarshall new Agent: "+requestData);
+ }
+ newRole.create(agent, true);
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveDomainContext.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveDomainContext.java new file mode 100644 index 0000000..bc1ed5c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveDomainContext.java @@ -0,0 +1,65 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.lifecycle.instance.predefined.server;
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+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.ItemPath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class RemoveDomainContext extends PredefinedStep {
+ public RemoveDomainContext() {
+ super();
+ }
+
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException {
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "RemoveDomainContext: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ if (params.length != 1) throw new InvalidDataException("RemoveDomainContext: Invalid parameters "+Arrays.toString(params));
+
+ DomainPath pathToDelete = new DomainPath(params[0]);
+ if (!pathToDelete.exists())
+ throw new ObjectNotFoundException("Context "+pathToDelete+" does not exist");
+
+ try {
+ pathToDelete.getItemPath();
+ throw new InvalidDataException("Path "+pathToDelete+" is an Entity. Use its own Erase step instead, or RemoveAgent.");
+ } catch (ObjectNotFoundException ex) { }
+
+ if (Gateway.getLookup().getChildren(pathToDelete).hasNext())
+ throw new ObjectCannotBeUpdated("Context "+pathToDelete+" is not empty. Cannot delete.");
+
+ Gateway.getLookupManager().delete(pathToDelete);
+ return requestData;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveRole.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveRole.java new file mode 100644 index 0000000..6136cac --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/RemoveRole.java @@ -0,0 +1,68 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.lifecycle.instance.predefined.server;
+
+import java.util.Arrays;
+
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.lookup.LookupManager;
+import org.cristalise.kernel.lookup.RolePath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class RemoveRole extends PredefinedStep
+{
+ public RemoveRole()
+ {
+ super();
+ }
+
+ //requestdata is xmlstring
+ @Override
+ protected String runActivityLogic(AgentPath agent, ItemPath item,
+ int transitionID, String requestData) throws InvalidDataException, CannotManageException, ObjectNotFoundException, ObjectCannotBeUpdated {
+
+ String[] params = getDataList(requestData);
+ if (Logger.doLog(3)) Logger.msg(3, "RemoveRole: called by "+agent+" on "+item+" with parameters "+Arrays.toString(params));
+ if (params.length != 1) throw new InvalidDataException("RemoveRole: Invalid parameters "+Arrays.toString(params));
+
+ LookupManager lookup = Gateway.getLookupManager();
+
+ RolePath thisRole; AgentPath[] agents;
+ thisRole = lookup.getRolePath(params[0]);
+ agents = Gateway.getLookup().getAgents(thisRole);
+
+ if (agents.length > 0)
+ throw new ObjectCannotBeUpdated("Cannot remove role. "+agents.length+" agents still hold it.");
+
+ lookup.delete(thisRole);
+
+ return requestData;
+
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/ServerPredefinedStepContainer.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/ServerPredefinedStepContainer.java new file mode 100644 index 0000000..0fdc34c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/predefined/server/ServerPredefinedStepContainer.java @@ -0,0 +1,62 @@ +/**
+ * 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.lifecycle.instance.predefined.server;
+
+import org.cristalise.kernel.graph.model.GraphPoint;
+import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStep;
+import org.cristalise.kernel.lifecycle.instance.predefined.PredefinedStepContainer;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2005/06/02 10:19:33 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+public class ServerPredefinedStepContainer extends PredefinedStepContainer {
+
+
+ @Override
+ public void createChildren()
+ {
+ super.createChildren();
+ serverPredInit("CreateNewItem", "Creates a new Item in this Server without description.", new CreateNewItem());
+ serverPredInit("CreateNewAgent", "Creates a new Agent in this Server without description.", new CreateNewAgent());
+ serverPredInit("CreateNewRole", "Creates a new Role in this Server.", new CreateNewRole());
+ serverPredInit("RemoveRole", "Removes a Role from this Server.", new RemoveRole());
+ serverPredInit("RemoveDomainContext", "Deletes an existing context in the domain tree, but only if empty", new RemoveDomainContext());
+ serverPredInit("AddDomainContext", "Creates an empty domain context in the tree", new AddDomainContext());
+ }
+
+ public void serverPredInit(String alias, String Description, PredefinedStep act)
+ {
+ act.setName(alias);
+ act.setType(alias);
+ act.getProperties().put("Description", Description);
+ act.getProperties().put("Agent Role", "Admin");
+ act.setCentrePoint(new GraphPoint());
+ act.setIsPredefined(true);
+ addChild(act, new GraphPoint(100, 75 * ++num));
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/State.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/State.java new file mode 100644 index 0000000..d78bb4e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/State.java @@ -0,0 +1,101 @@ +/**
+ * 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.lifecycle.instance.stateMachine;
+
+import java.util.HashMap;
+import java.util.Set;
+
+public class State {
+
+ int id;
+ String name;
+ boolean finished = false; // If true, this state deactivates the current activity and the lifecycle proceeds
+
+ HashMap<Integer, Transition> possibleTransitions;
+
+ public State() {
+ possibleTransitions = new HashMap<Integer, Transition>();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public String toString() {
+ return id+": "+name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public boolean isFinished() {
+ return finished;
+ }
+
+ public void setFinished(boolean finished) {
+ this.finished = finished;
+ }
+
+ public HashMap<Integer, Transition> getPossibleTransitions() {
+ return possibleTransitions;
+ }
+
+ protected void addPossibleTransition(Transition possibleTransition) {
+ possibleTransitions.put(possibleTransition.getId(), possibleTransition);
+ }
+
+ public Set<Integer> getPossibleTransitionIds() {
+ return possibleTransitions.keySet();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + id;
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ State other = (State) obj;
+ if (id != other.id)
+ return false;
+ return true;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/StateMachine.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/StateMachine.java new file mode 100644 index 0000000..975dee1 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/StateMachine.java @@ -0,0 +1,178 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.lifecycle.instance.stateMachine;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.cristalise.kernel.common.AccessRightsException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.InvalidTransitionException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.lifecycle.instance.Activity;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.utils.DescriptionObject;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class StateMachine implements DescriptionObject
+{
+ public String name;
+ public int version;
+
+ private ArrayList<State> states;
+ private ArrayList<Transition> transitions;
+ private final HashMap<Integer, State> stateCodes;
+ private final HashMap<Integer, Transition> transitionCodes;
+
+ State initialState;
+ int initialStateCode;
+ boolean isCoherent = false;
+
+ public StateMachine() {
+ states = new ArrayList<State>();
+ transitions = new ArrayList<Transition>();
+ stateCodes = new HashMap<Integer, State>();
+ transitionCodes = new HashMap<Integer, Transition>();
+ }
+
+ public void setStates(ArrayList<State> newStates) {
+ this.states = newStates;
+ validate();
+ }
+
+ public void setTransitions(ArrayList<Transition> newTransitions) {
+ this.transitions = newTransitions;
+ validate();
+ }
+
+ public void validate() {
+ stateCodes.clear();
+ transitionCodes.clear();
+ isCoherent = true;
+
+ for (State state : states) {
+ Logger.debug(6, "State "+state.id+": "+state.name);
+ stateCodes.put(state.getId(), state);
+ }
+
+ if (stateCodes.containsKey(initialStateCode))
+ initialState = stateCodes.get(initialStateCode);
+ else
+ isCoherent = false;
+
+ for (Transition trans : transitions) {
+ Logger.debug(6, "Transition "+trans.id+": "+trans.name);
+ transitionCodes.put(trans.getId(), trans);
+ isCoherent = isCoherent && trans.resolveStates(stateCodes);
+ }
+
+ }
+
+ public ArrayList<State> getStates() {
+ return states;
+ }
+
+ public ArrayList<Transition> getTransitions() {
+ return transitions;
+ }
+
+ public State getInitialState() {
+ return initialState;
+ }
+
+ public void setInitialState(State initialState) {
+ this.initialState = initialState;
+ initialStateCode = initialState.getId();
+ }
+
+ public int getInitialStateCode() {
+ return initialStateCode;
+ }
+
+ public void setInitialStateCode(int initialStateCode) {
+ this.initialStateCode = initialStateCode;
+ initialState = stateCodes.get(initialStateCode);
+ if (initialState == null) isCoherent = false;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public int getVersion() {
+ return version;
+ }
+
+ @Override
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ @Override
+ public void setVersion(int version) {
+ this.version = version;
+ }
+
+ public Transition getTransition(int transitionID) {
+ return transitionCodes.get(transitionID);
+ }
+
+ public State getState(int stateID) {
+ return stateCodes.get(stateID);
+ }
+
+ public Map<Transition, String> getPossibleTransitions(Activity act, AgentPath agent) throws ObjectNotFoundException, InvalidDataException {
+ HashMap<Transition, String> returnList = new HashMap<Transition, String>();
+ State currentState = getState(act.getState());
+ for (Integer transCode : currentState.getPossibleTransitionIds()) {
+ Transition possTrans = currentState.getPossibleTransitions().get(transCode);
+ try {
+ String role = possTrans.getPerformingRole(act, agent);
+ returnList.put(possTrans, role);
+ } catch (AccessRightsException ex) {
+ if (Logger.doLog(5))
+ Logger.msg(5, "Transition '"+possTrans+"' not possible for "+agent.getAgentName()+": "+ex.getMessage());
+ }
+ }
+ return returnList;
+ }
+
+ public State traverse(Activity act, Transition transition, AgentPath agent) throws InvalidTransitionException, AccessRightsException, ObjectNotFoundException, InvalidDataException {
+ State currentState = getState(act.getState());
+ if (transition.originState.equals(currentState)) {
+ transition.getPerformingRole(act, agent);
+ return transition.targetState;
+ }
+ else
+ throw new InvalidTransitionException("Transition '"+transition.getName()+"' not valid from state '"+currentState.getName());
+
+ }
+
+ public boolean isCoherent() {
+ return isCoherent;
+ }
+
+
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/Transition.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/Transition.java new file mode 100644 index 0000000..845b489 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/Transition.java @@ -0,0 +1,345 @@ +/**
+ * 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.lifecycle.instance.stateMachine;
+
+import java.util.HashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.cristalise.kernel.common.AccessRightsException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.lifecycle.instance.Activity;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.RolePath;
+import org.cristalise.kernel.persistency.outcome.Schema;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.CastorHashMap;
+import org.cristalise.kernel.utils.LocalObjectLoader;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class Transition {
+
+ int id;
+ String name;
+
+ int originStateId;
+ int targetStateId;
+ State originState;
+ State targetState;
+ String reservation;
+
+ String enabledProp; // Boolean property that permits this transition e.g. 'Skippable'
+
+ // activation properties
+ boolean requiresActive = true; // Whether the activity must be active for this transition to be available
+ boolean finishing; // whether the target state is a finishing state;
+
+ // permissions
+ String roleOverride;
+
+ TransitionOutcome outcome;
+ TransitionScript script;
+
+ public Transition() {
+ }
+
+
+ public Transition(int id, String name, int originStateId, int targetStateId) {
+ super();
+ this.id = id;
+ this.name = name;
+ this.originStateId = originStateId;
+ this.targetStateId = targetStateId;
+ }
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public State getOriginState() {
+ return originState;
+ }
+
+ public void setOriginState(State originState) {
+ this.originState = originState;
+ }
+
+ public State getTargetState() {
+ return targetState;
+ }
+
+ public void setTargetState(State targetState) {
+ this.targetState = targetState;
+ finishing = targetState.finished;
+ }
+
+ public String getEnabledProp() {
+ return enabledProp;
+ }
+
+ public void setEnabledProp(String enabledProp) {
+ this.enabledProp = enabledProp;
+ }
+
+ public boolean isRequiresActive() {
+ return requiresActive;
+ }
+
+ public boolean isFinishing() {
+ return finishing;
+ }
+
+ public void setRequiresActive(boolean requiresActive) {
+ this.requiresActive = requiresActive;
+ }
+
+ public String getRoleOverride() {
+ return roleOverride;
+ }
+
+ public void setRoleOverride(String roleOverride) {
+ this.roleOverride = roleOverride;
+ }
+
+ public TransitionOutcome getOutcome() {
+ return outcome;
+ }
+
+ public void setOutcome(TransitionOutcome outcome) {
+ this.outcome = outcome;
+ }
+
+ public TransitionScript getScript() {
+ return script;
+ }
+
+ public void setScript(TransitionScript script) {
+ this.script = script;
+ }
+
+ public String getReservation() {
+ return reservation;
+ }
+
+ public void setReservation(String reservation) {
+ this.reservation = reservation;
+ }
+
+ protected boolean resolveStates(HashMap<Integer, State> states) {
+ boolean allFound = true;
+ if (states.keySet().contains(originStateId)) {
+ originState = states.get(originStateId);
+ originState.addPossibleTransition(this);
+ }
+ else
+ allFound = false;
+ if (states.keySet().contains(targetStateId))
+ targetState = states.get(targetStateId);
+ else
+ allFound = false;
+ return allFound;
+ }
+
+ public int getOriginStateId() {
+ return originStateId;
+ }
+
+ public void setOriginStateId(int originStateId) {
+ this.originStateId = originStateId;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public int getTargetStateId() {
+ return targetStateId;
+ }
+
+ public void setTargetStateId(int targetStateId) {
+ this.targetStateId = targetStateId;
+ }
+
+ public String getPerformingRole(Activity act, AgentPath agent) throws ObjectNotFoundException, AccessRightsException {
+
+ // check available
+ if (!isEnabled(act.getProperties()))
+ throw new AccessRightsException("Transition '"+name+"' is disabled by the '"+enabledProp+"' property.");
+
+ // check active
+ if (isRequiresActive() && !act.getActive())
+ throw new AccessRightsException("Activity must be active to perform this transition");
+
+ RolePath role = null;
+ String overridingRole = resolveValue(roleOverride, act.getProperties());
+ boolean override = overridingRole != null;
+ boolean isOwner = false, isOwned = true;
+
+ // Check agent name
+ String agentName = act.getCurrentAgentName();
+ if (agentName != null && agentName.length() >0) {
+ if (agent.getAgentName().equals(agentName))
+ isOwner = true;
+ }
+ else isOwned = false;
+
+ // determine transition role
+ if (override) {
+ role = Gateway.getLookup().getRolePath(overridingRole);
+ }
+ else {
+ String actRole = act.getCurrentAgentRole();
+ if (actRole != null && actRole.length() > 0)
+ role = Gateway.getLookup().getRolePath(actRole);
+ }
+
+ // Decide the access
+ if (isOwned && !override && !isOwner)
+ throw new AccessRightsException("Agent '"+agent.getAgentName()
+ +"' cannot perform this transition because the activity '"+act.getName()+"' is currently owned by "+agentName);
+
+ if (role != null) {
+ if (agent.hasRole(role))
+ return role.getName();
+ else if (agent.hasRole("Admin"))
+ return "Admin";
+ else
+ throw new AccessRightsException("Agent '"+agent.getAgentName()
+ +"' does not hold a suitable role '"+role.getName()+"' for the activity "+act.getName());
+ }
+ else
+ return null;
+ }
+
+ public String getReservation(Activity act, AgentPath agent) {
+ if (reservation == null || reservation.length() == 0)
+ reservation = targetState.finished?"clear":"set";
+
+ String reservedAgent = act.getCurrentAgentName();
+ if (reservation.equals("set"))
+ reservedAgent = agent.getAgentName();
+ else if (reservation.equals("clear"))
+ reservedAgent = "";
+ return reservedAgent;
+
+ }
+
+ private static String resolveValue(String key, CastorHashMap props) {
+ if (key==null) return null;
+ String result = key;
+ Pattern propField = Pattern.compile("\\$\\{(.+?)\\}");
+ Matcher propMatcher = propField.matcher(result);
+ while (propMatcher.find()) {
+ String propName = propMatcher.group(1);
+ Object propValue = props.get(propName);
+ Logger.msg(8, "Replacing Property "+propName+" as "+propValue);
+ String propValString = propValue==null?"":propValue.toString();
+ result = result.replace("${"+propName+"}", propValString);
+ }
+ return result;
+ }
+
+ public boolean isEnabled(CastorHashMap props) {
+ if (enabledProp == null)
+ return true;
+ return (Boolean)props.get(enabledProp);
+ }
+
+ public boolean hasOutcome(CastorHashMap actProps) {
+ if (outcome == null || actProps == null) return false;
+ String outcomeName = resolveValue(outcome.schemaName, actProps);
+ if (outcomeName == null || outcomeName.length() == 0)
+ return false;
+ String outcomeVersion = resolveValue(outcome.schemaVersion, actProps);
+ if (outcomeVersion == null || outcomeVersion.length() == 0)
+ return false;
+ return true;
+ }
+
+ public Schema getSchema(CastorHashMap actProps) throws InvalidDataException, ObjectNotFoundException {
+ if (hasOutcome(actProps))
+ try {
+ return LocalObjectLoader.getSchema(resolveValue(outcome.schemaName, actProps),
+ Integer.parseInt(resolveValue(outcome.schemaVersion, actProps)));
+ } catch (NumberFormatException ex) {
+ throw new InvalidDataException("Bad schema version number: "+outcome.schemaVersion+" ("+resolveValue(outcome.schemaVersion, actProps)+")");
+ }
+ else
+ return null;
+ }
+
+ public String getScriptName(CastorHashMap actProps) {
+ return resolveValue(script.scriptName, actProps);
+ }
+
+ public int getScriptVersion(CastorHashMap actProps) throws InvalidDataException {
+ try {
+ return Integer.parseInt(resolveValue(script.scriptVersion, actProps));
+ } catch (NumberFormatException ex) {
+ throw new InvalidDataException("Bad Script version number: "+script.scriptVersion+" ("+resolveValue(script.scriptVersion, actProps)+")");
+ }
+ }
+
+ public boolean hasScript(CastorHashMap actProps) {
+ if (script == null || actProps == null) return false;
+ String scriptName = getScriptName(actProps);
+ if (scriptName == null || scriptName.length() == 0)
+ return false;
+ String scriptVersion = resolveValue(script.scriptVersion, actProps);
+ if (scriptVersion == null || scriptVersion.length() == 0)
+ return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + id;
+ return result;
+ }
+
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Transition other = (Transition) obj;
+ if (id != other.id)
+ return false;
+ return true;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionOutcome.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionOutcome.java new file mode 100644 index 0000000..7575359 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionOutcome.java @@ -0,0 +1,57 @@ +/**
+ * 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.lifecycle.instance.stateMachine;
+
+
+public class TransitionOutcome extends TransitionResource {
+
+ // schema properties
+ String schemaName, schemaVersion; // Name & version of the schema of the data required for this transition.
+ boolean required = true; // If true, then the data must be supplied to perform the transition, otherwise it is optional
+
+ public TransitionOutcome() {
+ }
+
+ public String getSchemaName() {
+ return schemaName;
+ }
+
+ public void setSchemaName(String schemaName) {
+ this.schemaName = schemaName;
+ }
+
+ public String getSchemaVersion() {
+ return schemaVersion;
+ }
+
+ public void setSchemaVersion(String schemaVersion) {
+ this.schemaVersion = schemaVersion;
+ }
+
+ public boolean isRequired() {
+ return required;
+ }
+
+ public void setRequired(boolean required) {
+ this.required = required;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionResource.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionResource.java new file mode 100644 index 0000000..e220447 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionResource.java @@ -0,0 +1,29 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.lifecycle.instance.stateMachine;
+
+public class TransitionResource {
+
+ public TransitionResource() {
+ // TODO Auto-generated constructor stub
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionScript.java b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionScript.java new file mode 100644 index 0000000..a41ec2c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/instance/stateMachine/TransitionScript.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.lifecycle.instance.stateMachine;
+
+
+public class TransitionScript extends TransitionResource {
+
+ // script properties
+ String scriptName, scriptVersion; // Name & version of the script to be run by the agent during this transition
+
+ public TransitionScript() {
+ }
+
+ public String getScriptName() {
+ return scriptName;
+ }
+
+ public void setScriptName(String scriptName) {
+ this.scriptName = scriptName;
+ }
+
+ public String getScriptVersion() {
+ return scriptVersion;
+ }
+
+ public void setScriptVersion(String scriptVersion) {
+ this.scriptVersion = scriptVersion;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lifecycle/package-info.java b/src/main/java/org/cristalise/kernel/lifecycle/package-info.java new file mode 100644 index 0000000..af6300b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/package-info.java @@ -0,0 +1,30 @@ +/**
+ * 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 the Item lifecycle, as composite workflows.
+ *
+ * <p>This package contains the activity description implementations. The
+ * workflow instance is in the {@link org.cristalise.kernel.lifecycle.instance}
+ * subpackage, which also contains the predefined steps.
+ *
+ */
+
+package org.cristalise.kernel.lifecycle;
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/lifecycle/routingHelpers/ViewpointDataHelper.java b/src/main/java/org/cristalise/kernel/lifecycle/routingHelpers/ViewpointDataHelper.java new file mode 100644 index 0000000..49bebf4 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lifecycle/routingHelpers/ViewpointDataHelper.java @@ -0,0 +1,86 @@ +/**
+ * 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.lifecycle.routingHelpers;
+
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.entity.proxy.ItemProxy;
+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.utils.XmlElementParser;
+
+
+public class ViewpointDataHelper
+{
+ static Object[] errArr = { "" };
+ /**
+ * Method get.
+ * @param value
+ * @return String[]
+ * @throws Exception
+ */
+ /**@param value : /UUID (or . if current) /SchemaName/Viewname/Path:XPathInOutcome */
+ public static Object [] get(String value) throws Exception
+ {
+ //Syntax of search : <EntityPath>/<ViewpointPath>:<XPathinOutcome>
+ String entityPath;
+ String viewpoint;
+ String xpath;
+ Object[] retArr;
+
+ // find syskey, viewname, xpath
+ int firstSlash = value.indexOf("/");
+ if (firstSlash > 0) {
+ entityPath = value.substring(0, firstSlash);
+ int startXPath = value.indexOf(":");
+ if (startXPath==-1) {
+ viewpoint = value.substring(firstSlash + 1);
+ xpath = null;
+ } else {
+ viewpoint = value.substring(firstSlash + 1, startXPath);
+ xpath = value.substring(startXPath+1);
+ }
+ }
+ else return errArr;
+
+ // find entity
+ ItemPath sourcePath = new ItemPath(entityPath);
+
+ try {
+ // load viewpoint
+ ItemProxy dataSource = Gateway.getProxyManager().getProxy(sourcePath);
+ Viewpoint view = (Viewpoint)dataSource.getObject(ClusterStorage.VIEWPOINT + "/" + viewpoint);
+ Outcome outcome = view.getOutcome();
+ if (xpath == null) {
+ retArr = new Object[1];
+ retArr[0] = outcome;
+ }
+ else
+ retArr = XmlElementParser.parse(outcome.getData(), xpath);
+ return retArr;
+
+ } catch (ObjectNotFoundException e) {
+ return errArr;
+ }
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/lookup/AgentPath.java b/src/main/java/org/cristalise/kernel/lookup/AgentPath.java new file mode 100644 index 0000000..cab9068 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/AgentPath.java @@ -0,0 +1,159 @@ +/**
+ * 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.lookup;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.UUID;
+
+import org.apache.xerces.impl.dv.util.Base64;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.SystemKey;
+import org.cristalise.kernel.process.Gateway;
+
+
+
+/**
+* Extends Path to enforce SystemKey structure and support int form
+*
+* @version $Revision: 1.12 $ $Date: 2005/10/13 08:15:00 $
+* @author $Author: abranson $
+**/
+public class AgentPath extends ItemPath
+{
+
+ private String mAgentName=null;
+ private String mPassword=null;
+
+ public AgentPath(SystemKey syskey) throws InvalidAgentPathException, InvalidItemPathException {
+ super(syskey);
+ try {
+ findAgentName();
+ } catch (ObjectNotFoundException e) {
+ throw new InvalidAgentPathException();
+ }
+ }
+ protected AgentPath(UUID uuid) throws InvalidAgentPathException, InvalidItemPathException {
+ super(uuid);
+ try {
+ findAgentName();
+ } catch (ObjectNotFoundException e) {
+ throw new InvalidAgentPathException();
+ }
+ }
+
+ public AgentPath(ItemPath itemPath) throws InvalidAgentPathException {
+ super(itemPath.mUUID);
+ try {
+ findAgentName();
+ } catch (ObjectNotFoundException e) {
+ throw new InvalidAgentPathException();
+ }
+ }
+
+ public AgentPath(ItemPath itemPath, String agentName) {
+ super(itemPath.mUUID);
+ mAgentName = agentName;
+ }
+
+ public AgentPath(String path) throws InvalidItemPathException {
+ super(path);
+ try {
+ findAgentName();
+ } catch (ObjectNotFoundException e) {
+ throw new InvalidAgentPathException();
+ }
+ }
+
+ public void setAgentName(String agentID)
+ {
+ mAgentName = agentID;
+ }
+
+ public String getAgentName()
+ {
+ if (mAgentName==null)
+ try {
+ findAgentName();
+ } catch (ObjectNotFoundException e) {
+ return null;
+ }
+ return mAgentName;
+ }
+
+ private void findAgentName() throws ObjectNotFoundException {
+ mAgentName = Gateway.getLookup().getAgentName(this);
+ }
+
+ public RolePath[] getRoles()
+ {
+ return Gateway.getLookup().getRoles(this);
+ }
+
+ public boolean hasRole(RolePath role) {
+ return Gateway.getLookup().hasRole(this, role);
+ }
+
+ public boolean hasRole(String role) {
+ try {
+ return hasRole(Gateway.getLookup().getRolePath(role));
+ } catch (ObjectNotFoundException ex) {
+ return false;
+ }
+ }
+
+ public void setPassword(String passwd)
+ {
+ mPassword = passwd;
+ }
+
+ public String getPassword()
+ {
+ return mPassword;
+ }
+
+ @Override
+ public String dump() {
+ return super.dump()+
+ "\n agentID="+
+ mAgentName;
+ }
+
+ public static String generateUserPassword(String pass, String algo) throws NoSuchAlgorithmException {
+ MessageDigest sha = MessageDigest.getInstance(algo);
+ sha.reset();
+ sha.update(pass.getBytes());
+ byte hash[] = sha.digest();
+ StringBuffer digest = new StringBuffer("{").append(algo).append("}");
+ digest.append(Base64.encode(hash));
+ return digest.toString();
+ }
+
+ public static AgentPath fromUUIDString(String uuid) throws InvalidAgentPathException {
+ try {
+ return new AgentPath(new ItemPath(uuid));
+ } catch (InvalidItemPathException ex) {
+ throw new InvalidAgentPathException(ex.getMessage());
+ }
+ }
+
+}
+
diff --git a/src/main/java/org/cristalise/kernel/lookup/DomainPath.java b/src/main/java/org/cristalise/kernel/lookup/DomainPath.java new file mode 100644 index 0000000..a054da6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/DomainPath.java @@ -0,0 +1,136 @@ +/**
+ * 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.lookup;
+
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.process.Gateway;
+
+
+
+/**
+* @version $Revision: 1.22 $ $Date: 2005/10/13 08:15:00 $
+* @author $Author: abranson $
+**/
+public class DomainPath extends Path
+{
+ private ItemPath target = null;
+ protected static String mTypeRoot;
+
+/* Very simple extension to Path. Only copies constructors and defines root */
+
+ public DomainPath()
+ {
+ super(Path.UNKNOWN);
+ }
+
+ public DomainPath(short type)
+ {
+ super();
+ mType = type;
+ }
+
+ public DomainPath(String[] path)
+ {
+ super(path, Path.UNKNOWN);
+ }
+
+ public DomainPath(String path)
+ {
+ super(path, Path.UNKNOWN);
+ }
+
+ public DomainPath(String path, ItemPath entity)
+ {
+ super(path, Path.UNKNOWN);
+ setItemPath(entity);
+ }
+
+ public DomainPath(DomainPath parent, String child) {
+ super(parent, child);
+ }
+
+ /* the root of domain paths is /domain
+ * clearly
+ */
+ @Override
+ public String getRoot() {
+ return "domain";
+ }
+
+ public DomainPath getParent() {
+ if (mPath.length == 0)
+ return null;
+
+ String[] parentPath = new String[mPath.length-1];
+ System.arraycopy(mPath, 0, parentPath, 0, parentPath.length);
+ return new DomainPath(parentPath);
+ }
+
+ public void setItemPath(ItemPath newTarget) {
+ if (newTarget == null) { // clear
+ target = null;
+ mType = Path.CONTEXT;
+ return;
+ }
+
+ target = newTarget;
+ mType = Path.ENTITY;
+ }
+
+ @Override
+ public ItemPath getItemPath() throws ObjectNotFoundException {
+ if (mType == UNKNOWN) { // must decide
+ checkType();
+ }
+
+ if (target == null)
+ throw new ObjectNotFoundException("Path "+toString()+" does not resolve to an Item");
+ return target;
+ }
+
+ @Override
+ public short getType() {
+ if (mType == UNKNOWN) { // must decide
+ checkType();
+ }
+ return mType;
+ }
+
+ protected void checkType() {
+ try {
+ setItemPath(Gateway.getLookup().resolvePath(this));
+ } catch (InvalidItemPathException ex) {
+ mType = CONTEXT;
+ } catch (ObjectNotFoundException ex) {
+ mType = CONTEXT;
+ }
+
+ }
+
+ /**
+ * Retrieves the domkey of the path
+ * @return the last path component;
+ */
+ public String getName() {
+ return mPath[mPath.length-1];
+ }
+}
+
diff --git a/src/main/java/org/cristalise/kernel/lookup/InvalidAgentPathException.java b/src/main/java/org/cristalise/kernel/lookup/InvalidAgentPathException.java new file mode 100644 index 0000000..60ac840 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/InvalidAgentPathException.java @@ -0,0 +1,33 @@ +/**
+ * 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.lookup;
+
+public class InvalidAgentPathException extends InvalidItemPathException {
+
+ public InvalidAgentPathException() {
+ super();
+ }
+
+ public InvalidAgentPathException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lookup/InvalidItemPathException.java b/src/main/java/org/cristalise/kernel/lookup/InvalidItemPathException.java new file mode 100644 index 0000000..b6817af --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/InvalidItemPathException.java @@ -0,0 +1,33 @@ +/**
+ * 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.lookup;
+
+public class InvalidItemPathException extends InvalidPathException {
+
+ public InvalidItemPathException() {
+ super();
+ }
+
+ public InvalidItemPathException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lookup/InvalidPathException.java b/src/main/java/org/cristalise/kernel/lookup/InvalidPathException.java new file mode 100644 index 0000000..9e75c11 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/InvalidPathException.java @@ -0,0 +1,33 @@ +/**
+ * 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.lookup;
+
+public class InvalidPathException extends Exception {
+
+ public InvalidPathException() {
+ super();
+ }
+
+ public InvalidPathException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lookup/ItemPath.java b/src/main/java/org/cristalise/kernel/lookup/ItemPath.java new file mode 100644 index 0000000..9df4a0a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/ItemPath.java @@ -0,0 +1,120 @@ +/**
+ * 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.lookup;
+
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.UUID;
+
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.SystemKey;
+
+
+
+/**
+* Extends Path to enforce SystemKey structure and support int form
+*
+* @version $Revision: 1.14 $ $Date: 2006/03/03 13:52:21 $
+* @author $Author: abranson $
+**/
+public class ItemPath extends Path
+{
+
+ public ItemPath() {
+ setSysKey(UUID.randomUUID());
+ }
+
+ protected ItemPath(UUID uuid) {
+ setSysKey(uuid);
+ }
+
+ public ItemPath(SystemKey syskey) {
+ setSysKey(syskey);
+ }
+
+ /*
+ */
+ public ItemPath(String[] path) throws InvalidItemPathException
+ {
+ super(path, Path.CONTEXT);
+ getSysKeyFromPath();
+ }
+
+ /*
+ */
+ public ItemPath(String path) throws InvalidItemPathException
+ {
+ super(path, Path.CONTEXT);
+ if (path == null) throw new InvalidItemPathException("Path cannot be null");
+ getSysKeyFromPath();
+ }
+
+ private void getSysKeyFromPath() throws InvalidItemPathException {
+ if (mPath.length == 1) {
+ try {
+ setSysKey(UUID.fromString(mPath[0]));
+ mType = Path.ENTITY;
+ } catch (IllegalArgumentException ex) {
+ throw new InvalidItemPathException(mPath[0]+" is not a valid UUID");
+ }
+ }
+ else
+ throw new InvalidItemPathException("Not a valid item path: "+Arrays.toString(mPath));
+ }
+
+ // EntityPaths root in /entity
+ @Override
+ public String getRoot() {
+ return "entity";
+ }
+
+ @Override
+ public ItemPath getItemPath() throws ObjectNotFoundException {
+ return this;
+ }
+
+ public byte[] getOID() {
+ if (mType == Path.CONTEXT) return null;
+ ByteBuffer bb = ByteBuffer.wrap(new byte[16]);
+ bb.putLong(mSysKey.msb);
+ bb.putLong(mSysKey.lsb);
+ return bb.array();
+ }
+
+ protected void setSysKey(UUID uuid) {
+ mUUID = uuid;
+ mSysKey = new SystemKey(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits());
+ setPathFromUUID(mUUID.toString());
+ }
+
+ protected void setSysKey(SystemKey sysKey) {
+ mSysKey = sysKey;
+ mUUID = new UUID(sysKey.msb, sysKey.lsb);
+ setPathFromUUID(mUUID.toString());
+ }
+
+ private void setPathFromUUID(String uuid) {
+ mPath = new String[1];
+ mPath[0] = uuid;
+ mType = Path.ENTITY;
+ }
+}
+
diff --git a/src/main/java/org/cristalise/kernel/lookup/Lookup.java b/src/main/java/org/cristalise/kernel/lookup/Lookup.java new file mode 100644 index 0000000..eb54775 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/Lookup.java @@ -0,0 +1,175 @@ +/**
+ * 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.lookup;
+
+import java.util.Iterator;
+
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.process.auth.Authenticator;
+import org.cristalise.kernel.property.Property;
+import org.cristalise.kernel.property.PropertyDescriptionList;
+
+
+/**
+ * @author abranson
+ *
+ */
+public interface Lookup {
+
+ /**
+ * Connect to the directory using the credentials supplied in the Authenticator.
+ *
+ * @param user The connected Authenticator. The Lookup implementation may use the AuthObject in this to communicate with the database.
+ */
+ public void open(Authenticator user);
+
+ /**
+ * Shutdown the lookup
+ */
+ public void close();
+
+ // Path resolution
+ /**
+ * Fetch the correct subclass class of ItemPath for a particular Item, derived from its lookup entry.
+ * This is used by the CORBA Server to make sure the correct Item subclass is used.
+ *
+ * @param sysKey The system key of the Item
+ * @return an ItemPath or AgentPath
+ * @throws InvalidItemPathException When the system key is invalid/out-of-range
+ * @throws ObjectNotFoundException When the Item does not exist in the directory.
+ */
+ public ItemPath getItemPath(String sysKey) throws InvalidItemPathException, ObjectNotFoundException;
+
+ /**
+ * Find the ItemPath for which a DomainPath is an alias.
+ *
+ * @param domainPath The path to resolve
+ * @return The ItemPath it points to (should be an AgentPath if the path references an Agent)
+ * @throws InvalidItemPathException
+ * @throws ObjectNotFoundException
+ */
+ public ItemPath resolvePath(DomainPath domainPath) throws InvalidItemPathException, ObjectNotFoundException;
+
+ /**
+ * Resolve a path to a CORBA Object Item or Agent
+ *
+ * @param path The path to be resolved
+ * @return The CORBA Object
+ * @throws ObjectNotFoundException When the Path doesn't exist, or doesn't have an IOR associated with it
+ */
+ public org.omg.CORBA.Object resolve(Path path) throws ObjectNotFoundException;
+
+ // Path finding and searching
+
+ /**
+ * Checks if a particular Path exists in the directory
+ * @param path The path to check
+ * @return boolean true if the path exists, false if it doesn't
+ */
+ public boolean exists(Path path);
+
+ /**
+ * List the next-level-deep children of a Path
+ *
+ * @param path The parent Path
+ * @return An Iterator of child Paths
+ */
+ public Iterator<Path> getChildren(Path path);
+
+ /**
+ * Find a path with a particular name (last component)
+ *
+ * @param start Search root
+ * @param name The name to search for
+ * @return An Iterator of matching Paths. Should be an empty Iterator if there are no matches.
+ */
+ public Iterator<Path> search(Path start, String name);
+
+ /**
+ * Search for Items in the specified path with the given property name and value
+ * @param start Search root
+ * @param propname Property name
+ * @param propvalue The property value to search for
+ * @return An Iterator of matching Paths
+ */
+ public Iterator<Path> search(Path start, Property... props);
+
+ /**
+ * Search for Items of a particular type, based on its PropertyDescription outcome
+ * @param start Search root
+ * @param props Properties unmarshalled from an ItemDescription's property description outcome.
+ * @return An Iterator of matching Paths
+ */
+ public Iterator<Path> search(Path start, PropertyDescriptionList props);
+
+ /**
+ * Find all DomainPaths that are aliases for a particular Item or Agent
+ * @param itemPath The ItemPath
+ * @return An Iterator of DomainPaths that are aliases for that Item
+ */
+ public Iterator<Path> searchAliases(ItemPath itemPath);
+
+ // Role and agent management
+
+ /**
+ * @param agentName
+ * @return
+ * @throws ObjectNotFoundException
+ */
+ public AgentPath getAgentPath(String agentName) throws ObjectNotFoundException;
+
+ /**
+ * @param roleName
+ * @return
+ * @throws ObjectNotFoundException
+ */
+ public RolePath getRolePath(String roleName) throws ObjectNotFoundException;
+
+ /**
+ * @param rolePath
+ * @return
+ * @throws ObjectNotFoundException
+ */
+ public AgentPath[] getAgents(RolePath rolePath) throws ObjectNotFoundException;
+
+ /**
+ * @param agentPath
+ * @return
+ */
+ public RolePath[] getRoles(AgentPath agentPath);
+
+ /**
+ * Returns all of the Agents in this centre who hold this role (including sub-roles)
+ *
+ * @param agentPath
+ * @param role
+ * @return
+ */
+ public boolean hasRole(AgentPath agentPath, RolePath role);
+
+ /**
+ * @param agentPath
+ * @return
+ * @throws ObjectNotFoundException
+ */
+ public String getAgentName(AgentPath agentPath) throws ObjectNotFoundException;
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lookup/LookupManager.java b/src/main/java/org/cristalise/kernel/lookup/LookupManager.java new file mode 100644 index 0000000..0ce04c3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/LookupManager.java @@ -0,0 +1,124 @@ +/**
+ * 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.lookup;
+
+import java.security.NoSuchAlgorithmException;
+
+import org.cristalise.kernel.common.ObjectAlreadyExistsException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+
+
+/**
+ * The LookupManager interface contains all of the directory modifying methods
+ * of the Lookup. This allows read-only Lookup implementations. Server processes
+ * will attempt to cast their Lookups into LookupManagers, and fail to start up
+ * if this is not possible.
+ *
+ */
+public interface LookupManager extends Lookup {
+
+ /**
+ * Called when a server starts up. The Lookup implementation should ensure
+ * that the initial structure of its directory is valid, and create it on
+ * first boot.
+ *
+ * @throws ObjectNotFoundException When initialization data is not found
+ */
+ public void initializeDirectory() throws ObjectNotFoundException;
+
+ // Path management
+
+ /**
+ * Register a new a Path in the directory.
+ *
+ * @param newPath The path to add
+ * @throws ObjectCannotBeUpdated When there is an error writing to the
+ * directory
+ * @throws ObjectAlreadyExistsException When the Path has already been registered
+ */
+ public void add(Path newPath) throws ObjectCannotBeUpdated, ObjectAlreadyExistsException;
+
+ /**
+ * Remove a Path from the directory.
+ *
+ * @param path The path to remove
+ * @throws ObjectCannotBeUpdated When an error occurs writing to the directory
+ */
+ public void delete(Path path) throws ObjectCannotBeUpdated;
+
+ // Role and agent management
+
+ /**
+ * Creates a new Role. Called by the server predefined step 'CreateNewRole'
+ *
+ * @param role The new role path
+ * @return
+ * @throws ObjectAlreadyExistsException
+ * @throws ObjectCannotBeUpdated
+ */
+ public RolePath createRole(RolePath role) throws ObjectAlreadyExistsException, ObjectCannotBeUpdated;
+
+ /**
+ * Adds the given Agent to the given Role, if they both exist.
+ *
+ * @param agent
+ * @param rolePath
+ * @throws ObjectCannotBeUpdated
+ * @throws ObjectNotFoundException
+ */
+ public void addRole(AgentPath agent, RolePath rolePath) throws ObjectCannotBeUpdated, ObjectNotFoundException;
+
+ /**
+ * Remove the given Agent from the given Role. Does not delete the Role.
+ *
+ * @param agent
+ * @param role
+ * @throws ObjectCannotBeUpdated
+ * @throws ObjectNotFoundException
+ */
+ public void removeRole(AgentPath agent, RolePath role) throws ObjectCannotBeUpdated, ObjectNotFoundException;
+
+ /**
+ * Set an Agent's password
+ *
+ * @param agent The Agent
+ * @param newPassword The Agent's new password
+ * @throws ObjectNotFoundException
+ * @throws ObjectCannotBeUpdated
+ * @throws NoSuchAlgorithmException
+ */
+ public void setAgentPassword(AgentPath agent, String newPassword) throws ObjectNotFoundException, ObjectCannotBeUpdated, NoSuchAlgorithmException;
+
+ /**
+ * Set the flag specifying whether Activities holding this Role should push
+ * Jobs its Agents.
+ *
+ * @param role The role to modify
+ * @param hasJobList boolean flag
+ *
+ * @throws ObjectNotFoundException When the Role doesn't exist
+ * @throws ObjectCannotBeUpdated
+ */
+ public void setHasJobList(RolePath role, boolean hasJobList) throws ObjectNotFoundException, ObjectCannotBeUpdated;
+
+
+}
diff --git a/src/main/java/org/cristalise/kernel/lookup/Path.java b/src/main/java/org/cristalise/kernel/lookup/Path.java new file mode 100644 index 0000000..77bca9b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/Path.java @@ -0,0 +1,243 @@ +/**
+ * 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.lookup;
+
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+import java.util.UUID;
+
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.SystemKey;
+import org.cristalise.kernel.process.Gateway;
+
+
+
+/**
+*
+**/
+public abstract class Path
+{
+ public static final String delim = "/";
+
+ // types
+ public static final short UNKNOWN = 0;
+ public static final short CONTEXT = 1;
+ public static final short ENTITY = 2;
+
+ protected String[] mPath = new String[0];
+
+ // slash delimited path
+ protected String mStringPath = null;
+ // entity or context
+ protected short mType = CONTEXT;
+
+ // item UUID (only valid for ItemPaths and DomainPaths that are aliases for Items)
+ protected UUID mUUID;
+ protected SystemKey mSysKey;
+
+ // ior is stored in here when it is resolved
+ protected org.omg.CORBA.Object mIOR = null;
+
+ public Path() {
+ }
+
+ /*
+ * Creates an empty path
+ */
+ public Path(short type)
+ {
+ mType = type;
+ }
+
+ /*
+ * Creates a path with an arraylist of the path (big endian)
+ */
+ public Path(String[] path, short type) {
+ setPath(path);
+ mType = type;
+ }
+
+ /*
+ * Creates a path from a slash separated string (big endian)
+ */
+ public Path(String path, short type) {
+ setPath(path);
+ mType = type;
+ }
+
+ /*
+ * Create a path by appending a child string to an existing path
+ */
+ public Path(Path parent, String child, short type) {
+ String[] oldPath = parent.getPath();
+ mPath = new String[oldPath.length+1];
+ for (int i=0; i<oldPath.length; i++)
+ mPath[i] = oldPath[i];
+ mPath[oldPath.length] = child;
+ mType = type;
+ }
+
+ /*
+ * Create a path by appending a child and inheriting the type
+ */
+ public Path(Path parent, String child) {
+ this(parent, child, UNKNOWN);
+ }
+ /*************************************************************************/
+
+ // Setters
+
+ /* string array path e.g. { "Product", "Crystal", "Barrel", "2L", "331013013348" }
+ * system/domain node ABSENT
+ */
+ public void setPath(String[] path)
+ {
+ mStringPath = null;
+ mPath = path.clone();
+ mUUID = null;
+ mSysKey = null;
+ }
+
+ /* string path e.g. /system/d000/d000/d001
+ * system/domain node PRESENT
+ */
+ public void setPath(String path)
+ {
+ ArrayList<String> newPath = new ArrayList<String>();
+ if (path != null) {
+ StringTokenizer tok = new StringTokenizer(path, delim);
+ if (tok.hasMoreTokens()) {
+ String first = tok.nextToken();
+ if (!first.equals(getRoot()))
+ newPath.add(first);
+ while (tok.hasMoreTokens())
+ newPath.add(tok.nextToken());
+ }
+ }
+
+ mPath = (newPath.toArray(mPath));
+ mStringPath = null;
+ mUUID = null;
+ mSysKey = null;
+ }
+
+ // lookup sets the IOR
+ public void setIOR(org.omg.CORBA.Object IOR) {
+ mIOR = IOR;
+ if (IOR == null) mType = Path.CONTEXT;
+ else mType = Path.ENTITY;
+ }
+
+ /* clone another path object
+ */
+ public void setPath(Path path)
+ {
+ mStringPath = null;
+ mPath = (path.getPath().clone());
+ mUUID = null;
+ mSysKey = null;
+ }
+
+ /*************************************************************************/
+
+
+ /*
+ * Getter Methods
+ */
+
+ // root is defined as 'domain', 'entity' or 'system' in subclasses
+ public abstract String getRoot();
+
+ public String[] getPath()
+ {
+ return mPath;
+ }
+
+ public String getString()
+ {
+ if (mStringPath == null) {
+ StringBuffer stringPathBuffer = new StringBuffer("/").append(getRoot());
+ for (String element : mPath)
+ stringPathBuffer.append(delim).append(element);
+ mStringPath = stringPathBuffer.toString();
+ }
+ return mStringPath;
+ }
+
+ public boolean exists() {
+ return Gateway.getLookup().exists(this);
+ }
+
+ /** Queries the lookup for the IOR
+ */
+
+ public org.omg.CORBA.Object getIOR() {
+ org.omg.CORBA.Object newIOR = null;
+ if (mIOR==null) { // if not cached try to resolve
+ Lookup myLookup = Gateway.getLookup();
+ try {
+ newIOR = myLookup.resolve(this);
+ } catch (ObjectNotFoundException ex) {
+ }
+ setIOR(newIOR);
+ }
+ return mIOR;
+ }
+
+ @Override
+ public String toString() {
+ return getString();
+ }
+
+ public short getType() {
+ return mType;
+ }
+
+ public SystemKey getSystemKey() {
+ return mSysKey;
+ }
+
+ public UUID getUUID() {
+ return mUUID;
+ }
+
+ public abstract ItemPath getItemPath() throws ObjectNotFoundException;
+
+ @Override
+ public boolean equals( Object path )
+ {
+ if (path == null) return false;
+ return toString().equals(path.toString());
+ }
+
+ @Override
+ public int hashCode() {
+ return toString().hashCode();
+ }
+
+ public String dump() {
+ StringBuffer comp = new StringBuffer("Components: { ");
+ for (String element : mPath)
+ comp.append("'").append(element).append("' ");
+ return "Path - dump(): "+comp.toString()+"}\n string="+toString()+"\n uuid="+getUUID()+"\n type="+mType;
+ }
+}
+
diff --git a/src/main/java/org/cristalise/kernel/lookup/RolePath.java b/src/main/java/org/cristalise/kernel/lookup/RolePath.java new file mode 100644 index 0000000..61f444c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/lookup/RolePath.java @@ -0,0 +1,116 @@ +/**
+ * 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.lookup;
+
+import java.util.Iterator;
+
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.process.Gateway;
+
+
+
+
+/**
+* @version $Revision: 1.7 $ $Date: 2005/04/26 06:48:12 $
+* @author $Author: abranson $
+**/
+public class RolePath extends DomainPath
+{
+ /**
+ *
+ */
+
+ private boolean hasJobList = false;
+
+ public RolePath() {
+ super("agent");
+ }
+
+ @Override
+ public RolePath getParent() {
+ try {
+ if (mPath.length > 2)
+ return Gateway.getLookup().getRolePath(mPath[mPath.length-2]);
+ } catch (ObjectNotFoundException ex) { }
+ return null;
+ }
+
+ public RolePath(RolePath parent, String roleName) {
+ super(parent, roleName);
+ }
+
+ public RolePath(String[] path, boolean jobList) {
+ super(path);
+ hasJobList = jobList;
+ }
+
+ public RolePath(RolePath parent, String roleName, boolean jobList) {
+ this(parent, roleName);
+ hasJobList = jobList;
+ }
+
+ /**
+ * @return Returns the hasJobList.
+ */
+ public boolean hasJobList() {
+ return hasJobList;
+ }
+ /**
+ * @param hasJobList The hasJobList to set.
+ * @throws ObjectCannotBeUpdated
+ * @throws ObjectNotFoundException
+ * @throws CannotManageException
+ */
+ public void setHasJobList(boolean hasJobList) throws ObjectNotFoundException, ObjectCannotBeUpdated, CannotManageException {
+ this.hasJobList = hasJobList;
+ }
+
+
+ @Override
+ protected void checkType() {
+ mType = CONTEXT;
+ }
+
+ public Iterator<Path> getChildren() {
+ return Gateway.getLookup().getChildren(this);
+ }
+
+ @Override
+ public String dump() {
+ StringBuffer comp = new StringBuffer("Components: { ");
+ for (String element : mPath)
+ comp.append("'").append(element).append("' ");
+
+ return "Path - dump(): "+
+ comp.toString()+
+ "}\n string="+
+ toString()+
+ "\n type="+
+ mType+
+ "\n name="+
+ getName()+
+ "\n ";
+ }
+
+}
+
diff --git a/src/main/java/org/cristalise/kernel/persistency/ClusterStorage.java b/src/main/java/org/cristalise/kernel/persistency/ClusterStorage.java new file mode 100644 index 0000000..ca43e67 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/ClusterStorage.java @@ -0,0 +1,296 @@ +/**
+ * 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.persistency;
+
+import org.cristalise.kernel.collection.Collection;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.common.SystemKey;
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.outcome.Outcome;
+import org.cristalise.kernel.persistency.outcome.Viewpoint;
+import org.cristalise.kernel.process.auth.Authenticator;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**
+ * <p>Interface for persistency managers of entities. It allows different kernel
+ * objects to be stored in different backend. For instance, Properties may be
+ * stored in LDAP, while Events, Outcomes and Viewpoints could be stored in a
+ * relational database. The kernel does and needs no analytical querying of the
+ * ClusterStorages, only simple gets and puts. This may be implemented on top
+ * of the storage implementation separately.
+ *
+ * <p>Each item is indexed by its {@link ItemPath}, which is may be constructed from its
+ * UUID, equivalent {@link SystemKey} object, or
+ *
+ * <p>Each first-level path under the Item is defined as a Cluster. Different
+ * Clusters may be stored in different places. Each ClusterStorage must support
+ * {@link #get(ItemPath, String)} and
+ * {@link #getClusterContents(ItemPath, String)} for clusters they return
+ * {@link #READ} and {@link #READWRITE} from queryClusterSupport and
+ * {@link #put(ItemPath, C2KLocalObject)} and {@link #delete(ItemPath, String)}
+ * for clusters they return {@link #WRITE} and {@link #READWRITE} from
+ * {@link #getClusterContents(ItemPath, String)}. Operations that have not been
+ * declared as not supported should throw a PersistencyException. If a
+ * cluster does not exist, get should return null, and delete should return with
+ * no action.
+ */
+public abstract class ClusterStorage {
+
+ /**
+ * Constant to return from {@link #queryClusterSupport(String)} for Cluster
+ * types this storage does not support.
+ */
+ public static final short NONE = 0;
+ /**
+ * Constant to return from {@link #queryClusterSupport(String)} for Cluster
+ * types this storage can read from a database but not write. An example
+ * would be pre-existing data in a database that is mapped to Items in some
+ * way.
+ */
+ public static final short READ = 1;
+ /**
+ * Constant to return from {@link #queryClusterSupport(String)} for Cluster
+ * types this storage can write to a database but not read. An example would
+ * be a realtime database export of data, which is transformed in an
+ * unrecoverable way for use in other systems.
+ */
+ public static final short WRITE = 2;
+ /**
+ * Constant to return from {@link #queryClusterSupport(String)} for data
+ * stores that CRISTAL may use for both reading and writing for the given
+ * Cluster type.
+ */
+ public static final short READWRITE = 3;
+
+ // Cluster types
+ /**
+ * The defined path of the root of the CRISTAL Kernel object cluster tree. A
+ * zero-length string.
+ */
+ public static final String ROOT = "";
+ /**
+ * The root of the Property object cluster. All Property paths start with
+ * this. Defined as "Property". Properties are stored underneath according
+ * to their name e.g. "Property/Name"
+ */
+ public static final String PROPERTY = "Property";
+ /**
+ * The root of the Collection object cluster. All Collection paths start
+ * with this. Defined as "Collection". Collections are stored underneath by
+ * name e.g. "Collection/Composition"
+ */
+ public static final String COLLECTION = "Collection";
+ /**
+ * The cluster which holds the Item workflow. Defined as "LifeCycle". Holds
+ * the workflow inside, which is named "workflow", hence
+ * "LifeCycle/workflow".
+ *
+ * @see org.cristalise.kernel.lifecycle.instance.Workflow
+ */
+ public static final String LIFECYCLE = "LifeCycle";
+ /**
+ * This cluster holds all outcomes of this Item. The path to each outcome is
+ * "Outcome/<i>Schema Name</i>/<i>Schema Version</i>/<i>Event ID</i>"
+ */
+ public static final String OUTCOME = "Outcome";
+ /**
+ * This is the cluster that contains all event for this Item. This cluster
+ * may be instantiated in a client as a History, which is a RemoteMap.
+ * Events are stored with their ID: "/AuditTrail/<i>Event ID</i>"
+ */
+ public static final String HISTORY = "AuditTrail";
+ /**
+ * This cluster contains all viewpoints. Its name is defined as "ViewPoint".
+ * The paths of viewpoint objects stored here follow this pattern:
+ * "ViewPoint/<i>Schema Name</i>/<i>Viewpoint Name</i>"
+ */
+ public static final String VIEWPOINT = "ViewPoint";
+ /**
+ * Agents store their persistent jobs in this cluster that have been pushed
+ * to them by activities configured to do so. The name is defined as "Job"
+ * and each new job received is assigned an integer ID one more than the
+ * highest already present.
+ */
+ public static final String JOB = "Job";
+
+ /**
+ * An array of all currently supported cluster types, for iterative
+ * purposes.
+ */
+ public static final String[] allClusterTypes = { PROPERTY, COLLECTION,
+ LIFECYCLE, OUTCOME, HISTORY, VIEWPOINT, JOB };
+
+ /**
+ * Connects to the storage. It must be possible to retrieve CRISTAL local
+ * objects after this method returns.
+ *
+ * @param auth
+ * The Authenticator instance that the user or server logged in
+ * with.
+ * @throws PersistencyException
+ * If storage initialization failed
+ */
+ public abstract void open(Authenticator auth)
+ throws PersistencyException;
+
+ /**
+ * Shuts down the storage. Data must be completely written to disk before
+ * this method returns, so the process can exit. No further gets or puts
+ * should follow.
+ *
+ * @throws PersistencyException
+ * If closing failed
+ */
+ public abstract void close() throws PersistencyException;
+
+ /**
+ * Declares whether or not this ClusterStorage can read or write a
+ * particular CRISTAL local object type.
+ *
+ * @param clusterType
+ * The Cluster type requested. Must be one of the Cluster type
+ * constants from this class.
+ * @return A ClusterStorage constant: NONE, READ, WRITE, or READWRITE
+ */
+ public abstract short queryClusterSupport(String clusterType);
+
+ /**
+ * @return A full name of this storage for logging
+ */
+ public abstract String getName();
+
+ /**
+ * @return A short code for this storage for reference
+ */
+ public abstract String getId();
+
+ /**
+ * Utility method to find the cluster for a particular Local Object (the
+ * first part of its path)
+ *
+ * @param Local
+ * object path
+ * @return The cluster to which it belongs
+ */
+ protected static String getClusterType(String path) {
+ try {
+ if (path == null || path.length() == 0)
+ return ClusterStorage.ROOT;
+ int start = path.charAt(0) == '/' ? 1 : 0;
+ int end = path.indexOf('/', start + 1);
+ if (end == -1)
+ end = path.length();
+ return path.substring(start, end);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ return ClusterStorage.ROOT;
+ }
+ }
+
+ /**
+ * Gives the path for a local object. Varies by Cluster.
+ *
+ * @param C2KLocalObject
+ * @return Its path
+ */
+ public static String getPath(C2KLocalObject obj) {
+ String root = obj.getClusterType();
+ if (root == null)
+ return null; // no storage allowed
+ if (obj instanceof Outcome) {
+ Outcome oc = (Outcome) obj;
+ return root + "/" + oc.getSchemaType() + "/"
+ + oc.getSchemaVersion() + "/" + oc.getName();
+ } else if (obj instanceof Viewpoint) {
+ Viewpoint vp = (Viewpoint) obj;
+ return root + "/" + vp.getSchemaName() + "/" + vp.getName();
+ } else if (obj instanceof Collection) {
+ Collection<?> coll = (Collection<?>) obj;
+ return root + "/" + coll.getName() + "/" +coll.getVersionName();
+ }
+ return root + "/" + obj.getName();
+ }
+
+ /* object manipulation */
+
+ // retrieve object by path
+ /**
+ * Fetches a CRISTAL local object from storage
+ *
+ * @param itemPath
+ * The ItemPath of the containing Item
+ * @param path
+ * The path of the local object
+ * @return The C2KLocalObject, or null if the object was not found
+ * @throws PersistencyException
+ * when retrieval failed
+ */
+ public abstract C2KLocalObject get(ItemPath itemPath, String path)
+ throws PersistencyException;
+
+ /**
+ * Stores a CRISTAL local object. The path is automatically generated.
+ *
+ * @param itemPath
+ * The Item that the object will be stored under
+ * @param obj
+ * The C2KLocalObject to store
+ * @throws PersistencyException
+ * When storage fails
+ */
+ public abstract void put(ItemPath itemPath, C2KLocalObject obj)
+ throws PersistencyException;
+
+ /**
+ * Remove a CRISTAL local object from storage. This should be used sparingly
+ * and responsibly, as it violated traceability. Objects removed in this way
+ * are not expected to be recoverable.
+ *
+ * @param itemPath
+ * The containing Item
+ * @param path
+ * The path of the object to be removed
+ * @throws PersistencyException
+ * When deletion fails or is not allowed
+ */
+ public abstract void delete(ItemPath itemPath, String path)
+ throws PersistencyException;
+
+ // directory listing
+ /**
+ * Queries the local path below the given root and returns the possible next
+ * elements.
+ *
+ * @param itemPath
+ * The Item to query
+ * @param path
+ * The path within that Item to query. May be ClusterStorage.ROOT
+ * (empty String)
+ * @return A String array of the possible next path elements
+ * @throws PersistencyException
+ * When an error occurred during the query
+ */
+ public abstract String[] getClusterContents(ItemPath itemPath, String path)
+ throws PersistencyException;
+
+}
diff --git a/src/main/java/org/cristalise/kernel/persistency/ClusterStorageManager.java b/src/main/java/org/cristalise/kernel/persistency/ClusterStorageManager.java new file mode 100644 index 0000000..46485b6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/ClusterStorageManager.java @@ -0,0 +1,413 @@ +/**
+ * 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.persistency;
+
+import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.entity.agent.JobList;
+import org.cristalise.kernel.entity.proxy.ProxyMessage;
+import org.cristalise.kernel.events.History;
+import org.cristalise.kernel.lookup.ItemPath;
+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.auth.Authenticator;
+import org.cristalise.kernel.utils.Logger;
+import org.cristalise.kernel.utils.SoftCache;
+import org.cristalise.kernel.utils.WeakCache;
+
+
+/**
+ * instantiates ClusterStorages listed in properties file All read/write requests to storage pass through this object, which
+ * can query the capabilities of each declared storage, and channel requests accordingly. Transaction based.
+ *
+ * * @version $Revision: 1.62 $ $Date: 2006/02/01 13:27:46 $
+ * @author $Author: abranson $
+ */
+public class ClusterStorageManager {
+ HashMap<String, ClusterStorage> allStores = new HashMap<String, ClusterStorage>();
+ String[] clusterPriority = new String[0];
+ HashMap<String, ArrayList<ClusterStorage>> clusterWriters = new HashMap<String, ArrayList<ClusterStorage>>();
+ HashMap<String, ArrayList<ClusterStorage>> clusterReaders = new HashMap<String, ArrayList<ClusterStorage>>();
+ // we don't need a soft cache for the top level cache - the proxies and entities clear that when reaped
+ HashMap<ItemPath, Map<String, C2KLocalObject>> memoryCache = new HashMap<ItemPath, Map<String, C2KLocalObject>>();
+
+ /**
+ * Initialises all ClusterStorage handlers listed by class name in the property "ClusterStorages"
+ * This property is usually process specific, and so should be in the server/client.conf and not the connect file.
+ */
+ public ClusterStorageManager(Authenticator auth) throws PersistencyException {
+ Object clusterStorageProp = Gateway.getProperties().getObject("ClusterStorage");
+ if (clusterStorageProp == null || clusterStorageProp.equals("")) {
+ throw new PersistencyException("ClusterStorageManager.init() - no ClusterStorages defined. No persistency!");
+ }
+
+ ArrayList<ClusterStorage> rootStores;
+ if (clusterStorageProp instanceof String)
+ rootStores = instantiateStores((String)clusterStorageProp);
+ else if (clusterStorageProp instanceof ArrayList<?>) {
+ ArrayList<?> propStores = (ArrayList<?>)clusterStorageProp;
+ rootStores = new ArrayList<ClusterStorage>();
+ clusterPriority = new String[propStores.size()];
+ for (Object thisStore : propStores) {
+ if (thisStore instanceof ClusterStorage)
+ rootStores.add((ClusterStorage)thisStore);
+ else
+ throw new PersistencyException("Supplied ClusterStorage "+thisStore.toString()+" was not an instance of ClusterStorage");
+ }
+ }
+ else {
+ throw new PersistencyException("Unknown class of ClusterStorage property: "+clusterStorageProp.getClass().getName());
+ }
+
+ int clusterNo = 0;
+ for (ClusterStorage newStorage : rootStores) {
+ try {
+ newStorage.open(auth);
+ } catch (PersistencyException ex) {
+ Logger.error(ex);
+ throw new PersistencyException("ClusterStorageManager.init() - Error initialising storage handler " + newStorage.getClass().getName() +
+ ": " + ex.getMessage());
+ }
+ Logger.msg(5, "ClusterStorageManager.init() - Cluster storage " + newStorage.getClass().getName() +
+ " initialised successfully.");
+ allStores.put(newStorage.getId(), newStorage);
+ clusterPriority[clusterNo++] = newStorage.getId();
+ }
+ clusterReaders.put(ClusterStorage.ROOT, rootStores); // all storages are queried for clusters at the root level
+
+ }
+
+ public ArrayList<ClusterStorage> instantiateStores(String allClusters) throws PersistencyException {
+ ArrayList<ClusterStorage> rootStores = new ArrayList<ClusterStorage>();
+ StringTokenizer tok = new StringTokenizer(allClusters, ",");
+ clusterPriority = new String[tok.countTokens()];
+
+ while (tok.hasMoreTokens()) {
+ ClusterStorage newStorage = null;
+ String newStorageClass = tok.nextToken();
+ try {
+ try {
+ newStorage = (ClusterStorage)(Class.forName(newStorageClass).newInstance());
+ } catch (ClassNotFoundException ex2) {
+ newStorage = (ClusterStorage)(Class.forName("org.cristalise.storage."+newStorageClass).newInstance());
+ }
+ } catch (ClassNotFoundException ex) {
+ throw new PersistencyException("ClusterStorageManager.init() - The cluster storage handler class " + newStorageClass +
+ " could not be found.");
+ } catch (InstantiationException ex) {
+ throw new PersistencyException("ClusterStorageManager.init() - The cluster storage handler class " + newStorageClass +
+ " could not be instantiated.");
+ } catch (IllegalAccessException ex) {
+ throw new PersistencyException("ClusterStorageManager.init() - The cluster storage handler class " + newStorageClass +
+ " was not allowed to be instantiated.");
+ }
+ rootStores.add(newStorage);
+ }
+ return rootStores;
+ }
+
+ public void close() {
+ for (ClusterStorage thisStorage : allStores.values()) {
+ try {
+ thisStorage.close();
+ } catch (PersistencyException ex) {
+ Logger.error(ex);
+ }
+ }
+ }
+
+ /**
+ * Returns the loaded storage that declare that they can handle writing or reading the specified cluster name (e.g.
+ * Collection, Property) Must specify if the request is a read or a write.
+ */
+ private ArrayList<ClusterStorage> findStorages(String clusterType, boolean forWrite) {
+
+ // choose the right cache for readers or writers
+ HashMap<String, ArrayList<ClusterStorage>> cache;
+ if (forWrite)
+ cache = clusterWriters;
+ else
+ cache = clusterReaders;
+
+ // check to see if we've been asked to do this before
+ if (cache.containsKey(clusterType))
+ return cache.get(clusterType);
+
+ // not done yet, we'll have to query them all
+ Logger.msg(7, "ClusterStorageManager.findStorages() - finding storage for "+clusterType+" forWrite:"+forWrite);
+ ArrayList<ClusterStorage> useableStorages = new ArrayList<ClusterStorage>();
+ for (String element : clusterPriority) {
+ ClusterStorage thisStorage = allStores.get(element);
+ short requiredSupport = forWrite ? ClusterStorage.WRITE : ClusterStorage.READ;
+ if ((thisStorage.queryClusterSupport(clusterType) & requiredSupport) == requiredSupport) {
+ Logger.msg(7, "ClusterStorageManager.findStorages() - Got "+thisStorage.getName());
+ useableStorages.add(thisStorage);
+ }
+ }
+ cache.put(clusterType, useableStorages);
+ return useableStorages;
+ }
+
+ /**
+ * Retrieves the ids of the next level of a cluster
+ * Does not look in any currently open transactions.
+ */
+ public String[] getClusterContents(ItemPath itemPath, String path) throws PersistencyException {
+
+ ArrayList<String> contents = new ArrayList<String>();
+ // get all readers
+ Logger.msg(8, "ClusterStorageManager.getClusterContents() - Finding contents of "+path);
+ ArrayList<ClusterStorage> readers = findStorages(ClusterStorage.getClusterType(path), false);
+ // try each in turn until we get a result
+ for (ClusterStorage thisReader : readers) {
+ try {
+ String[] thisArr = thisReader.getClusterContents(itemPath, path);
+ if (thisArr != null) {
+ for (int j = 0; j < thisArr.length; j++)
+ if (!contents.contains(thisArr[j])) {
+ Logger.msg(9, "ClusterStorageManager.getClusterContents() - "+thisReader.getName()+" reports "+thisArr[j]);
+ contents.add(thisArr[j]);
+ }
+ }
+ } catch (PersistencyException e) {
+ Logger.msg(5, "ClusterStorageManager.getClusterContents() - reader " + thisReader.getName() +
+ " could not retrieve contents of " + itemPath + "/" + path + ": " + e.getMessage());
+ }
+ }
+
+ String[] retArr = new String[0];
+ retArr = contents.toArray(retArr);
+ return retArr;
+ }
+
+ /** Internal get method. Retrieves clusters from ClusterStorages & maintains the memory cache */
+ public C2KLocalObject get(ItemPath itemPath, String path) throws PersistencyException, ObjectNotFoundException {
+ C2KLocalObject result = null;
+ // check cache first
+ Map<String, C2KLocalObject> sysKeyMemCache = null;
+ sysKeyMemCache = memoryCache.get(itemPath);
+ if (sysKeyMemCache != null) {
+ synchronized(sysKeyMemCache) {
+ C2KLocalObject obj = sysKeyMemCache.get(path);
+ if (obj != null) {
+ Logger.msg(7, "ClusterStorageManager.get() - found "+itemPath+"/"+path+" in memcache");
+ return obj;
+ }
+ }
+ }
+
+ // special case - loading viewpoint contents
+ if (path.startsWith(ClusterStorage.VIEWPOINT) &&
+ path.endsWith("/data")) {
+ StringTokenizer tok = new StringTokenizer(path,"/");
+ if (tok.countTokens() == 4) { // to not catch viewpoints called 'data'
+ Outcome data = null;
+ Viewpoint view = (Viewpoint)get(itemPath, path.substring(0, path.lastIndexOf("/")));
+ if (view != null)
+ data = view.getOutcome();
+ return data;
+ }
+ }
+
+ // deal out top level remote maps
+ if (path.indexOf('/') == -1) {
+ if (path.equals(ClusterStorage.HISTORY))
+ result = new History(itemPath, null);
+ if (path.equals(ClusterStorage.JOB))
+ result = new JobList(itemPath, null);
+ if (result!=null) {
+ synchronized(sysKeyMemCache) {
+ sysKeyMemCache.put(path, result);
+ }
+ return result;
+ }
+
+ }
+
+ // else try each reader in turn until we find it
+ ArrayList<ClusterStorage> readers = findStorages(ClusterStorage.getClusterType(path), false);
+ for (ClusterStorage thisReader : readers) {
+ try {
+ result = thisReader.get(itemPath, path);
+ Logger.msg(7, "ClusterStorageManager.get() - reading "+path+" from "+thisReader.getName() + " for item " + itemPath);
+ if (result != null) { // got it!
+ // store it in the cache
+ if (sysKeyMemCache == null) { // create cache if needed
+ boolean useWeak = Gateway.getProperties().getBoolean("Storage.useWeakCache", false);
+ Logger.msg(7,"ClusterStorageManager.put() - Creating "+(useWeak?"Weak":"Strong")+" cache for item "+itemPath);
+ sysKeyMemCache = useWeak?new WeakCache<String, C2KLocalObject>():new SoftCache<String, C2KLocalObject>(0);
+ synchronized (memoryCache) {
+ memoryCache.put(itemPath, sysKeyMemCache);
+ }
+ }
+ synchronized(sysKeyMemCache) {
+ sysKeyMemCache.put(path, result);
+ }
+ // then return it
+ return result;
+ }
+ } catch (PersistencyException e) {
+ Logger.msg(7, "ClusterStorageManager.get() - reader " + thisReader.getName() + " could not retrieve " + itemPath +
+ "/" + path + ": " + e.getMessage());
+ }
+ }
+ throw new ObjectNotFoundException("ClusterStorageManager.get() - Path " + path + " not found in " + itemPath);
+ }
+
+ /** Internal put method. Creates or overwrites a cluster in all writers. Used when committing transactions. */
+ public void put(ItemPath itemPath, C2KLocalObject obj) throws PersistencyException {
+ String path = ClusterStorage.getPath(obj);
+ ArrayList<ClusterStorage> writers = findStorages(ClusterStorage.getClusterType(path), true);
+ for (ClusterStorage thisWriter : writers) {
+ try {
+ Logger.msg(7, "ClusterStorageManager.put() - writing "+path+" to "+thisWriter.getName());
+ thisWriter.put(itemPath, obj);
+ } catch (PersistencyException e) {
+ Logger.error("ClusterStorageManager.put() - writer " + thisWriter.getName() + " could not store " +
+ itemPath + "/" + path + ": " + e.getMessage());
+ throw e;
+ }
+ }
+ // put in mem cache if that worked
+ Map<String, C2KLocalObject> sysKeyMemCache;
+ if (memoryCache.containsKey(itemPath))
+ sysKeyMemCache = memoryCache.get(itemPath);
+ else {
+ boolean useWeak = Gateway.getProperties().getBoolean("Storage.useWeakCache", false);
+ Logger.msg(7,"ClusterStorageManager.put() - Creating "+(useWeak?"Weak":"Strong")+" cache for entity "+itemPath);
+ sysKeyMemCache = useWeak?new WeakCache<String, C2KLocalObject>():new SoftCache<String, C2KLocalObject>(0);
+ synchronized (memoryCache) {
+ memoryCache.put(itemPath, sysKeyMemCache);
+ }
+ }
+
+ synchronized(sysKeyMemCache) {
+ sysKeyMemCache.put(path, obj);
+ }
+
+ if (Logger.doLog(9)) dumpCacheContents(9);
+
+ // transmit proxy event
+ Gateway.getProxyServer().sendProxyEvent( new ProxyMessage(itemPath, path, ProxyMessage.ADDED));
+ }
+
+ /** Deletes a cluster from all writers */
+ public void remove(ItemPath itemPath, String path) throws PersistencyException {
+ ArrayList<ClusterStorage> writers = findStorages(ClusterStorage.getClusterType(path), true);
+ for (ClusterStorage thisWriter : writers) {
+ try {
+ Logger.msg(7, "ClusterStorageManager.delete() - removing "+path+" from "+thisWriter.getName());
+ thisWriter.delete(itemPath, path);
+ } catch (PersistencyException e) {
+ Logger.error("ClusterStorageManager.delete() - writer " + thisWriter.getName() + " could not delete " + itemPath +
+ "/" + path + ": " + e.getMessage());
+ throw e;
+ }
+ }
+
+ if (memoryCache.containsKey(itemPath)) {
+ Map<String, C2KLocalObject> itemMemCache = memoryCache.get(itemPath);
+ synchronized (itemMemCache) {
+ itemMemCache.remove(path);
+ }
+ }
+
+
+ // transmit proxy event
+ Gateway.getProxyServer().sendProxyEvent( new ProxyMessage(itemPath, path, ProxyMessage.DELETED));
+ }
+
+ public void clearCache(ItemPath itemPath, String path) {
+ Logger.msg(7, "CSM.clearCache() - removing "+itemPath+"/"+path);
+
+ if (memoryCache.containsKey(itemPath)) {
+ Map<String, C2KLocalObject> sysKeyMemCache = memoryCache.get(itemPath);
+ synchronized(sysKeyMemCache) {
+ for (Iterator<String> iter = sysKeyMemCache.keySet().iterator(); iter.hasNext();) {
+ String thisPath = iter.next();
+ if (thisPath.startsWith(path)) {
+ Logger.msg(7, "CSM.clearCache() - removing "+itemPath+"/"+thisPath);
+ iter.remove();
+ }
+ }
+ }
+ }
+ }
+
+ public void clearCache(ItemPath itemPath) {
+
+ Logger.msg(5, "CSM.clearCache() - removing entire cache of "+itemPath);
+
+ if (memoryCache.containsKey(itemPath)) {
+ synchronized (memoryCache) {
+ if (Logger.doLog(6)) {
+ Map<String, C2KLocalObject> sysKeyMemCache = memoryCache.get(itemPath);
+ int size = sysKeyMemCache.size();
+ Logger.msg(6, "CSM.clearCache() - "+size+" objects to remove.");
+ }
+ memoryCache.remove(itemPath);
+ }
+ }
+ else
+ Logger.msg(6, "CSM.clearCache() - No objects cached");
+ }
+
+ public void clearCache() {
+ synchronized (memoryCache) {
+ memoryCache.clear();
+ }
+ Logger.msg(5, "CSM.clearCache() - cleared entire cache, "+memoryCache.size()+" entities.");
+ }
+
+ public void dumpCacheContents(int logLevel) {
+ if (!Logger.doLog(logLevel)) return;
+ synchronized(memoryCache) {
+ for (ItemPath itemPath : memoryCache.keySet()) {
+ Logger.msg(logLevel, "Cached Objects of Entity "+itemPath);
+ Map<String, C2KLocalObject> sysKeyMemCache = memoryCache.get(itemPath);
+ try {
+ synchronized(sysKeyMemCache) {
+ for (Object name : sysKeyMemCache.keySet()) {
+ String path = (String) name;
+ try {
+ Logger.msg(logLevel, " Path "+path+": "+sysKeyMemCache.get(path).getClass().getName());
+ } catch (NullPointerException e) {
+ Logger.msg(logLevel, " Path "+path+": reaped");
+ }
+ }
+ }
+ } catch (ConcurrentModificationException ex) {
+ Logger.msg(logLevel, "Cache modified - aborting");
+ }
+ }
+ Logger.msg(logLevel, "Total number of cached entities: "+memoryCache.size());
+ }
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/persistency/RemoteMap.java b/src/main/java/org/cristalise/kernel/persistency/RemoteMap.java new file mode 100644 index 0000000..deb8f0b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/RemoteMap.java @@ -0,0 +1,398 @@ +/**
+ * 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.persistency;
+
+import java.util.AbstractSet;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.TreeMap;
+
+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.entity.proxy.MemberSubscription;
+import org.cristalise.kernel.entity.proxy.ProxyObserver;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**
+ * Maps a storage cluster onto a java.util.Map
+ *
+ * @author Andrew Branson
+ * $Revision: 1.22 $
+ * $Date: 2006/03/03 13:52:21 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ */
+public class RemoteMap<V extends C2KLocalObject> extends TreeMap<String, V> implements C2KLocalObject {
+
+ private int mID=-1;
+ private String mName;
+ protected ItemPath mItemPath;
+ private String mPath = "";
+ Object keyLock = null;
+ TransactionManager storage;
+ ProxyObserver<V> listener;
+ Comparator<String> comp;
+ ItemProxy source;
+ Object mLocker; // if this remote map will participate in a transaction
+
+ public RemoteMap(ItemPath itemPath, String path, Object locker) {
+
+ super(new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ Integer i1 = null, i2 = null;
+ try {
+ i1 = Integer.valueOf(o1);
+ i2 = Integer.valueOf(o2);
+ return i1.compareTo(i2);
+ } catch (NumberFormatException ex) { }
+ return o1.compareTo(o2);
+ }
+ });
+
+ mItemPath = itemPath;
+ mLocker = locker;
+
+ // split the path into path/name
+ int lastSlash = path.lastIndexOf("/");
+ mName = path.substring(lastSlash+1);
+ if (lastSlash>0) mPath = path.substring(0,lastSlash);
+
+ // see if the name is also a suitable id
+ try {
+ mID = Integer.parseInt(mName);
+ } catch (NumberFormatException e) {}
+ storage = Gateway.getStorage();
+
+ listener = new ProxyObserver<V>() {
+ @Override
+ public void add(V obj) {
+ synchronized (this) {
+ putLocal(obj.getName(), obj);
+ }
+ }
+
+ @Override
+ public void remove(String id) {
+ synchronized (this) {
+ removeLocal(id);
+ }
+ }
+
+ @Override
+ public void control(String control, String msg) { }
+ };
+
+ try {
+ source = Gateway.getProxyManager().getProxy(mItemPath);
+ source.subscribe(new MemberSubscription<V>(listener, path, false));
+ } catch (Exception ex) {
+ Logger.error("Error subscribing to remote map. Changes will not be received");
+ Logger.error(ex);
+ }
+ }
+
+ protected void loadKeys() {
+ if (keyLock != null) return;
+ clear();
+ keyLock = new Object();
+ synchronized(this) {
+ String[] keys;
+ try {
+ keys = storage.getClusterContents(mItemPath, mPath+mName);
+ for (String key : keys) super.put(key, null);
+ } catch (PersistencyException e) {
+ Logger.error(e);
+ }
+
+ }
+ }
+
+ public synchronized int getLastId() {
+ loadKeys();
+ if (size() == 0) return -1;
+ try {
+ return Integer.parseInt(lastKey());
+ } catch (NumberFormatException ex) {
+ return -1;
+ }
+ }
+
+
+ // c2kLocalObject methods
+ public void setID(int id) { mID = id; }
+
+ public int getID() { return mID; }
+
+ @Override
+ public void setName(String name) { mName = name; }
+
+ @Override
+ public String getName() { return mName; }
+
+ /**
+ * Cannot be stored
+ */
+ @Override
+ public String getClusterType() {
+ return null;
+ }
+ /**
+ * @see java.util.Map#clear()
+ */
+ @Override
+ public synchronized void clear() {
+ synchronized (this) {
+ super.clear();
+ }
+ keyLock = null;
+ }
+
+
+
+ /**
+ * @see java.util.Map#containsKey(Object)
+ */
+ @Override
+ public synchronized boolean containsKey(Object key) {
+ if (keyLock == null) loadKeys();
+ return super.containsKey(key);
+ }
+
+ /**
+ * This must retrieve all the values until a match is made.
+ * Very expensive, but if you must, you must.
+ * @see java.util.Map#containsValue(Object)
+ */
+ @Override
+ public synchronized boolean containsValue(Object value) {
+ loadKeys();
+ synchronized(this) {
+ for (String key: keySet()) {
+ if (get(key).equals(value)) return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * @see java.util.Map#get(Object)
+ */
+ @Override
+ public synchronized V get(Object objKey) {
+ loadKeys();
+ String key;
+ if (objKey instanceof Integer)
+ key = ((Integer)objKey).toString();
+ else if (objKey instanceof String)
+ key = (String)objKey;
+ else
+ return null;
+
+ synchronized(this) {
+ try {
+ V value = super.get(key);
+ if (value == null) {
+ value = (V)storage.get(mItemPath, mPath+mName+"/"+key, mLocker);
+ super.put(key, value);
+ }
+ return value;
+ } catch (PersistencyException e) {
+ Logger.error(e);
+ } catch (ObjectNotFoundException e) {
+ Logger.error(e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * @see java.util.Map#isEmpty()
+ */
+ @Override
+ public synchronized boolean isEmpty() {
+ loadKeys();
+ return super.isEmpty();
+ }
+
+ /**
+ * @see java.util.Map#keySet()
+ */
+ @Override
+ public synchronized Set<String> keySet() {
+ loadKeys();
+ return super.keySet();
+ }
+
+ /**
+ * Inserts the given object into the storage
+ * the key is ignored - it can be fetched from the value.
+ * @see java.util.Map#put(Object, Object)
+ */
+ @Override
+ public synchronized V put(String key, V value) {
+ try {
+ synchronized(this) {
+ storage.put(mItemPath, value, mLocker);
+ return putLocal(key, value);
+ }
+ } catch (PersistencyException e) {
+ Logger.error(e);
+ return null;
+ }
+ }
+
+ protected synchronized V putLocal(String key, V value) {
+ return super.put(key, value);
+ }
+
+ /**
+ * @see java.util.Map#remove(Object)
+ */
+ @Override
+ public synchronized V remove(Object key) {
+ loadKeys();
+ if (containsKey(key)) try {
+ synchronized(keyLock) {
+ storage.remove(mItemPath, mPath+mName+"/"+key, mLocker);
+ return super.remove(key);
+ }
+ } catch (PersistencyException e) {
+ Logger.error(e);
+ }
+ return null;
+ }
+
+ protected synchronized V removeLocal(Object key) {
+ return super.remove(key);
+ }
+
+ /**
+ * @see java.util.Map#size()
+ */
+ @Override
+ public synchronized int size() {
+ loadKeys();
+ return super.size();
+ }
+
+ /**
+ * @see java.util.Map#values()
+ */
+ @Override
+ public synchronized Collection<V> values() {
+ return new RemoteSet<V>(this);
+ }
+
+ /**
+ * Basic implementation of Set and Collection to bridge to the Iterator
+ * Disallows all writes.
+ */
+
+ private class RemoteSet<E extends C2KLocalObject> extends AbstractSet<E> {
+ RemoteMap<E> mParent;
+
+ public RemoteSet(RemoteMap<E> parent) {
+ mParent = parent;
+ }
+
+ // no modifications allowed
+ @Override
+ public boolean add(E o) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public boolean addAll(Collection<? extends E> c) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public void clear() {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public boolean remove(Object o) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public boolean removeAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+ @Override
+ public boolean retainAll(Collection<?> c) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Iterator<E> iterator() {
+ return new RemoteIterator<E>(mParent);
+ }
+
+ @Override
+ public int size() {
+ return mParent.size();
+ }
+
+ }
+ /**
+ * Iterator view on RemoteMap data. Doesn't preload anything.
+ * REVISIT: Will go strange if the RemoteMap is modified. Detect this and throw ConcurrentMod ex
+ */
+ private class RemoteIterator<C extends C2KLocalObject> implements Iterator<C> {
+ RemoteMap<C> mParent;
+ Iterator<String> iter;
+ String currentKey;
+
+ public RemoteIterator(RemoteMap<C> parent) {
+ mParent = parent;
+ iter = mParent.keySet().iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return iter.hasNext();
+ }
+
+ @Override
+ public C next() {
+ currentKey = iter.next();
+ return mParent.get(currentKey);
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ }
+
+
+
+
+}
diff --git a/src/main/java/org/cristalise/kernel/persistency/TransactionManager.java b/src/main/java/org/cristalise/kernel/persistency/TransactionManager.java new file mode 100644 index 0000000..7712da6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/TransactionManager.java @@ -0,0 +1,353 @@ +/**
+ * 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.persistency;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.entity.agent.JobList;
+import org.cristalise.kernel.events.History;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.process.auth.Authenticator;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class TransactionManager {
+
+ HashMap<ItemPath, Object> locks;
+ HashMap<Object, ArrayList<TransactionEntry>> pendingTransactions;
+ ClusterStorageManager storage;
+
+ public TransactionManager(Authenticator auth) throws PersistencyException {
+ storage = new ClusterStorageManager(auth);
+ locks = new HashMap<ItemPath, Object>();
+ pendingTransactions = new HashMap<Object, ArrayList<TransactionEntry>>();
+ }
+
+ public boolean hasPendingTransactions()
+ {
+ return pendingTransactions.size() > 0;
+ }
+
+ public ClusterStorageManager getDb() {
+ return storage;
+ }
+
+ public void close() {
+ if (pendingTransactions.size() != 0) {
+ Logger.error("There were pending transactions on shutdown. All changes were lost.");
+ dumpPendingTransactions(0);
+ }
+ Logger.msg("Transaction Manager: Closing storages");
+ storage.close();
+ }
+
+ public String[] getClusterContents(ItemPath itemPath, String path) throws PersistencyException {
+ if (path.startsWith("/") && path.length() > 1) path = path.substring(1);
+ return storage.getClusterContents(itemPath, path);
+ }
+
+ /**
+ * Public get method. Required a 'locker' object for a transaction key.
+ * Checks the transaction table first to see if the caller has uncommitted changes
+ */
+ public C2KLocalObject get(ItemPath itemPath, String path, Object locker)
+ throws PersistencyException,
+ ObjectNotFoundException {
+ if (path.startsWith("/") && path.length() > 1) path = path.substring(1);
+
+ // deal out top level remote maps, if transactions aren't needed
+ if (path.indexOf('/') == -1) {
+ if (path.equals(ClusterStorage.HISTORY) && locker != null)
+ return new History(itemPath, locker);
+ if (path.equals(ClusterStorage.JOB) && locker != null)
+ return new JobList(itemPath, locker);
+ }
+
+ // check to see if the locker has been modifying this cluster
+ if (locks.containsKey(itemPath) && locks.get(itemPath).equals(locker)) {
+ ArrayList<TransactionEntry> lockerTransaction = pendingTransactions.get(locker);
+ for (TransactionEntry thisEntry : lockerTransaction) {
+ if (itemPath.equals(thisEntry.itemPath) && path.equals(thisEntry.path)) {
+ if (thisEntry.obj == null)
+ throw new PersistencyException("ClusterStorageManager.get() - Cluster " + path + " has been deleted in " + itemPath +
+ " but not yet committed");
+ return thisEntry.obj;
+ }
+ }
+ }
+ return storage.get(itemPath, path);
+ }
+
+ /**
+ * Public put method. Manages the transaction table keyed by the object 'locker'.
+ * If this object is null, transaction support is bypassed (so long as no lock exists on that object).
+ */
+ public void put(ItemPath itemPath, C2KLocalObject obj, Object locker) throws PersistencyException {
+ Object tempLocker = null;
+ ArrayList<TransactionEntry> lockerTransaction;
+
+ synchronized(locks) {
+ // look to see if this object is already locked
+ if (locks.containsKey(itemPath)) {
+ // if it's this locker, get the transaction list
+ Object thisLocker = locks.get(itemPath);
+ if (thisLocker.equals(locker)) // retrieve the transaction list
+ lockerTransaction = pendingTransactions.get(locker);
+ else // locked by someone else
+ throw new PersistencyException("ClusterStorageManager.get() - Access denied: Object " + itemPath +
+ " has been locked for writing by " + thisLocker);
+ }
+ else { // no locks for this item
+ if (locker == null) { // lock the item until the non-transactional put is complete :/
+ tempLocker = new Object();
+ locks.put(itemPath, tempLocker);
+ lockerTransaction = null;
+ }
+ else { // initialise the transaction
+ locks.put(itemPath, locker);
+ lockerTransaction = new ArrayList<TransactionEntry>();
+ pendingTransactions.put(locker, lockerTransaction);
+ }
+ }
+ }
+
+ if (tempLocker != null) { // non-locking put/delete
+ storage.put(itemPath, obj);
+ locks.remove(itemPath);
+ return;
+ }
+
+ // create the new entry in the transaction table
+ TransactionEntry newEntry = new TransactionEntry(itemPath, obj);
+ /* equals() in TransactionEntry only compares sysKey and path, so we can use
+ * contains() in ArrayList to looks for preexisting entries for this cluster
+ * and overwrite them.
+ */
+ if (lockerTransaction.contains(newEntry))
+ lockerTransaction.remove(newEntry);
+ lockerTransaction.add(newEntry);
+ }
+
+ /** Public delete method. Uses the put method, with null as the object value.
+ */
+ public void remove(ItemPath itemPath, String path, Object locker) throws PersistencyException {
+ ArrayList<TransactionEntry> lockerTransaction;
+ Object tempLocker = null;
+ synchronized(locks) {
+ // look to see if this object is already locked
+ if (locks.containsKey(itemPath)) {
+ // if it's this locker, get the transaction list
+ Object thisLocker = locks.get(itemPath);
+ if (thisLocker.equals(locker)) // retrieve the transaction list
+ lockerTransaction = pendingTransactions.get(locker);
+ else // locked by someone else
+ throw new PersistencyException("ClusterStorageManager.get() - Access denied: Object " + itemPath +
+ " has been locked for writing by " + thisLocker);
+ }
+ else { // either we are the locker, or there is no locker
+ if (locker == null) { // non-locking put/delete
+ tempLocker = new Object();
+ locks.put(itemPath, tempLocker);
+ lockerTransaction = null;
+ }
+ else {// initialise the transaction
+ locks.put(itemPath, locker);
+ lockerTransaction = new ArrayList<TransactionEntry>();
+ pendingTransactions.put(locker, lockerTransaction);
+ }
+ }
+ }
+
+ if (tempLocker != null) {
+ storage.remove(itemPath, path);
+ locks.remove(itemPath);
+ return;
+ }
+
+ // create the new entry in the transaction table
+ TransactionEntry newEntry = new TransactionEntry(itemPath, path);
+ /* equals() in TransactionEntry only compares sysKey and path, so we can use
+ * contains() in ArrayList to looks for preexisting entries for this cluster
+ * and overwrite them.
+ */
+ if (lockerTransaction.contains(newEntry))
+ lockerTransaction.remove(newEntry);
+ lockerTransaction.add(newEntry);
+
+ }
+
+ /**
+ * Removes all child objects from the given path
+ *
+ * @param sysKey - entity to delete from
+ * @param path - root path to delete
+ * @param locker - locking object
+ *
+ * @throws PersistencyException - when deleting fails
+ */
+ public void removeCluster(ItemPath itemPath, String path, Object locker) throws PersistencyException {
+
+ String[] children = getClusterContents(itemPath, path);
+ for (String element : children)
+ removeCluster(itemPath, path+(path.length()>0?"/":"")+element, locker);
+ if (children.length==0 && path.indexOf("/") > -1)
+ remove(itemPath, path, locker);
+
+ }
+ /**
+ * Writes all pending changes to the backends.
+ */
+ public void commit(Object locker) {
+ synchronized(locks) {
+ ArrayList<TransactionEntry> lockerTransactions = pendingTransactions.get(locker);
+ HashMap<TransactionEntry, Exception> exceptions = new HashMap<TransactionEntry, Exception>();
+ // quit if no transactions are present;
+ if (lockerTransactions == null) return;
+ for (TransactionEntry thisEntry : lockerTransactions) {
+ try {
+ if (thisEntry.obj == null)
+ storage.remove(thisEntry.itemPath, thisEntry.path);
+ else
+ storage.put(thisEntry.itemPath, thisEntry.obj);
+ locks.remove(thisEntry.itemPath);
+ } catch (Exception e) {
+ exceptions.put(thisEntry, e);
+ }
+ }
+ pendingTransactions.remove(locker);
+ if (exceptions.size() > 0) { // oh dear
+ Logger.error("TransactionManager.commit() - Problems during transaction commit of locker "+locker.toString()+". Database may be in an inconsistent state.");
+ for (TransactionEntry entry : exceptions.keySet()) {
+ Exception ex = exceptions.get(entry);
+ Logger.msg(entry.toString());
+ Logger.error(ex);
+ }
+ dumpPendingTransactions(0);
+ Logger.die("Database failure");
+ }
+
+ }
+ }
+
+ /**
+ * Rolls back all changes sent in the name of 'locker' and unlocks the sysKeys
+ */
+ public void abort(Object locker) {
+ synchronized(locks) {
+ if (locks.containsValue(locker)) {
+ for (ItemPath thisPath : locks.keySet()) {
+ if (locks.get(thisPath).equals(locker))
+ locks.remove(thisPath);
+ }
+ }
+ pendingTransactions.remove(locker);
+ }
+ }
+
+ public void clearCache(ItemPath itemPath, String path) {
+ if (itemPath == null)
+ storage.clearCache();
+ else if (path == null)
+ storage.clearCache(itemPath);
+ else
+ storage.clearCache(itemPath, path);
+
+ }
+
+ public void dumpPendingTransactions(int logLevel) {
+ Logger.msg(logLevel, "================");
+ Logger.msg(logLevel, "Transaction dump");
+ Logger.msg(logLevel, "Locked Items:");
+ if (locks.size() == 0)
+ Logger.msg(logLevel, " None");
+ else
+ for (ItemPath thisPath : locks.keySet()) {
+ Object locker = locks.get(thisPath);
+ Logger.msg(logLevel, " "+thisPath+" locked by "+locker);
+ }
+
+ Logger.msg(logLevel, "Open transactions:");
+ if (pendingTransactions.size() == 0)
+ Logger.msg(logLevel, " None");
+ else
+ for (Object thisLocker : pendingTransactions.keySet()) {
+ Logger.msg(logLevel, " Transaction owner:"+thisLocker);
+ ArrayList<TransactionEntry> entries = pendingTransactions.get(thisLocker);
+ for (TransactionEntry thisEntry : entries) {
+ Logger.msg(logLevel, " "+thisEntry.toString());
+ }
+ }
+ }
+
+ /** Used in the transaction table to store details of a put until commit
+ */
+ static class TransactionEntry {
+ public ItemPath itemPath;
+ public String path;
+ public C2KLocalObject obj;
+ public TransactionEntry(ItemPath itemPath, C2KLocalObject obj) {
+ this.itemPath = itemPath;
+ this.path = ClusterStorage.getPath(obj);
+ this.obj = obj;
+ }
+
+ public TransactionEntry(ItemPath itemPath, String path) {
+ this.itemPath = itemPath;
+ this.path = path;
+ this.obj = null;
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer report = new StringBuffer();
+ if (obj == null)
+ report.append("Delete");
+ else
+ report.append("Put "+obj.getClass().getName());
+ report.append(" at ").append(path).append(" in ").append(itemPath);
+ return report.toString();
+
+ }
+ /**
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return itemPath.hashCode()*path.hashCode();
+ }
+
+ /**
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other instanceof TransactionEntry)
+ return hashCode() == ((TransactionEntry)other).hashCode();
+ return false;
+ }
+
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/persistency/outcome/Outcome.java b/src/main/java/org/cristalise/kernel/persistency/outcome/Outcome.java new file mode 100644 index 0000000..95f3e6b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/outcome/Outcome.java @@ -0,0 +1,290 @@ +/**
+ * 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.persistency.outcome;
+import java.io.StringReader;
+import java.util.StringTokenizer;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+
+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.persistency.ClusterStorage;
+import org.cristalise.kernel.utils.LocalObjectLoader;
+import org.cristalise.kernel.utils.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.w3c.dom.bootstrap.DOMImplementationRegistry;
+import org.w3c.dom.ls.DOMImplementationLS;
+import org.w3c.dom.ls.LSSerializer;
+import org.xml.sax.InputSource;
+
+
+public class Outcome implements C2KLocalObject {
+ Integer mID;
+ String mData;
+ String mSchemaType;
+ int mSchemaVersion;
+ Document dom;
+ static DocumentBuilder parser;
+ static DOMImplementationLS impl;
+ static XPath xpath;
+
+ static {
+ // Set up parser
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setValidating(false);
+ dbf.setNamespaceAware(false);
+ try {
+ parser = dbf.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ Logger.error(e);
+ Logger.die("Cannot function without XML parser");
+ }
+
+ // Set up serialiser
+ try {
+ DOMImplementationRegistry registry = DOMImplementationRegistry.newInstance();
+ impl = (DOMImplementationLS)registry.getDOMImplementation("LS");
+ } catch (Exception e) {
+ Logger.error(e);
+ Logger.die("Cannot function without XML serialiser");
+ }
+
+ XPathFactory xPathFactory = XPathFactory.newInstance();
+ xpath = xPathFactory.newXPath();
+ }
+
+ //id is the eventID
+ public Outcome(int id, String data, String schemaType, int schemaVersion) {
+ mID = id;
+ mData = data;
+ mSchemaType = schemaType;
+ mSchemaVersion = schemaVersion;
+ }
+
+ public Outcome(String path, String data) throws PersistencyException {
+ // derive all the meta data from the path
+ StringTokenizer tok = new StringTokenizer(path,"/");
+ if (tok.countTokens() != 3 && !(tok.nextToken().equals(ClusterStorage.OUTCOME)))
+ throw new PersistencyException("Outcome() - Outcome path must have three components: "+path);
+ mSchemaType = tok.nextToken();
+ String verstring = tok.nextToken();
+ String objId = tok.nextToken();
+ try {
+ mSchemaVersion = Integer.parseInt(verstring);
+ } catch (NumberFormatException ex) {
+ throw new PersistencyException("Outcome() - Outcome version was an invalid number: "+verstring);
+ }
+ try {
+ mID = Integer.valueOf(objId);
+ } catch (NumberFormatException ex) {
+ mID = null;
+ }
+ mData = data;
+ }
+
+ public void setID(Integer ID) {
+ mID = ID;
+ }
+
+ public Integer getID() {
+ return mID;
+ }
+
+ @Override
+ public void setName(String name) {
+ try {
+ mID = Integer.valueOf(name);
+ } catch (NumberFormatException e) {
+ Logger.error("Invalid id set on Outcome:"+name);
+ }
+ }
+
+ @Override
+ public String getName() {
+ return mID.toString();
+ }
+
+ public void setData(String data) {
+ mData = data;
+ dom = null;
+ }
+
+ public void setData(Document data) {
+ dom = data;
+ mData = null;
+ }
+
+ public String getFieldByXPath(String xpath) throws XPathExpressionException, InvalidDataException {
+ Node field = getNodeByXPath(xpath);
+ if (field == null)
+ throw new InvalidDataException(xpath);
+
+ else if (field.getNodeType()==Node.TEXT_NODE || field.getNodeType()==Node.CDATA_SECTION_NODE)
+ return field.getNodeValue();
+
+ else if (field.getNodeType()==Node.ELEMENT_NODE) {
+ NodeList fieldChildren = field.getChildNodes();
+ if (fieldChildren.getLength() == 0)
+ throw new InvalidDataException("No child node for element");
+
+ else if (fieldChildren.getLength() == 1) {
+ Node child = fieldChildren.item(0);
+ if (child.getNodeType()==Node.TEXT_NODE || child.getNodeType()==Node.CDATA_SECTION_NODE)
+ return child.getNodeValue();
+ else
+ throw new InvalidDataException("Can't get data from child node of type "+child.getNodeName());
+ }
+ else
+ throw new InvalidDataException("Element "+xpath+" has too many children");
+ }
+ else if (field.getNodeType()==Node.ATTRIBUTE_NODE)
+ return field.getNodeValue();
+ else
+ throw new InvalidDataException("Don't know what to do with node "+field.getNodeName());
+ }
+
+ public void setFieldByXPath(String xpath, String data) throws XPathExpressionException, InvalidDataException {
+ Node field = getNodeByXPath(xpath);
+ if (field == null)
+ throw new InvalidDataException(xpath);
+
+ else if (field.getNodeType()==Node.ELEMENT_NODE) {
+ NodeList fieldChildren = field.getChildNodes();
+ if (fieldChildren.getLength() == 0) {
+ field.appendChild(dom.createTextNode(data));
+ }
+ else if (fieldChildren.getLength() == 1) {
+ Node child = fieldChildren.item(0);
+ switch (child.getNodeType()) {
+ case Node.TEXT_NODE:
+ case Node.CDATA_SECTION_NODE:
+ child.setNodeValue(data);
+ break;
+ default:
+ throw new InvalidDataException("Can't set child node of type "+child.getNodeName());
+ }
+ }
+ else
+ throw new InvalidDataException("Element "+xpath+" has too many children");
+ }
+ else if (field.getNodeType()==Node.ATTRIBUTE_NODE)
+ field.setNodeValue(data);
+ else
+ throw new InvalidDataException("Don't know what to do with node "+field.getNodeName());
+ }
+
+
+ public String getData() {
+ if (mData == null && dom != null) {
+ mData = serialize(dom, false);
+ }
+ return mData;
+ }
+
+ public Schema getSchema() throws ObjectNotFoundException {
+ return LocalObjectLoader.getSchema(mSchemaType, mSchemaVersion);
+ }
+
+ public void setSchemaType(String schemaType) {
+ mSchemaType = schemaType;
+ }
+
+ public String getSchemaType() {
+ return mSchemaType;
+ }
+
+ public int getSchemaVersion() {
+ return mSchemaVersion;
+ }
+
+ public void setSchemaVersion(int schVer) {
+ mSchemaVersion = schVer;
+ }
+
+ @Override
+ public String getClusterType() {
+ return ClusterStorage.OUTCOME;
+ }
+
+ // special script API methods
+
+ /**
+ * Parses the outcome into a DOM tree
+ * @return a DOM Document
+ */
+ public Document getDOM() {
+ if (dom == null)
+ try {
+ synchronized (parser) {
+ if (mData!=null)
+ dom = parser.parse(new InputSource(new StringReader(mData)));
+ else
+ dom = parser.newDocument();
+ }
+ } catch (Exception e) {
+ Logger.error(e);
+ return null;
+ }
+ return dom;
+ }
+
+ public String getField(String name) {
+ NodeList elements = getDOM().getDocumentElement().getElementsByTagName(name);
+ if (elements.getLength() == 1 && elements.item(0).hasChildNodes() && elements.item(0).getFirstChild() instanceof Text)
+ return ((Text)elements.item(0).getFirstChild()).getData();
+ else
+ return null;
+ }
+
+ public NodeList getNodesByXPath(String xpathExpr) throws XPathExpressionException {
+
+ XPathExpression expr = xpath.compile(xpathExpr);
+ return (NodeList)expr.evaluate(getDOM(), XPathConstants.NODESET);
+
+ }
+
+ public Node getNodeByXPath(String xpathExpr) throws XPathExpressionException {
+
+ XPathExpression expr = xpath.compile(xpathExpr);
+ return (Node)expr.evaluate(getDOM(), XPathConstants.NODE);
+
+ }
+
+ static public String serialize(Document doc, boolean prettyPrint)
+ {
+ LSSerializer writer = impl.createLSSerializer();
+ writer.getDomConfig().setParameter("format-pretty-print", prettyPrint);
+ writer.getDomConfig().setParameter("xml-declaration", false);
+ return writer.writeToString(doc);
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeInitiator.java b/src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeInitiator.java new file mode 100644 index 0000000..0a22fd0 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeInitiator.java @@ -0,0 +1,31 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.persistency.outcome;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.entity.agent.Job;
+
+
+public interface OutcomeInitiator {
+
+ public String initOutcome(Job job) throws InvalidDataException;
+
+}
diff --git a/src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeValidator.java b/src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeValidator.java new file mode 100644 index 0000000..fed0c8c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/outcome/OutcomeValidator.java @@ -0,0 +1,207 @@ +/**
+ * 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.persistency.outcome;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.apache.xerces.parsers.DOMParser;
+import org.apache.xerces.parsers.IntegratedParserConfiguration;
+import org.apache.xerces.parsers.XMLGrammarPreparser;
+import org.apache.xerces.util.SymbolTable;
+import org.apache.xerces.util.XMLGrammarPoolImpl;
+import org.apache.xerces.xni.XNIException;
+import org.apache.xerces.xni.grammars.XMLGrammarDescription;
+import org.apache.xerces.xni.parser.XMLErrorHandler;
+import org.apache.xerces.xni.parser.XMLInputSource;
+import org.apache.xerces.xni.parser.XMLParseException;
+import org.apache.xerces.xni.parser.XMLParserConfiguration;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.utils.Logger;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+
+/**************************************************************************
+ *
+ * $Revision: 1.24 $
+ * $Date: 2005/06/09 13:50:10 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+public class OutcomeValidator implements ErrorHandler, XMLErrorHandler {
+
+ protected static final String NAMESPACES_FEATURE_ID = "http://xml.org/sax/features/namespaces";
+ /** Validation feature id (http://xml.org/sax/features/validation). */
+ protected static final String VALIDATION_FEATURE_ID = "http://xml.org/sax/features/validation";
+ /** Schema validation feature id (http://apache.org/xml/features/validation/schema). */
+ protected static final String SCHEMA_VALIDATION_FEATURE_ID = "http://apache.org/xml/features/validation/schema";
+ /** Schema full checking feature id (http://apache.org/xml/features/validation/schema-full-checking). */
+ protected static final String SCHEMA_FULL_CHECKING_FEATURE_ID = "http://apache.org/xml/features/validation/schema-full-checking";
+ public static final String GRAMMAR_POOL = "http://apache.org/xml/properties/internal/grammar-pool";
+
+ static SchemaValidator schemaValid = new SchemaValidator();
+
+ Schema schema;
+ protected StringBuffer errors = null;
+ XMLGrammarPoolImpl schemaGrammarPool = new XMLGrammarPoolImpl(1);
+ SymbolTable sym = new SymbolTable();
+
+ public static OutcomeValidator getValidator(Schema schema) throws InvalidDataException {
+
+ if (schema.docType.equals("Schema") &&
+ schema.docVersion==0)
+ return schemaValid;
+
+ return new OutcomeValidator(schema);
+ }
+
+ protected OutcomeValidator() {
+ errors = new StringBuffer();
+ }
+
+ public OutcomeValidator(Schema schema) throws InvalidDataException {
+ this.schema = schema;
+
+ if (schema.docType.equals("Schema"))
+ throw new InvalidDataException("Use SchemaValidator to validate schema");
+
+ errors = new StringBuffer();
+ Logger.msg(5, "Parsing "+schema.docType+" version "+schema.docVersion+". "+schema.schema.length()+" chars");
+
+ XMLGrammarPreparser preparser = new XMLGrammarPreparser(sym);
+ preparser.registerPreparser(XMLGrammarDescription.XML_SCHEMA, null);
+ preparser.setProperty(GRAMMAR_POOL, schemaGrammarPool);
+
+ preparser.setFeature(NAMESPACES_FEATURE_ID, true);
+ preparser.setFeature(VALIDATION_FEATURE_ID, true);
+ preparser.setFeature(SCHEMA_VALIDATION_FEATURE_ID, true);
+ preparser.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, true);
+ preparser.setErrorHandler(this);
+ try {
+ preparser.preparseGrammar(XMLGrammarDescription.XML_SCHEMA, new XMLInputSource(null, null, null, new StringReader(schema.schema), null));
+ } catch (IOException ex) {
+ throw new InvalidDataException("Error parsing schema: "+ex.getMessage());
+ }
+
+ if (errors.length() > 0) {
+ throw new InvalidDataException("Schema error: \n"+errors.toString());
+ }
+
+ }
+
+ public synchronized String validate(Outcome outcome) {
+ if (outcome == null) return "Outcome object was null";
+ Logger.msg(5, "Validating outcome no "+outcome.getID()+" as "+schema.docType+" v"+schema.docVersion);
+ if (outcome.getSchemaType().equals(schema.docType)
+ && outcome.getSchemaVersion() == schema.docVersion) {
+ return validate(outcome.getData());
+ }
+ else
+ return "Outcome type and version did not match schema "+schema.docType;
+ }
+
+ public synchronized String validate(String outcome) {
+ if (outcome == null) return "Outcome String was null";
+ errors = new StringBuffer();
+ try {
+ XMLParserConfiguration parserConfiguration = new IntegratedParserConfiguration(sym, schemaGrammarPool);
+ parserConfiguration.setFeature(NAMESPACES_FEATURE_ID, true);
+ parserConfiguration.setFeature(VALIDATION_FEATURE_ID, true);
+ // now we can still do schema features just in case,
+ // so long as it's our configuraiton......
+ parserConfiguration.setFeature(SCHEMA_VALIDATION_FEATURE_ID, true);
+ parserConfiguration.setFeature(SCHEMA_FULL_CHECKING_FEATURE_ID, true);
+ DOMParser parser = new DOMParser(parserConfiguration);
+ parser.setErrorHandler(this);
+
+ parser.parse(new XMLInputSource(null, null, null, new StringReader(outcome), null));
+ } catch (Exception e) {
+ return e.getMessage();
+ }
+ return errors.toString();
+ }
+
+ private void appendError(String level, Exception ex) {
+ errors.append(level);
+ String message = ex.getMessage();
+ if (message == null || message.length()==0)
+ message = ex.getClass().getName();
+ errors.append(message);
+ errors.append("\n");
+ }
+
+ /**
+ * ErrorHandler for instances
+ */
+ @Override
+ public void error(SAXParseException ex) throws SAXException {
+ appendError("ERROR: ", ex);
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void fatalError(SAXParseException ex) throws SAXException {
+ appendError("FATAL: ", ex);
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void warning(SAXParseException ex) throws SAXException {
+ appendError("WARNING: ", ex);
+ }
+
+ /**
+ * XMLErrorHandler for schema
+ */
+ @Override
+ public void error(String domain, String key, XMLParseException ex)
+ throws XNIException {
+ appendError("ERROR: ", ex);
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void fatalError(String domain, String key, XMLParseException ex)
+ throws XNIException {
+ appendError("FATAL: ", ex);
+ }
+
+ /**
+ *
+ */
+ @Override
+ public void warning(String domain, String key, XMLParseException ex)
+ throws XNIException {
+ appendError("WARNING: ", ex);
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/persistency/outcome/Schema.java b/src/main/java/org/cristalise/kernel/persistency/outcome/Schema.java new file mode 100644 index 0000000..4ae6ef3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/outcome/Schema.java @@ -0,0 +1,73 @@ +/**
+ * 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.persistency.outcome;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.exolab.castor.xml.schema.reader.SchemaReader;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.InputSource;
+
+/**
+ * @author Andrew Branson
+ *
+ * $Revision: 1.3 $
+ * $Date: 2006/09/14 14:13:26 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ */
+
+public class Schema {
+ public String docType;
+ public int docVersion;
+ public String schema;
+ public org.exolab.castor.xml.schema.Schema som;
+
+ /**
+ * @param docType
+ * @param docVersion
+ * @param schema
+ */
+ public Schema(String docType, int docVersion, String schema) {
+ super();
+ this.docType = docType;
+ this.docVersion = docVersion;
+ this.schema = schema;
+ }
+
+ public Schema(String schema) {
+ this.schema = schema;
+ }
+
+ public org.exolab.castor.xml.schema.Schema parse(ErrorHandler errorHandler) throws IOException {
+ InputSource schemaSource = new InputSource(new StringReader(schema));
+ SchemaReader mySchemaReader = new SchemaReader(schemaSource);
+ if (errorHandler!= null) {
+ mySchemaReader.setErrorHandler(errorHandler);
+ mySchemaReader.setValidation(true);
+ }
+ som = mySchemaReader.read();
+ return som;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/persistency/outcome/SchemaValidator.java b/src/main/java/org/cristalise/kernel/persistency/outcome/SchemaValidator.java new file mode 100644 index 0000000..b9684d2 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/outcome/SchemaValidator.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.persistency.outcome;
+
+import java.io.IOException;
+
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2005/04/26 06:48:13 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+
+public class SchemaValidator extends OutcomeValidator {
+
+ public SchemaValidator() {
+
+ }
+
+ @Override
+ public synchronized String validate(String outcome) {
+ errors = new StringBuffer();
+ Schema schema = new Schema(outcome);
+ try {
+ schema.parse(this);
+ } catch (IOException e) {
+ errors.append(e.getMessage());
+ }
+ return errors.toString();
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/persistency/outcome/Viewpoint.java b/src/main/java/org/cristalise/kernel/persistency/outcome/Viewpoint.java new file mode 100644 index 0000000..630975a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/persistency/outcome/Viewpoint.java @@ -0,0 +1,191 @@ +/**
+ * 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.persistency.outcome;
+
+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.events.Event;
+import org.cristalise.kernel.lookup.InvalidItemPathException;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.Gateway;
+
+
+/**
+ * @author Andrew Branson
+ *
+ * $Revision: 1.10 $
+ * $Date: 2005/10/05 07:39:36 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ */
+
+public class Viewpoint implements C2KLocalObject {
+
+ // db fields
+ ItemPath itemPath;
+ String schemaName;
+ String name;
+ int schemaVersion;
+ int eventId;
+ public static final int NONE = -1;
+
+ public Viewpoint() {
+ eventId = NONE;
+ itemPath = null;
+ schemaVersion = NONE;
+ schemaName = null;
+ name = null;
+ }
+
+ public Viewpoint(ItemPath itemPath, String schemaName, String name, int schemaVersion, int eventId) {
+ this.itemPath = itemPath;
+ this.schemaName = schemaName;
+ this.name = name;
+ this.schemaVersion = schemaVersion;
+ this.eventId = eventId;
+ }
+
+ public Outcome getOutcome() throws ObjectNotFoundException, PersistencyException {
+ if (eventId == NONE) throw new ObjectNotFoundException("No last eventId defined");
+ Outcome retVal = (Outcome)Gateway.getStorage().get(itemPath, ClusterStorage.OUTCOME+"/"+schemaName+"/"+schemaVersion+"/"+eventId, null);
+ return retVal;
+ }
+
+ @Override
+ public String getClusterType() {
+ return ClusterStorage.VIEWPOINT;
+ }
+
+
+ /**
+ * Returns the eventId.
+ * @return int
+ */
+ public int getEventId() {
+ return eventId;
+ }
+
+ /**
+ * Returns the name.
+ * @return String
+ */
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * Returns the schemaName.
+ * @return String
+ */
+ public String getSchemaName() {
+ return schemaName;
+ }
+
+ /**
+ * Returns the schemaVersion.
+ * @return int
+ */
+ public int getSchemaVersion() {
+ return schemaVersion;
+ }
+
+ /**
+ * Returns the sysKey.
+ * @return int
+ */
+ public ItemPath getItemPath() {
+ return itemPath;
+ }
+
+ /**
+ * Sets the eventId.
+ * @param eventId The eventId to set
+ */
+ public void setEventId(int eventId) {
+ this.eventId = eventId;
+ }
+
+ /**
+ * Sets the name.
+ * @param name The name to set
+ */
+ @Override
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets the schemaName.
+ * @param schemaName The schemaName to set
+ */
+ public void setSchemaName(String schemaName) {
+ this.schemaName = schemaName;
+ }
+
+ /**
+ * Sets the schemaVersion.
+ * @param schemaVersion The schemaVersion to set
+ */
+ public void setSchemaVersion(int schemaVersion) {
+ this.schemaVersion = schemaVersion;
+ }
+
+ /**
+ * Sets the sysKey.
+ * @param sysKey The sysKey to set
+ */
+ public void setItemPath(ItemPath itemPath) {
+ this.itemPath = itemPath;
+ }
+
+ public void setItemUUID( String uuid ) throws InvalidItemPathException
+ {
+ setItemPath(new ItemPath(uuid));
+ }
+
+ public String getItemUUID() {
+ return getItemPath().getUUID().toString();
+ }
+
+ /**
+ * Method getEvent.
+ * @return GDataRecord
+ */
+ public Event getEvent()
+ throws InvalidDataException, PersistencyException, ObjectNotFoundException
+ {
+ if (eventId == NONE)
+ throw new InvalidDataException("No last eventId defined");
+
+ return (Event)Gateway.getStorage().get(itemPath, ClusterStorage.HISTORY+"/"+eventId, null);
+ }
+
+ @Override
+ public String toString() {
+ return name;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/process/AbstractMain.java b/src/main/java/org/cristalise/kernel/process/AbstractMain.java new file mode 100644 index 0000000..5acfbef --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/AbstractMain.java @@ -0,0 +1,178 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import org.cristalise.kernel.process.resource.BadArgumentsException;
+import org.cristalise.kernel.utils.FileStringUtility;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/25 15:27:35 $
+ * @version $Revision: 1.67 $
+ **************************************************************************/
+abstract public class AbstractMain
+{
+ public static boolean isServer = false;
+ private static ShutdownHandler shutdownHandler;
+
+ public static String MAIN_ARG_NONEWLOGSTREAM = "noNewLogStream";
+ public static String MAIN_ARG_CONFIG = "config";
+ public static String MAIN_ARG_LOGLEVEL = "logLevel";
+ public static String MAIN_ARG_LOGFILE = "logFile";
+ public static String MAIN_ARG_CONNECT = "connect";
+
+
+
+ /**************************************************************************
+ * reading and setting input paramaters
+ **************************************************************************
+ *
+ * Known arguments :
+ * <ul>
+ * <li>logLevel: the log level 0-9 (+10 to have time, +20 to have only one level)</li>
+ * <li>logFile: the full path of the target log file. if none, the Logstream is the stdOut</li>
+ * <li>noNewLogStream: if present no new Logstream is added to the logger (
+ * considers that the Logger is already configured)</li>
+ *
+ * <li>config</li>
+ * <li>connect</li>
+ * <li>LocalCentre</li>
+ * </ul>
+ *
+ *
+ * @param args
+ * @return
+ * @throws BadArgumentsException
+ */
+ public static Properties readC2KArgs( String[] args ) throws BadArgumentsException {
+ Properties c2kProps;
+ Properties argProps = new Properties();
+ int logLevel = 0;
+ PrintStream logStream = System.out;
+
+ int i = 0;
+ while( i < args.length ) {
+ if (args[i].startsWith("-") && args[i].length()>1) {
+ String key = args[i].substring(1);
+ if (argProps.containsKey(key))
+ throw new BadArgumentsException("Argument "+args[i]+" given twice");
+ String value = "";
+ if (!args[i+1].startsWith("-"))
+ value = args[++i];
+ argProps.put(key, value);
+ i++;
+ }
+ else
+ throw new BadArgumentsException("Bad argument: "+args[i]);
+
+ }
+
+ if (argProps.containsKey("logFile"))
+ try {
+ logStream = new PrintStream(new FileOutputStream(argProps.getProperty("logFile"), true));
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ throw new BadArgumentsException("Logfile "+argProps.getProperty("logFile")+" cannot be created");
+ }
+
+
+ // if the optional arg "noNewLogStream" isn't present => add a
+ // new LogStream
+ boolean wMustAddNewLogStream = !argProps.contains(MAIN_ARG_NONEWLOGSTREAM);
+ if (wMustAddNewLogStream) {
+
+ // Set up log stream
+ if (argProps.containsKey("logLevel"))
+ logLevel = Integer.parseInt(argProps.getProperty("logLevel"));
+
+ Logger.addLogStream(logStream, logLevel);
+ }
+ if (wMustAddNewLogStream) Logger.msg(
+ String.format("New logStream added at logLevel %d: %s", logLevel, logStream.getClass().getName()));
+
+
+ // Dump params if log high enough
+
+ if (Logger.doLog(3)) for (Enumeration<?> e = argProps.propertyNames(); e.hasMoreElements();) {
+ String next = (String)e.nextElement();
+ System.out.println("AbstractMain: Param "+next+": "+argProps.getProperty(next));
+ }
+
+ String configPath = argProps.getProperty("config");
+ if (configPath == null)
+ throw new BadArgumentsException("Config file not specified");
+
+ if (!new File(configPath).exists())
+ throw new BadArgumentsException("Config file "+configPath+" not found");
+ else
+ Logger.msg(0, "Config file: "+configPath);
+
+ // Load config & connect files into c2kprops
+ c2kProps = FileStringUtility.loadConfigFile(argProps.getProperty("config") );
+ c2kProps.putAll(argProps); // args overlap config
+
+ String connectFile = c2kProps.getProperty("connect");
+ if (connectFile == null)
+ throw new BadArgumentsException("Connect file not specified");
+
+ if (!new File(connectFile).exists())
+ throw new BadArgumentsException("Connect file "+connectFile+" not found");
+ else
+ Logger.msg(0, "Connect file: "+connectFile);
+
+ FileStringUtility.appendConfigFile( c2kProps, connectFile);
+
+ if (!c2kProps.containsKey("LocalCentre")) {
+ String connectFileName = new File(connectFile).getName();
+ String centreId = connectFileName.substring(0, connectFileName.lastIndexOf(".clc"));
+ c2kProps.setProperty("LocalCentre", centreId);
+ }
+
+ c2kProps.putAll(argProps); // args override connect file too
+ Logger.msg(7, "AbstractMain::standardSetUp() - readC2KArgs() DONE.");
+
+ return c2kProps;
+ }
+
+ public static void setShutdownHandler(ShutdownHandler handler) {
+ shutdownHandler = handler;
+ }
+
+ public static void shutdown(int errCode) {
+ if (shutdownHandler!= null)
+ shutdownHandler.shutdown(errCode, isServer);
+ else
+ try {
+ Gateway.close();
+ } catch (Exception ex) {
+ Logger.error(ex);
+ }
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/process/Bootstrap.java b/src/main/java/org/cristalise/kernel/process/Bootstrap.java new file mode 100644 index 0000000..8934cd8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/Bootstrap.java @@ -0,0 +1,394 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process;
+
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.UUID;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.entity.proxy.AgentProxy;
+import org.cristalise.kernel.entity.proxy.ItemProxy;
+import org.cristalise.kernel.events.Event;
+import org.cristalise.kernel.events.History;
+import org.cristalise.kernel.lifecycle.CompositeActivityDef;
+import org.cristalise.kernel.lifecycle.instance.CompositeActivity;
+import org.cristalise.kernel.lifecycle.instance.Workflow;
+import org.cristalise.kernel.lifecycle.instance.predefined.server.ServerPredefinedStepContainer;
+import org.cristalise.kernel.lifecycle.instance.stateMachine.Transition;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.DomainPath;
+import org.cristalise.kernel.lookup.InvalidItemPathException;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.lookup.LookupManager;
+import org.cristalise.kernel.lookup.Path;
+import org.cristalise.kernel.lookup.RolePath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.persistency.outcome.Outcome;
+import org.cristalise.kernel.persistency.outcome.OutcomeValidator;
+import org.cristalise.kernel.persistency.outcome.Viewpoint;
+import org.cristalise.kernel.process.resource.DefaultResourceImportHandler;
+import org.cristalise.kernel.process.resource.ResourceImportHandler;
+import org.cristalise.kernel.property.Property;
+import org.cristalise.kernel.property.PropertyArrayList;
+import org.cristalise.kernel.property.PropertyDescription;
+import org.cristalise.kernel.property.PropertyDescriptionList;
+import org.cristalise.kernel.utils.FileStringUtility;
+import org.cristalise.kernel.utils.LocalObjectLoader;
+import org.cristalise.kernel.utils.Logger;
+import org.custommonkey.xmlunit.Diff;
+import org.custommonkey.xmlunit.XMLUnit;
+
+
+/**
+ * @version $Revision: 1.25 $ $Date: 2006/01/10 09:48:32 $
+ * @author $Author: abranson $
+ */
+
+public class Bootstrap
+{
+ static DomainPath thisServerPath;
+ static HashMap<String, ResourceImportHandler> resHandlerCache = new HashMap<String, ResourceImportHandler>();
+ static HashMap<String, AgentProxy> systemAgents = new HashMap<String, AgentProxy>();
+
+ /**
+ * Run everything without timing-out the service wrapper
+ */
+ public static void run() throws Exception {
+ // check for system agents
+ checkAdminAgents();
+
+ // create the server's mother item
+ createServerItem();
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Thread.currentThread().setName("Bootstrapper");
+
+ ClassLoader wClassLoader = Bootstrap.class.getClassLoader();
+ Logger.msg(String.format("Bootstrap.run() setContextClassLoader=[%s]",wClassLoader));
+ Thread.currentThread().setContextClassLoader(wClassLoader);
+
+ // make sure all of the boot items are up-to-date
+ Logger.msg("Bootstrap.run() - Verifying kernel boot data items");
+ verifyBootDataItems();
+
+ // verify the server item's wf
+ Logger.msg("Bootstrap.run() - Initialising Server Item Workflow");
+ initServerItemWf();
+
+ Gateway.getModuleManager().setUser(systemAgents.get("system"));
+ Gateway.getModuleManager().registerModules();
+
+ Logger.msg("Bootstrap.run() - Bootstrapping complete");
+ } catch (Throwable e) {
+ Logger.error(e);
+ Logger.die("Exception performing bootstrap. Check that everything is OK.");
+ }
+ }
+ }).start();
+ }
+
+ /**************************************************************************
+ * Checks all kernel descriptions, stored in resources
+ **************************************************************************/
+ public static void verifyBootDataItems() throws Exception {
+ String bootItems;
+ Logger.msg(1, "Verifying kernel boot items");
+ bootItems = FileStringUtility.url2String(Gateway.getResource().getKernelResourceURL("boot/allbootitems.txt"));
+ verifyBootDataItems(bootItems, null, true);
+ Logger.msg(1, "Boot data items complete");
+ }
+
+ private static void verifyBootDataItems(String bootList, String ns, boolean reset) throws InvalidItemPathException {
+ StringTokenizer str = new StringTokenizer(bootList, "\n\r");
+ while (str.hasMoreTokens()) {
+ String thisItem = str.nextToken();
+ ItemPath itemPath = null;
+ String[] itemParts = thisItem.split("/");
+ if (itemParts.length == 3) { // includes UUID
+ itemPath = new ItemPath(itemParts[2]);
+ }
+ String itemType = itemParts[0];
+ String itemName = itemParts[1];
+ try {
+ String location = "boot/"+thisItem+(itemType.equals("OD")?".xsd":".xml");
+ verifyResource(ns, itemName, 0, itemType, itemPath, location, reset);
+ } catch (Exception e) {
+ Logger.error(e);
+ Logger.die("Error importing bootstrap items. Unsafe to continue.");
+ }
+ }
+ }
+
+ public static DomainPath verifyResource(String ns, String itemName, int version, String itemType, ItemPath itemPath, String dataLocation, boolean reset) throws Exception {
+ LookupManager lookupManager = Gateway.getLookupManager();
+ ResourceImportHandler typeImpHandler = getHandler(itemType);
+ Logger.msg(1, "Bootstrap.verifyResource() - Verifying version "+version+" of "+typeImpHandler.getName()+" "+itemName);
+
+ // Find or create Item for Resource
+ DomainPath modDomPath = typeImpHandler.getPath(itemName, ns);
+ ItemProxy thisProxy;
+ Iterator<Path> en = Gateway.getLookup().search(typeImpHandler.getTypeRoot(), itemName);
+ if (!en.hasNext()) {
+ if (itemPath == null) itemPath = new ItemPath();
+ Logger.msg("Bootstrap.verifyResource() - "+typeImpHandler.getName()+" "+itemName+" not found. Creating new.");
+ thisProxy = createResourceItem(typeImpHandler, itemName, ns, itemPath);
+ }
+ else {
+ DomainPath path = (DomainPath)en.next();
+ thisProxy = Gateway.getProxyManager().getProxy(path);
+ if (itemPath != null && !path.getItemPath().equals(itemPath)) {
+ Logger.warning("Resource "+itemType+"/"+itemName+" should have path "+itemPath+" but was found with path "+path.getItemPath());
+ itemPath = path.getItemPath();
+ }
+ if (itemPath == null) itemPath = path.getItemPath();
+ // Verify module property and location
+
+ String moduleName = (ns==null?"kernel":ns);
+ String itemModule;
+ try{
+ itemModule = thisProxy.getProperty("Module");
+ if (!itemModule.equals("") && !itemModule.equals("null") && !moduleName.equals(itemModule)) {
+ Logger.error("Bootstrap.verifyResource() - Module clash! Resource '"+itemName+"' included in module "+moduleName+" but is assigned to '"+itemModule+"'. Not overwriting.");
+ return path;
+ }
+ } catch (ObjectNotFoundException ex) {
+ itemModule = "";
+ }
+
+ if (!moduleName.equals(itemModule)) { // write module property
+ Gateway.getStorage().put(itemPath, new Property("Module", moduleName, false), thisProxy);
+ }
+
+ if (!modDomPath.equals(path)) { // move item to module subtree
+ Logger.msg("Module item "+itemName+" found with path "+path.toString()+". Moving to "+modDomPath.toString());
+ modDomPath.setItemPath(itemPath);
+ if (!modDomPath.exists())
+ lookupManager.add(modDomPath);
+ lookupManager.delete(path);
+ }
+ }
+
+ // Verify/Import Outcomes, creating events and views as necessary
+ Set<Outcome> impList = typeImpHandler.getResourceOutcomes(itemName, ns, dataLocation, version);
+ for (Outcome newOutcome : impList) {
+ try {
+ Viewpoint currentData = (Viewpoint)thisProxy.getObject(ClusterStorage.VIEWPOINT+"/"+newOutcome.getSchemaType()+"/"+version);
+ Outcome oldData = currentData.getOutcome();
+ XMLUnit.setIgnoreWhitespace(true);
+ XMLUnit.setIgnoreComments(true);
+ Diff xmlDiff = new Diff(newOutcome.getDOM(), oldData.getDOM());
+ if (xmlDiff.identical()) {
+ Logger.msg(5, "Bootstrap.verifyResource() - Data identical, no update required");
+ continue;
+ }
+ else {
+ Logger.msg("Difference found in "+itemName+": "+xmlDiff.toString());
+ if (!reset && !currentData.getEvent().getStepPath().equals("Bootstrap")) {
+ Logger.msg("Version "+version+" was not set by Bootstrap, and reset not requested. Not overwriting.");
+ continue;
+ }
+ }
+
+ } catch (ObjectNotFoundException ex) {
+ Logger.msg("Bootstrap.verifyResource() - Item "+itemName+" exists but version "+version+" not found! Attempting to insert new.");
+ }
+
+ // data was missing or doesn't match
+ // validate it (but not for kernel objects because we need those to validate the rest)
+ if (ns!= null) {
+ OutcomeValidator validator = OutcomeValidator.getValidator(LocalObjectLoader.getSchema(newOutcome.getSchemaType(), newOutcome.getSchemaVersion()));
+ String error = validator.validate(newOutcome.getData());
+ if (error.length() > 0) {
+ Logger.error("Outcome not valid: \n " + error);
+ throw new InvalidDataException(error);
+ }
+ }
+
+ // store
+ Logger.msg("Bootstrap.verifyResource() - Writing new "+newOutcome.getSchemaType()+" v"+version+" to "+typeImpHandler.getName()+" "+itemName);
+ History hist = new History(itemPath, thisProxy);
+ Transition predefDone = new Transition(0, "Done", 0, 0);
+ Event newEvent = hist.addEvent(systemAgents.get("system").getPath(), "Admin", "Bootstrap", "Bootstrap", "Bootstrap", newOutcome.getSchemaType(), 0, "PredefinedStep", 0, predefDone, String.valueOf(version));
+ newOutcome.setID(newEvent.getID());
+ Viewpoint newLastView = new Viewpoint(itemPath, newOutcome.getSchemaType(), "last", 0, newEvent.getID());
+ Viewpoint newNumberView = new Viewpoint(itemPath, newOutcome.getSchemaType(), String.valueOf(version), 0, newEvent.getID());
+ Gateway.getStorage().put(itemPath, newOutcome, thisProxy);
+ Gateway.getStorage().put(itemPath, newLastView, thisProxy);
+ Gateway.getStorage().put(itemPath, newNumberView, thisProxy);
+ }
+ Gateway.getStorage().commit(thisProxy);
+ return modDomPath;
+ }
+
+ private static ResourceImportHandler getHandler(String resType) throws Exception {
+ if (resHandlerCache.containsKey(resType))
+ return resHandlerCache.get(resType);
+ ResourceImportHandler handler = null;
+ if (Gateway.getProperties().containsKey("ResourceImportHandler."+resType)) {
+ try {
+ handler = (ResourceImportHandler) Gateway.getProperties().getInstance("ResourceImportHandler."+resType);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ Logger.error("Exception loading ResourceHandler for "+resType+". Using default.");
+ }
+ }
+
+ if (handler == null)
+ handler = new DefaultResourceImportHandler(resType);
+
+ resHandlerCache.put(resType, handler);
+ return handler;
+ }
+
+ /**
+ * @param itemType
+ * @param itemName
+ * @param data
+ */
+ private static ItemProxy createResourceItem(ResourceImportHandler impHandler, String itemName, String ns, ItemPath itemPath) throws Exception {
+ // create props
+ PropertyDescriptionList pdList = impHandler.getPropDesc();
+ PropertyArrayList props = new PropertyArrayList();
+ LookupManager lookupManager = Gateway.getLookupManager();
+
+ for (int i = 0; i < pdList.list.size(); i++) {
+ PropertyDescription pd = pdList.list.get(i);
+ String propName = pd.getName();
+ String propVal = propName.equals("Name")?itemName:pd.getDefaultValue();
+ props.list.add(new Property(propName, propVal, pd.getIsMutable()));
+ }
+
+ CompositeActivity ca = new CompositeActivity();
+ if (ns!=null && Gateway.getProperties().getBoolean("Module.debug", false))
+ try {
+ ca = (CompositeActivity) ((CompositeActivityDef)LocalObjectLoader.getActDef(impHandler.getWorkflowName(), 0)).instantiate();
+ } catch (ObjectNotFoundException ex) {
+ Logger.error("Module resource workflow "+impHandler.getWorkflowName()+" not found. Using empty.");
+ }
+
+
+ Gateway.getCorbaServer().createItem(itemPath);
+ lookupManager.add(itemPath);
+ DomainPath newDomPath = impHandler.getPath(itemName, ns);
+ newDomPath.setItemPath(itemPath);
+ lookupManager.add(newDomPath);
+ ItemProxy newItemProxy = Gateway.getProxyManager().getProxy(itemPath);
+ newItemProxy.initialise( systemAgents.get("system").getPath(), props, ca, null);
+ return newItemProxy;
+ }
+
+ /**************************************************************************
+ * Checks for the existence of the admin users so you can use Cristal
+ **************************************************************************/
+ private static void checkAgent(String name, String pass, RolePath rolePath, String uuid) throws Exception {
+ Logger.msg(1, "Bootstrap.checkAgent() - Checking for existence of '"+name+"' user.");
+ LookupManager lookup = Gateway.getLookupManager();
+
+ try {
+ systemAgents.put(name, Gateway.getProxyManager().getAgentProxy(lookup.getAgentPath(name)));
+ Logger.msg(3, "Bootstrap.checkAgent() - User '"+name+"' found.");
+ return;
+ } catch (ObjectNotFoundException ex) { }
+
+ Logger.msg("Bootstrap.checkAgent() - User '"+name+"' not found. Creating.");
+
+ try {
+ AgentPath agentPath = new AgentPath(new ItemPath(uuid), name);
+ agentPath.setPassword(pass);
+ Gateway.getCorbaServer().createAgent(agentPath);
+ lookup.add(agentPath);
+
+ // assign admin role
+ Logger.msg("Bootstrap.checkAgent() - Assigning role '"+rolePath.getName()+"'");
+ Gateway.getLookupManager().addRole(agentPath, rolePath);
+ Gateway.getStorage().put(agentPath, new Property("Name", name, true), null);
+ Gateway.getStorage().put(agentPath, new Property("Type", "Agent", false), null);
+ systemAgents.put(name, Gateway.getProxyManager().getAgentProxy(agentPath));
+ } catch (Exception ex) {
+ Logger.error("Unable to create "+name+" user.");
+ throw ex;
+ }
+ }
+
+ /**
+ *
+ */
+ public static void checkAdminAgents() throws Exception {
+
+ // check for administrative user & admin role
+ String adminPassword = Gateway.getProperties().getString("AdminPassword", "admin12345");
+ RolePath rootRole = new RolePath();
+ if (!rootRole.exists()) Gateway.getLookupManager().createRole(rootRole);
+ RolePath adminRole = new RolePath(rootRole, "Admin", false);
+ if (!adminRole.exists()) Gateway.getLookupManager().createRole(adminRole);
+
+ // check for import user
+ checkAgent("system", adminPassword, adminRole, new UUID(0, 0).toString());
+
+ checkAgent("admin", adminPassword, adminRole, new UUID(0, 1).toString());
+
+ // check for local usercode user & role
+ RolePath usercodeRole = new RolePath(rootRole, "UserCode", true);
+ if (!usercodeRole.exists()) Gateway.getLookupManager().createRole(usercodeRole);
+ checkAgent(InetAddress.getLocalHost().getHostName(), "uc", usercodeRole, UUID.randomUUID().toString());
+ }
+
+ public static void createServerItem() throws Exception {
+ LookupManager lookupManager = Gateway.getLookupManager();
+ String serverName = Gateway.getProperties().getString("ItemServer.name", InetAddress.getLocalHost().getHostName());
+ thisServerPath = new DomainPath("/servers/"+serverName);
+ ItemPath serverEntity;
+ try {
+ serverEntity = thisServerPath.getItemPath();
+ } catch (ObjectNotFoundException ex) {
+ Logger.msg("Creating server item "+thisServerPath);
+ serverEntity = new ItemPath();
+ Gateway.getCorbaServer().createItem(serverEntity);
+ lookupManager.add(serverEntity);
+ thisServerPath.setItemPath(serverEntity);
+ lookupManager.add(thisServerPath);
+ }
+ Gateway.getStorage().put(serverEntity, new Property("Name", serverName, false), null);
+ Gateway.getStorage().put(serverEntity, new Property("Type", "Server", false), null);
+ Gateway.getStorage().put(serverEntity, new Property("KernelVersion", Gateway.getKernelVersion(), true), null);
+ int proxyPort = Gateway.getProperties().getInt("ItemServer.Proxy.port", 1553);
+ Gateway.getStorage().put(serverEntity,
+ new Property("ProxyPort", String.valueOf(proxyPort), false), null);
+ Gateway.getStorage().put(serverEntity,
+ new Property("ConsolePort", String.valueOf(Logger.getConsolePort()), true), null);
+ Gateway.getProxyManager().connectToProxyServer(serverName, proxyPort);
+
+ }
+
+ public static void initServerItemWf() throws Exception {
+ CompositeActivityDef serverWfCa = (CompositeActivityDef)LocalObjectLoader.getActDef("ServerItemWorkflow", 0);
+ Workflow wf = new Workflow((CompositeActivity)serverWfCa.instantiate(), new ServerPredefinedStepContainer());
+ wf.initialise(thisServerPath.getItemPath(), systemAgents.get("system").getPath());
+ Gateway.getStorage().put(thisServerPath.getItemPath(), wf, null);
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/process/ClientShell.java b/src/main/java/org/cristalise/kernel/process/ClientShell.java new file mode 100644 index 0000000..0a9ad83 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/ClientShell.java @@ -0,0 +1,71 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process;
+
+import java.util.Scanner;
+
+import org.cristalise.kernel.entity.proxy.AgentProxy;
+import org.cristalise.kernel.process.auth.ProxyLogin;
+import org.cristalise.kernel.scripting.Script;
+import org.cristalise.kernel.scripting.ScriptParsingException;
+
+
+public class ClientShell extends StandardClient {
+
+ AgentProxy user;
+ Script console;
+
+ public ClientShell(AgentProxy user) throws Exception {
+ this.user = user;
+ console = new Script("javascript", user, System.out);
+ }
+
+ public void run() {
+ Scanner scan = new Scanner(System.in);
+ System.out.print("> ");
+ while (scan.hasNextLine()) {
+ String command = scan.nextLine();
+ try {
+ console.setScript(command);
+ Object response = console.execute();
+ if (response == null)
+ System.out.println("Ok");
+ else
+ System.out.println(response);
+ } catch (ScriptParsingException e) {
+ System.err.println("Syntax error: "+e.getMessage());
+ } catch (Throwable ex) {
+ ex.printStackTrace();
+ }
+ System.out.print("> ");
+ }
+ shutdown(0);
+ }
+
+ public static void main(String[] args) throws Exception {
+ Gateway.init(readC2KArgs(args));
+ ProxyLogin auth = (ProxyLogin)Gateway.getProperties().getInstance("cli.auth");
+ AgentProxy user = auth.authenticate(Gateway.getProperties().getProperty("Name"));
+ ClientShell shell = new ClientShell(user);
+ shell.run();
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/process/Gateway.java b/src/main/java/org/cristalise/kernel/process/Gateway.java new file mode 100644 index 0000000..c7936c3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/Gateway.java @@ -0,0 +1,426 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process;
+
+/**
+ * @version $Revision: 1.17 $ $Date: 2005/10/12 12:51:54 $
+ * @author $Author: abranson $
+ */
+
+import java.net.MalformedURLException;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.CorbaServer;
+import org.cristalise.kernel.entity.proxy.AgentProxy;
+import org.cristalise.kernel.entity.proxy.ProxyManager;
+import org.cristalise.kernel.entity.proxy.ProxyServer;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.Lookup;
+import org.cristalise.kernel.lookup.LookupManager;
+import org.cristalise.kernel.persistency.TransactionManager;
+import org.cristalise.kernel.process.auth.Authenticator;
+import org.cristalise.kernel.process.module.ModuleManager;
+import org.cristalise.kernel.process.resource.Resource;
+import org.cristalise.kernel.process.resource.ResourceLoader;
+import org.cristalise.kernel.utils.CastorXMLUtility;
+import org.cristalise.kernel.utils.FileStringUtility;
+import org.cristalise.kernel.utils.Language;
+import org.cristalise.kernel.utils.Logger;
+import org.cristalise.kernel.utils.ObjectProperties;
+
+
+
+/**************************************************************************
+ * The Gateway is the central object of a CRISTAL process. It initializes,
+ * maintains and shuts down every other subsystem in both the client and the
+ * server.
+ *
+ * Child objects:
+ * <ul>
+ * <li>Lookup - Provides access to the CRISTAL directory. Find or
+ * search for Items or Agents.
+ * <li>EntityProxyManager - Gives a local proxy object for Entities found
+ * in LDAP. Execute activities in Items, query or subscribe to Entity data.
+ * <li>TransactionManager - Access to the configured CRISTAL databases
+ * <li>CorbaServer - Manages the memory pool of active Entities
+ * <li>mORB - the Orbacus CORBA ORB
+ * </ul>
+ *
+ * @author $Author: abranson $ $Date: 2005/10/12 12:51:54 $
+ * @version $Revision: 1.17 $
+ **************************************************************************/
+
+public class Gateway
+{
+ static private ObjectProperties mC2KProps = new ObjectProperties();
+ static private ModuleManager mModules;
+ static private org.omg.CORBA.ORB mORB;
+ static private boolean orbDestroyed = false;
+ static private Lookup mLookup;
+ static private LookupManager mLookupManager = null;
+ static private TransactionManager mStorage;
+ static private ProxyManager mProxyManager;
+ static private ProxyServer mProxyServer;
+ static private CorbaServer mCorbaServer;
+ static private CastorXMLUtility mMarshaller;
+ static private ResourceLoader mResource;
+
+
+
+ private Gateway() { }
+
+ /**
+ * Initialises the Gateway and all of the client objects it holds, with
+ * the exception of the Lookup, which is initialised during connect()
+ *
+ * @param props - java.util.Properties containing all application properties.
+ * If null, the java system properties are used
+ * @throws InvalidDataException - invalid properties caused a failure in initialisation
+ */
+ static public void init(Properties props) throws InvalidDataException {
+ init(props, null);
+ }
+
+ /**
+ * Initialises the Gateway and all of the client objects it holds, with
+ * the exception of the Lookup, which is initialised during connect()
+ *
+ * @param props - java.util.Properties containing all application properties.
+ * If null, the java system properties are used
+ * @param res - ResourceLoader for the kernel to use to resolve all class resource requests
+ * such as for bootstrap descriptions and version information
+ * @throws InvalidDataException - invalid properties caused a failure in initialisation
+ */
+ static public void init(Properties props, ResourceLoader res) throws InvalidDataException {
+
+ // Init properties & resources
+ mC2KProps.clear();
+
+ orbDestroyed = false;
+ mResource = res;
+ if (mResource == null) mResource = new Resource();
+
+ // report version info
+ Logger.msg("Kernel version: "+getKernelVersion());
+
+ // load kernel mapfiles giving the resourse loader and the properties of
+ // the application to be able to configure castor
+ try {
+ mMarshaller = new CastorXMLUtility(mResource, props, mResource.getKernelResourceURL("mapFiles/"));
+ } catch (MalformedURLException e1) {
+ throw new InvalidDataException("Invalid Resource Location");
+ }
+
+
+ // init module manager
+ try {
+ mModules = new ModuleManager(mResource.getModuleDefURLs(), AbstractMain.isServer);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new InvalidDataException("Could not load module definitions.");
+ }
+
+ // merge in module props
+ Properties moduleProperties = mModules.getAllModuleProperties();
+ for (Enumeration<?> e = moduleProperties.propertyNames(); e.hasMoreElements();) {
+ String propName = (String)e.nextElement();
+ mC2KProps.put(propName, moduleProperties.get(propName));
+ }
+
+ // Overwrite with argument props
+ if (props != null) mC2KProps.putAll(props);
+
+ // dump properties
+ dumpC2KProps(7);
+
+ //Initialise language file
+ String languageFile = getProperties().getString("language.file");
+ if (languageFile != null && languageFile.length() > 0) {
+ Language.isTranlated=true;
+ Language.mTableOfTranslation = FileStringUtility.loadLanguageFile(languageFile);
+ }
+ }
+
+ /**
+ * Makes this process capable of creating and managing server entities. Runs the
+ * bootstrap to create the root LDAP contexts, initialises the CORBA server and
+ * time-out manager.
+ *
+ * @throws InvalidDataException - error initialising
+ */
+ static public void startServer(Authenticator auth) throws InvalidDataException, CannotManageException {
+ try {
+ // check top level directory contexts
+ if (mLookup instanceof LookupManager) {
+ mLookupManager = (LookupManager)mLookup;
+ mLookupManager.initializeDirectory();
+ }
+ else {
+ throw new CannotManageException("Lookup implementation is not a LookupManager. Cannot write to directory");
+ }
+
+ // start entity proxy server
+ mProxyServer = new ProxyServer(mC2KProps.getProperty("ItemServer.name"));
+
+ // Init ORB - set various config
+ String serverName = mC2KProps.getProperty("ItemServer.name");
+ if (serverName != null)
+ mC2KProps.put("com.sun.CORBA.ORBServerHost", serverName);
+ String serverPort = mC2KProps.getProperty("ItemServer.iiop", "1500");
+ mC2KProps.put("com.sun.CORBA.ORBServerPort", serverPort);
+ //TODO: externalize this (or replace corba completely)
+ mC2KProps.put("com.sun.CORBA.POA.ORBServerId", "1");
+ mC2KProps.put("com.sun.CORBA.POA.ORBPersistentServerPort", serverPort);
+ mC2KProps.put("com.sun.CORBA.codeset.charsets", "0x05010001, 0x00010109"); // need to force UTF-8 in the Sun ORB
+ mC2KProps.put("com.sun.CORBA.codeset.wcharsets", "0x00010109, 0x05010001");
+ //Standard initialisation of the ORB
+ orbDestroyed = false;
+ mORB = org.omg.CORBA.ORB.init(new String[0], mC2KProps);
+
+ Logger.msg("Gateway.init() - ORB initialised. ORB is " + mORB.getClass().getName() );
+
+ // start corba server components
+ mCorbaServer = new CorbaServer();
+
+ // start checking bootstrap & module items
+ Bootstrap.run();
+ System.out.println("Server '"+serverName+"' initialised.");
+ } catch (Exception ex) {
+ Logger.error(ex);
+ Logger.die("Exception starting server components. Shutting down.");
+ }
+
+ }
+
+ public static ModuleManager getModuleManager() {
+ return mModules;
+ }
+
+ /**
+ * Connects to the LDAP server in an administrative context - using the admin username and
+ * password given in the LDAP.user and LDAP.password props of the kernel properties.
+ *
+ * @throws InvalidDataException - bad params
+ * @throws PersistencyException - error starting storages
+ */
+ static public Authenticator connect()
+ throws InvalidDataException,
+ PersistencyException
+ {
+ try {
+ Authenticator auth = (Authenticator)mC2KProps.getInstance("Authenticator");
+ auth.authenticate("System");
+
+ mLookup = (Lookup)mC2KProps.getInstance("Lookup");
+ mLookup.open(auth);
+
+ mStorage = new TransactionManager(auth);
+ mProxyManager = new ProxyManager();
+
+ return auth;
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new InvalidDataException("Cannot connect server process. Please check config.");
+ }
+
+
+ }
+
+ /**
+ * Logs in with the given username and password, and initialises the lookup, storage and proxy manager.
+ *
+ * @param agentName - username
+ * @param agentPassword - password
+ * @return an AgentProxy on the requested user
+ * @throws InvalidDataException
+ * @throws PersistencyException
+ * @throws ClassNotFoundException
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ */
+ static public AgentProxy connect(String agentName, String agentPassword, String resource)
+ throws InvalidDataException, ObjectNotFoundException, PersistencyException, InstantiationException, IllegalAccessException, ClassNotFoundException
+ {
+ Authenticator auth = (Authenticator)mC2KProps.getInstance("Authenticator");
+ if (!auth.authenticate(agentName, agentPassword, resource))
+ throw new InvalidDataException("Login failed");
+
+ mLookup = (Lookup)mC2KProps.getInstance("Lookup");
+ mLookup.open(auth);
+
+ mStorage = new TransactionManager(auth);
+ mProxyManager = new ProxyManager();
+
+ // find agent proxy
+ AgentPath agentPath = mLookup.getAgentPath(agentName);
+ AgentProxy userProxy = (AgentProxy) mProxyManager.getProxy(agentPath);
+ userProxy.setAuthObj(auth);
+
+ // Run module startup scripts. Server does this during bootstrap
+ mModules.setUser(userProxy);
+ mModules.runScripts("startup");
+
+ return userProxy;
+ }
+
+ static public AgentProxy connect(String agentName, String agentPassword)
+ throws InvalidDataException, ObjectNotFoundException, PersistencyException, InstantiationException, IllegalAccessException, ClassNotFoundException
+ {
+ return connect(agentName, agentPassword, null);
+ }
+
+ /**
+ * Shuts down all kernel api objects
+ */
+ public static void close()
+ {
+ // run shutdown module scripts
+ if (mModules != null)
+ mModules.runScripts("shutdown");
+
+ // shut down servers if running
+ if (mCorbaServer != null)
+ mCorbaServer.close();
+ mCorbaServer = null;
+
+ // disconnect from storages
+ if (mStorage != null)
+ mStorage.close();
+ mStorage = null;
+
+ // disconnect from ldap
+ if (mLookup != null)
+ mLookup.close();
+ mLookup = null;
+ mLookupManager = null;
+
+ // shut down proxy manager & server
+ if (mProxyManager != null)
+ mProxyManager.shutdown();
+ if (mProxyServer != null)
+ mProxyServer.shutdownServer();
+ mProxyManager = null;
+ mProxyServer = null;
+
+ // close log consoles
+ Logger.closeConsole();
+
+ // finally, destroy the ORB
+ if (!orbDestroyed) {
+ getORB().destroy();
+ orbDestroyed = true;
+ mORB = null;
+ }
+
+ // clean up remaining objects
+ mModules = null;
+ mResource = null;
+ mMarshaller = null;
+ mC2KProps.clear();
+ }
+
+ static public org.omg.CORBA.ORB getORB()
+ {
+ if (orbDestroyed) throw new RuntimeException("Gateway has been closed. ORB is destroyed. ");
+
+ if (mORB == null) {
+ mC2KProps.put("com.sun.CORBA.codeset.charsets", "0x05010001, 0x00010109"); // need to force UTF-8 in the Sun ORB
+ mC2KProps.put("com.sun.CORBA.codeset.wcharsets", "0x00010109, 0x05010001");
+ mORB = org.omg.CORBA.ORB.init(new String[0], mC2KProps);
+ }
+ return mORB;
+ }
+
+ static public Lookup getLookup()
+ {
+ return mLookup;
+ }
+
+ static public LookupManager getLookupManager() throws CannotManageException
+ {
+ if (mLookupManager == null)
+ throw new CannotManageException("No Lookup Manager created. Not a server process.");
+ else
+ return mLookupManager;
+ }
+
+ static public CorbaServer getCorbaServer()
+ {
+ return mCorbaServer;
+ }
+
+ static public TransactionManager getStorage()
+ {
+ return mStorage;
+ }
+
+ static public CastorXMLUtility getMarshaller()
+ {
+ return mMarshaller;
+ }
+
+ static public ResourceLoader getResource()
+ {
+ return mResource;
+ }
+
+ static public ProxyManager getProxyManager()
+ {
+ return mProxyManager;
+ }
+
+
+ public static ProxyServer getProxyServer() {
+ return mProxyServer;
+ }
+
+ static public String getCentreId() {
+ return getProperties().getString("LocalCentre");
+ }
+
+ static public Enumeration<?> propertyNames() {
+ return mC2KProps.propertyNames();
+ }
+
+ static public void dumpC2KProps(int logLevel) {
+ if (!Logger.doLog(logLevel)) return;
+ mC2KProps.dumpProps(logLevel);
+ }
+
+ static public ObjectProperties getProperties() {
+ return mC2KProps;
+ }
+
+ static public String getKernelVersion() {
+ try {
+ return mResource.getTextResource(null, "textFiles/version.txt");
+ } catch (Exception ex) {
+ return "No version info found";
+ }
+
+ }
+}
+
diff --git a/src/main/java/org/cristalise/kernel/process/ShutdownHandler.java b/src/main/java/org/cristalise/kernel/process/ShutdownHandler.java new file mode 100644 index 0000000..f34800d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/ShutdownHandler.java @@ -0,0 +1,26 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process;
+
+public interface ShutdownHandler {
+
+ public void shutdown(int errCode, boolean isServer);
+}
diff --git a/src/main/java/org/cristalise/kernel/process/StandardClient.java b/src/main/java/org/cristalise/kernel/process/StandardClient.java new file mode 100644 index 0000000..c97fed0 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/StandardClient.java @@ -0,0 +1,31 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process;
+
+
+abstract public class StandardClient extends AbstractMain
+{
+
+ static public void main(String[] args) throws Exception {
+ Gateway.init(readC2KArgs(args));
+ //AgentProxy user = Gateway.connect("username", "password");
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/process/StandardServer.java b/src/main/java/org/cristalise/kernel/process/StandardServer.java new file mode 100644 index 0000000..9d31b8e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/StandardServer.java @@ -0,0 +1,67 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process;
+
+import org.cristalise.kernel.process.auth.Authenticator;
+import org.cristalise.kernel.utils.Logger;
+
+/**************************************************************************
+ * Base class for all servers i.e. c2k processes that serve Entities
+ *
+ * @author $Author: abranson $ $Date: 2005/04/28 13:49:43 $
+ * @version $Revision: 1.47 $
+ **************************************************************************/
+public class StandardServer extends AbstractMain
+{
+ protected static StandardServer server;
+
+ /**************************************************************************
+ * void StandardInitalisation( String[] )
+ *
+ * Set-up calls to ORB, POA and Factorys, both optional and required.
+ **************************************************************************/
+ protected static void standardInitialisation( String[] args )
+ throws Exception
+ {
+ isServer = true;
+
+ // read args and init Gateway
+ Gateway.init(readC2KArgs(args));
+
+ // connect to LDAP as root
+ Authenticator auth = Gateway.connect();
+
+ //start console
+ Logger.initConsole("ItemServer");
+
+ //initialize the server objects
+ Gateway.startServer(auth);
+
+ Logger.msg(5, "StandardServer::standardInitialisation - complete.");
+
+ }
+
+ public static void main(String[] args) throws Exception
+ {
+ //initialise everything
+ standardInitialisation( args );
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/process/UserCodeProcess.java b/src/main/java/org/cristalise/kernel/process/UserCodeProcess.java new file mode 100644 index 0000000..ff63baf --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/UserCodeProcess.java @@ -0,0 +1,276 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.cristalise.kernel.common.InvalidTransitionException;
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.entity.agent.Job;
+import org.cristalise.kernel.entity.proxy.AgentProxy;
+import org.cristalise.kernel.entity.proxy.MemberSubscription;
+import org.cristalise.kernel.entity.proxy.ProxyObserver;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.scripting.ErrorInfo;
+import org.cristalise.kernel.scripting.ScriptErrorException;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * $Revision: 1.31 $
+ * $Date: 2004/10/21 08:02:19 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class UserCodeProcess extends StandardClient implements ProxyObserver<Job>, Runnable {
+
+ // Default state machine transitions
+ private static final int START = 1;
+ private static final int COMPLETE = 2;
+ private static final int SUSPEND = 3;
+ private static final int RESUME = 4;
+
+ protected AgentProxy agent;
+ static boolean active = true;
+ ArrayList<String> ignoredPaths = new ArrayList<String>();
+ HashMap<String, ErrorInfo> errors = new HashMap<String, ErrorInfo>();
+ final HashMap<String, C2KLocalObject> jobs = new HashMap<String, C2KLocalObject>();
+
+ public UserCodeProcess(String agentName, String agentPass, String resource) {
+ // login - try for a while in case server hasn't imported our user yet
+ for (int i=1;i<6;i++) {
+ try {
+ Logger.msg("Login attempt "+i+" of 5");
+ agent = Gateway.connect(agentName, agentPass, resource);
+ break;
+ } catch (Exception ex) {
+ Logger.error("Could not log in.");
+ Logger.error(ex);
+ try {
+ Thread.sleep(5000);
+ } catch (InterruptedException ex2) { }
+ }
+ }
+ System.out.println(getDesc()+" initialised for " + agentName);
+ }
+
+ @Override
+ public void run() {
+ Thread.currentThread().setName("Usercode Process");
+ // subscribe to job list
+ agent.subscribe(new MemberSubscription<Job>(this, ClusterStorage.JOB, true));
+ while (active) {
+ Job thisJob = null;
+ synchronized (jobs) {
+ if (jobs.size() > 0) {
+ thisJob = getJob(jobs, COMPLETE);
+ if (thisJob == null)
+ thisJob = getJob(jobs, START);
+ if (thisJob == null)
+ thisJob = getJob(jobs, SUSPEND);
+ if (thisJob == null)
+ thisJob = getJob(jobs, RESUME);
+
+ if (thisJob == null) {
+ Logger.error("No supported jobs, but joblist is not empty! Discarding remaining jobs");
+ jobs.clear();
+ }
+ else
+ jobs.remove(ClusterStorage.getPath(thisJob));
+ }
+ }
+
+ if (thisJob != null) {
+ String jobKey = thisJob.getItemPath()+":"+thisJob.getStepPath();
+ int transitionId = thisJob.getTransition().getId();
+ try {
+ if (transitionId==START) {
+ Logger.msg(5, "Testing start conditions");
+ boolean start = assessStartConditions(thisJob);
+ if (start) {
+ Logger.msg(5, "Attempting to start");
+ agent.execute(thisJob);
+ }
+ else {
+ Logger.msg(5, "Start conditions failed "+thisJob.getStepName()+" in "+thisJob.getItemPath());
+ }
+ }
+ else if (transitionId==COMPLETE) {
+ Logger.msg(5, "Executing logic");
+ runUCLogic(thisJob);
+ if (ignoredPaths.contains(jobKey))
+ ignoredPaths.remove(jobKey);
+ }
+ else if (transitionId==SUSPEND) {
+ if (ignoredPaths.contains(jobKey)) {
+ if (errors.containsKey(jobKey)) {
+ thisJob.setOutcome(Gateway.getMarshaller().marshall(errors.get(jobKey)));
+ errors.remove(jobKey);
+ }
+ agent.execute(thisJob);
+ }
+ }
+ else if (transitionId==RESUME) {
+ if (!ignoredPaths.contains(jobKey))
+ agent.execute(thisJob);
+ }
+ } catch (ScriptErrorException ex) {
+ errors.put(jobKey, ex.getErrors());
+ ignoredPaths.add(jobKey);
+ } catch (InvalidTransitionException ex) {
+ // must have already been done by someone else - ignore
+ } catch (Throwable ex) {
+ Logger.error("Error executing "+thisJob.getTransition().getName()+" job:");
+ Logger.error(ex);
+ ErrorInfo ei = new ErrorInfo();
+ ei.setFatal();
+ ei.addError(ex.getClass().getSimpleName());
+ ei.addError(ex.getMessage());
+ errors.put(jobKey, ei);
+ ignoredPaths.add(jobKey);
+ }
+ }
+ try {
+ synchronized (jobs) {
+ if (jobs.size() == 0) {
+ Logger.msg("Sleeping");
+ while (active && jobs.size() == 0)
+ jobs.wait(2000);
+ }
+ }
+ } catch (InterruptedException ex) { }
+ }
+
+ // shut down
+ try
+ {
+ Gateway.close();
+ }
+ catch( Exception ex )
+ {
+ Logger.error(ex);
+ }
+ }
+
+ private static Job getJob(HashMap<String, C2KLocalObject> jobs, int transition) {
+ for (C2KLocalObject c2kLocalObject : jobs.values()) {
+ Job thisJob = (Job)c2kLocalObject;
+ if (thisJob.getTransition().getId() == transition) {
+ Logger.msg(1,"=================================================================");
+ Logger.msg(1, "Got "+thisJob.getTransition().getName()+" job for "+thisJob.getStepName()+" in "+thisJob.getItemPath());
+ return thisJob;
+ }
+ }
+ return null;
+ }
+
+ public boolean assessStartConditions(Job job) {
+ // default implementation - has no start conditions.
+ return true;
+ }
+
+ public void runUCLogic(Job job) throws Exception {
+ // default implementation - the agent will execute any scripts defined when we execute
+ agent.execute(job);
+ }
+
+
+ /**
+ * Receives job from the AgentProxy. Reactivates thread if sleeping.
+ */
+ @Override
+ public void add(Job contents) {
+ synchronized(jobs) {
+ Logger.msg(7, "Adding "+ClusterStorage.getPath(contents));
+ jobs.put(ClusterStorage.getPath(contents), contents);
+ jobs.notify();
+ }
+
+ }
+
+ @Override
+ public void control(String control, String msg) {
+ if (MemberSubscription.ERROR.equals(control))
+ Logger.error("Error in job subscription: "+msg);
+ }
+
+ /**
+ * Removes job removal notification from the AgentProxy.
+ */
+ @Override
+ public void remove(String id) {
+ synchronized(jobs) {
+ Logger.msg(7, "Deleting "+id);
+ jobs.remove(id);
+ }
+ }
+
+ public static UserCodeProcess getInstance() throws UnknownHostException {
+ return new UserCodeProcess(InetAddress.getLocalHost().getHostName(), "uc", Gateway.getProperties().getString("AuthResource", "Cristal"));
+ }
+
+ static public void main(String[] args)
+ {
+ int status = 0;
+
+ try
+ {
+ Gateway.init(readC2KArgs(args));
+ UserCodeProcess proc = getInstance();
+ new Thread(proc).start();
+ Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
+ @Override
+ public void run() {
+ shutdown();
+ }
+ }));
+ }
+ catch( Exception ex )
+ {
+ Logger.error(ex);
+
+ try
+ {
+ Gateway.close();
+ }
+ catch(Exception ex1)
+ {
+ Logger.error(ex1);
+ }
+ status = 1;
+ System.exit(status);
+ }
+ }
+
+ public String getDesc() {
+ return("Usercode Process");
+ }
+
+ public static void shutdown() {
+ active = false;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/process/auth/Authenticator.java b/src/main/java/org/cristalise/kernel/process/auth/Authenticator.java new file mode 100644 index 0000000..2d92d4d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/auth/Authenticator.java @@ -0,0 +1,93 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.auth;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+
+/**
+ * This interface is used by the kernel to store an authenticated connection
+ * and/or token that will be used by kernel components. The CRISTAL property
+ * 'Authenticator' is used to specify the implementation used. It is
+ * instantiated by the connect() methods of the Gateway, and will be found in
+ * the AgentProxy returned by connect(). Lookup and ClusterStorage instances are
+ * initialized with this Authenticator, which is expected to maintain the same
+ * user's connection through the process lifetime, reconnecting if the
+ * connection is lost.
+ *
+ * @since 3.0
+ *
+ */
+public interface Authenticator {
+
+ /**
+ * Authenticates a CRISTAL agent. If this method returns true, then the
+ * connect method will create and return an AgentProxy for the given
+ * username using the Lookup and ProxyManager.
+ *
+ * @param agentName
+ * The username of the Agent to be authenticated. This must be
+ * already present as an Agent in the CRISTAL directory.
+ * @param password
+ * The Agent's password
+ * @param resource
+ * The authentication resource/domain/realm of the agent.
+ * Included so that domains may include CRISTAL users from
+ * different realms. This parameter is passed into the connect()
+ * method if required. May be null.
+ * @return a boolean indicating if the authentication was successful. If so,
+ * then the Gateway will generate an AgentProxy for the given user.
+ * @throws ObjectNotFoundException
+ * When the Agent doesn't exist
+ * @throws InvalidDataException
+ * When authentication fails for another reason
+ */
+ public boolean authenticate(String agentName, String password,
+ String resource) throws InvalidDataException,
+ ObjectNotFoundException;
+
+ /**
+ * Authenticates a superuser connection for the server. It must be able to
+ * act on behalf of any other Agent, as the server needs to do this.
+ * Credentials may be in the CRISTAL properties, or some other mechanism.
+ *
+ * @param resource
+ * @return
+ * @throws InvalidDataException
+ * @throws ObjectNotFoundException
+ */
+ public boolean authenticate(String resource) throws InvalidDataException,
+ ObjectNotFoundException;
+
+ /**
+ * Lookup and storage implementations that need to use user or superuser
+ * authentication can retrieve it using this method. This will be highly
+ * implementation specific.
+ *
+ * @return the connection/token created during authentication
+ */
+ public Object getAuthObject();
+
+ /**
+ * Close or expire the connection as the CRISTAL process shuts down.
+ */
+ public void disconnect();
+}
diff --git a/src/main/java/org/cristalise/kernel/process/auth/ConsoleAuth.java b/src/main/java/org/cristalise/kernel/process/auth/ConsoleAuth.java new file mode 100644 index 0000000..319c792 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/auth/ConsoleAuth.java @@ -0,0 +1,65 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.auth;
+
+import java.util.Properties;
+import java.util.Scanner;
+
+import org.cristalise.kernel.entity.proxy.AgentProxy;
+import org.cristalise.kernel.process.Gateway;
+
+
+public class ConsoleAuth implements ProxyLogin {
+
+ public ConsoleAuth() {
+ }
+
+ @Override
+ public void initialize(Properties props) throws Exception {
+
+ }
+ @Override
+ public AgentProxy authenticate(String resource) throws Exception {
+ AgentProxy user = null;
+ if (resource!=null) System.out.println("Please log in"+(resource.length()>0?"to "+resource:""));
+ Scanner scan = new Scanner(System.in);
+ int loginAttempts = 0;
+ while (user == null && loginAttempts++ < 3) {
+ System.out.print("User:");
+ String username = scan.nextLine();
+ System.out.print("Password:");
+ String pass = scan.nextLine();
+ try {
+ user = Gateway.connect(username, pass, resource);
+ } catch (Exception ex) {
+ System.err.println(ex.getMessage());
+ }
+ }
+
+ if (user == null) {
+ System.err.println("Bye");
+ System.exit(0);
+ }
+ return user;
+
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/process/auth/ProxyLogin.java b/src/main/java/org/cristalise/kernel/process/auth/ProxyLogin.java new file mode 100644 index 0000000..9305d50 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/auth/ProxyLogin.java @@ -0,0 +1,42 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.auth;
+
+import java.util.Properties;
+
+import org.cristalise.kernel.entity.proxy.AgentProxy;
+
+
+/**
+ * This interface is used by client processes to implement alternative login
+ * mechanisms aside from the standard username and password. Implementations may
+ * synchronize Agents with an external user library, such as Active Directory.
+ * Implementations are expected to set up the Gateway process and its
+ * authenticated components itself.
+ *
+ */
+public interface ProxyLogin {
+
+ public void initialize(Properties props) throws Exception;
+
+ public AgentProxy authenticate(String resource) throws Exception;
+
+}
diff --git a/src/main/java/org/cristalise/kernel/process/module/Module.java b/src/main/java/org/cristalise/kernel/process/module/Module.java new file mode 100644 index 0000000..840614b --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/Module.java @@ -0,0 +1,224 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.module;
+
+import java.util.ArrayList;
+import java.util.Properties;
+
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.entity.imports.ImportAgent;
+import org.cristalise.kernel.entity.imports.ImportDependency;
+import org.cristalise.kernel.entity.imports.ImportDependencyMember;
+import org.cristalise.kernel.entity.imports.ImportItem;
+import org.cristalise.kernel.entity.imports.ImportOutcome;
+import org.cristalise.kernel.entity.imports.ImportRole;
+import org.cristalise.kernel.entity.proxy.AgentProxy;
+import org.cristalise.kernel.entity.proxy.ItemProxy;
+import org.cristalise.kernel.lookup.DomainPath;
+import org.cristalise.kernel.lookup.RolePath;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.property.Property;
+import org.cristalise.kernel.scripting.ErrorInfo;
+import org.cristalise.kernel.scripting.ScriptingEngineException;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class Module extends ImportItem {
+
+ private ModuleInfo info;
+ private String resURL;
+ private ModuleImports imports = new ModuleImports();
+ private ArrayList<ModuleConfig> config = new ArrayList<ModuleConfig>();
+ private ArrayList<ModuleScript> scripts = new ArrayList<ModuleScript>();
+
+ public Module() {
+ super();
+ // Module properties
+ properties.add(new Property("Type", "Module", false));
+ setInitialPath("/desc/modules/");
+ setWorkflow("NoWorkflow");
+ setWorkflowVer(0);
+ imports.list.add(this);
+ }
+
+ public void runScript(String event, AgentProxy user, boolean isServer) throws ScriptingEngineException {
+ for (ModuleScript script : scripts) {
+ if (script.shouldRun(event, isServer)) {
+ Logger.msg("Running "+script.event+" "+script.target+" script from "+name);
+ Object result = script.getScript(ns, user).execute();
+ if (result instanceof ErrorInfo) {
+ ErrorInfo error = (ErrorInfo) result;
+ Logger.error(error.toString());
+ if (error.getFatal())
+ throw new ScriptingEngineException("Fatal Script Error");
+ }
+ else if (result != null)
+ Logger.msg(result.toString());
+ }
+ }
+ }
+
+ public void setModuleXML(String moduleXML) {
+ ImportOutcome moduleOutcome = new ImportOutcome("Module", 0, "last", null);
+ moduleOutcome.data = moduleXML;
+ outcomes.add(moduleOutcome);
+ }
+
+ @Override
+ public void setNamespace(String ns) {
+ super.setNamespace(ns);
+ replaceProp(new Property("Namespace", ns, false));
+ }
+
+ @Override
+ public void setName(String name) {
+ super.setName(name);
+ replaceProp(new Property("Name", name, false));
+ }
+
+ private void replaceProp(Property newProp) {
+ for (Property prop : properties) {
+ if (prop.getName().equals("Namespace")) {
+ prop.setMutable(newProp.isMutable());
+ prop.setValue(newProp.getValue());
+ return;
+ }
+ }
+ properties.add(newProp);
+ }
+ public void importAll(ItemProxy serverEntity, AgentProxy systemAgent, String moduleXML, boolean reset) throws Exception {
+ setModuleXML(moduleXML);
+
+ for (ModuleResource thisRes : imports.getResources()) {
+ try {
+ thisRes.setNamespace(ns);
+ thisRes.create(systemAgent.getPath(), reset);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ Logger.die("Error importing module resources. Unsafe to continue.");
+ }
+ }
+
+ for (ImportRole thisRole : imports.getRoles()) {
+ RolePath rolePath;
+ try {
+ String roleName = thisRole.name;
+ if (roleName.indexOf('/') > -1) roleName = roleName.substring(roleName.indexOf('/')+1);
+ rolePath = Gateway.getLookup().getRolePath(roleName);
+ if (rolePath.hasJobList() != thisRole.hasJobList()) {
+ Logger.msg("Module.importAll() - Role '"+thisRole.name+"' has incorrect joblist settings. Correcting.");
+ rolePath.setHasJobList(thisRole.hasJobList());
+ Gateway.getLookupManager().createRole(rolePath);
+ }
+ } catch (ObjectNotFoundException ex) {
+ Logger.msg("Module.importAll() - Role '"+thisRole.name+"' not found. Creating.");
+ thisRole.create(systemAgent.getPath(), reset);
+ }
+ }
+
+ for (ImportAgent thisAgent : imports.getAgents()) {
+ try {
+ Gateway.getLookup().getAgentPath(thisAgent.name);
+ Logger.msg(3, "Module.importAll() - User '"+thisAgent.name+"' found.");
+ continue;
+ } catch (ObjectNotFoundException ex) { }
+ Logger.msg("Module.importAll() - User '"+thisAgent.name+"' not found. Creating.");
+ thisAgent.create(systemAgent.getPath(), reset);
+ }
+
+ for (ImportItem thisItem : imports.getItems()) {
+ thisItem.setNamespace(ns);
+ thisItem.create(systemAgent.getPath(), reset);
+ }
+
+ }
+
+ public Properties getProperties(boolean isServer) {
+ Properties props = new Properties();
+ for (ModuleConfig thisProp : config) {
+ if (thisProp.include(isServer))
+ props.put(thisProp.name, thisProp.value);
+ }
+ return props;
+ }
+
+ public ArrayList<ModuleScript> getScripts() {
+ return scripts;
+ }
+
+ public void setResURL(String resURL) {
+ this.resURL = resURL;
+ }
+ public String getDesc() {
+ return info.desc;
+ }
+ public String getVersion() {
+ return info.version;
+ }
+ public String getResURL() {
+ return resURL;
+ }
+ public ArrayList<String> getDependencies() {
+ return info.dependency;
+ }
+ public boolean hasDependency(String dep) {
+ return info.dependency.contains(dep);
+ }
+
+ public ModuleInfo getInfo() {
+ return info;
+ }
+
+ public void setInfo(ModuleInfo info) {
+ this.info = info;
+ replaceProp(new Property("Version", info.version, true));
+ }
+
+ public ModuleImports getImports() {
+ return imports;
+ }
+
+ public void setImports(ModuleImports imp) {
+ // Add dependency for all children
+ imports = imp;
+ ImportDependency children = new ImportDependency("Contents");
+ for (ModuleImport thisImport : imports.list) {
+ DomainPath path = thisImport.domainPath;
+ if (path != null)
+ children.dependencyMemberList.add(new ImportDependencyMember(path.toString()));
+ }
+ dependencyList.add(children);
+ }
+
+ public void setConfig(ArrayList<ModuleConfig> config) {
+ this.config = config;
+ }
+
+ public void setScripts(ArrayList<ModuleScript> scripts) {
+ this.scripts = scripts;
+ }
+
+ public ArrayList<ModuleConfig> getConfig() {
+ return config;
+ }
+
+
+} diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleConfig.java b/src/main/java/org/cristalise/kernel/process/module/ModuleConfig.java new file mode 100644 index 0000000..1165e31 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleConfig.java @@ -0,0 +1,42 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.module;
+
+public class ModuleConfig {
+
+ public String name;
+ public String value;
+ public String target;
+
+ public ModuleConfig() {
+ }
+
+ public ModuleConfig(String name, String value, String target) {
+ super();
+ this.name = name;
+ this.value = value;
+ this.target = target;
+ }
+
+ public boolean include(boolean isServer) {
+ return (target == null || target.length() == 0 || isServer == target.equals("server"));
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleException.java b/src/main/java/org/cristalise/kernel/process/module/ModuleException.java new file mode 100644 index 0000000..e09107e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleException.java @@ -0,0 +1,29 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.module;
+
+public class ModuleException extends Exception {
+
+ public ModuleException(String msg) {
+ super(msg);
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleImport.java b/src/main/java/org/cristalise/kernel/process/module/ModuleImport.java new file mode 100644 index 0000000..22faa5a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleImport.java @@ -0,0 +1,87 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.module;
+
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.InvalidCollectionModification;
+import org.cristalise.kernel.common.ObjectAlreadyExistsException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.lookup.DomainPath;
+import org.cristalise.kernel.lookup.InvalidItemPathException;
+import org.cristalise.kernel.lookup.ItemPath;
+
+
+public abstract class ModuleImport {
+
+ protected String ns;
+ protected String name;
+ protected DomainPath domainPath;
+ protected ItemPath itemPath;
+
+ public ModuleImport() {
+ }
+
+ public abstract void create(AgentPath agentPath, boolean reset) throws ObjectNotFoundException,
+ ObjectCannotBeUpdated, CannotManageException, ObjectAlreadyExistsException, InvalidCollectionModification;
+
+ public void setID( String uuid ) throws InvalidItemPathException
+ {
+ if (uuid != null && uuid.length() > 0) itemPath = new ItemPath(uuid);
+ }
+
+ public String getID() {
+ return itemPath==null?null:itemPath.getUUID().toString();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setNamespace(String ns) {
+ this.ns = ns;
+ }
+
+ public String getNamespace() {
+ return ns;
+ }
+
+ public DomainPath getDomainPath() {
+ return domainPath;
+ }
+
+ public void setDomainPath(DomainPath domainPath) {
+ this.domainPath = domainPath;
+ }
+
+ public ItemPath getItemPath() {
+ return itemPath;
+ }
+
+ public void setItemPath(ItemPath itemPath) {
+ this.itemPath = itemPath;
+ }
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleImports.java b/src/main/java/org/cristalise/kernel/process/module/ModuleImports.java new file mode 100644 index 0000000..53c7e9d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleImports.java @@ -0,0 +1,78 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.module;
+
+import java.util.ArrayList;
+
+import org.cristalise.kernel.entity.imports.ImportAgent;
+import org.cristalise.kernel.entity.imports.ImportItem;
+import org.cristalise.kernel.entity.imports.ImportRole;
+import org.cristalise.kernel.utils.CastorArrayList;
+
+
+public class ModuleImports extends CastorArrayList<ModuleImport> {
+
+ public ModuleImports()
+ {
+ super();
+ }
+
+ public ModuleImports(ArrayList<ModuleImport> aList)
+ {
+ super(aList);
+ }
+
+ public ArrayList<ModuleResource> getResources() {
+ ArrayList<ModuleResource> subset = new ArrayList<ModuleResource>();
+ for (ModuleImport imp : list) {
+ if (imp instanceof ModuleResource)
+ subset.add((ModuleResource)imp);
+ }
+ return subset;
+ }
+
+ public ArrayList<ImportItem> getItems() {
+ ArrayList<ImportItem> subset = new ArrayList<ImportItem>();
+ for (ModuleImport imp : list) {
+ if (imp instanceof ImportItem)
+ subset.add((ImportItem)imp);
+ }
+ return subset;
+ }
+
+ public ArrayList<ImportAgent> getAgents() {
+ ArrayList<ImportAgent> subset = new ArrayList<ImportAgent>();
+ for (ModuleImport imp : list) {
+ if (imp instanceof ImportAgent)
+ subset.add((ImportAgent)imp);
+ }
+ return subset;
+ }
+
+ public ArrayList<ImportRole> getRoles() {
+ ArrayList<ImportRole> subset = new ArrayList<ImportRole>();
+ for (ModuleImport imp : list) {
+ if (imp instanceof ImportRole)
+ subset.add((ImportRole)imp);
+ }
+ return subset;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleInfo.java b/src/main/java/org/cristalise/kernel/process/module/ModuleInfo.java new file mode 100644 index 0000000..8f482fc --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleInfo.java @@ -0,0 +1,34 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.module;
+
+import java.util.ArrayList;
+
+public class ModuleInfo {
+
+ public String desc;
+ public String version;
+ public ArrayList<String> dependency = new ArrayList<String>();
+
+ public ModuleInfo() {
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleManager.java b/src/main/java/org/cristalise/kernel/process/module/ModuleManager.java new file mode 100644 index 0000000..d95abe6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleManager.java @@ -0,0 +1,211 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.module;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Properties;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.entity.proxy.AgentProxy;
+import org.cristalise.kernel.entity.proxy.ItemProxy;
+import org.cristalise.kernel.lookup.DomainPath;
+import org.cristalise.kernel.persistency.outcome.OutcomeValidator;
+import org.cristalise.kernel.persistency.outcome.Schema;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.scripting.ScriptingEngineException;
+import org.cristalise.kernel.utils.FileStringUtility;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class ModuleManager {
+ ArrayList<Module> modules = new ArrayList<Module>();
+ HashMap<String, String> modulesXML = new HashMap<String, String>();
+ Properties props = new Properties();
+ AgentProxy user;
+ boolean isServer;
+ OutcomeValidator moduleValidator;
+
+ public ModuleManager(Enumeration<URL> moduleEnum, boolean isServer) throws ModuleException {
+ this.isServer = isServer;
+ try {
+ Schema moduleSchema = new Schema("Module", 0,
+ FileStringUtility.url2String(Gateway.getResource().getKernelResourceURL("boot/OD/Module.xsd")));
+ moduleValidator = new OutcomeValidator(moduleSchema);
+ } catch (InvalidDataException ex) {
+ Logger.error(ex);
+ throw new ModuleException("Module Schema is not valid");
+ } catch (IOException ex) {
+ throw new ModuleException("Could not load Module Schema from kernel resources");
+ }
+ ArrayList<String> loadedModules = new ArrayList<String>();
+ ArrayList<String> moduleNs = new ArrayList<String>();
+ while(moduleEnum.hasMoreElements()) {
+ URL newModuleURL = moduleEnum.nextElement();
+ try {
+ String moduleXML = FileStringUtility.url2String(newModuleURL);
+ String errors = moduleValidator.validate(moduleXML);
+ if (errors.length() > 0)
+ throw new ModuleException("Module XML found at "+newModuleURL+" was not valid: "+errors);
+ Module newModule = (Module)Gateway.getMarshaller().unmarshall(moduleXML);
+ if (newModule.getResURL() != null && newModule.getResURL().length()>0) Gateway.getResource().addModuleBaseURL(newModule.getNamespace(), newModule.getResURL());
+ modules.add(newModule);
+ modulesXML.put(newModule.getNamespace(), moduleXML);
+ if (loadedModules.contains(newModule.getName())) throw new ModuleException("Module name clash: "+newModule.getName());
+ if (moduleNs.contains(newModule.getNamespace())) throw new ModuleException("Module namespace clash: "+newModule.getNamespace());
+ Logger.debug(4, "Module found: "+newModule.getNamespace()+" - "+newModule.getName());
+ loadedModules.add(newModule.getName()); moduleNs.add(newModule.getNamespace());
+ } catch (ModuleException e) {
+ Logger.error("Could not load module description from "+newModuleURL);
+ throw e;
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new ModuleException("Could not load module.xml from "+newModuleURL);
+ }
+ }
+
+ Logger.debug(5, "Checking dependencies");
+ boolean allDepsPresent = true;
+
+ ArrayList<String> prevModules = new ArrayList<String>();
+ for (int i=0; i<modules.size();i++) {
+ boolean depClean = false;
+ int skipped = 0;
+ Module thisMod = modules.get(i);
+ Logger.msg(5, "Checking dependencies of module "+thisMod.getName());
+ while (!depClean) {
+ ArrayList<String> deps = thisMod.getDependencies();
+ depClean = true;
+ for (String dep : deps) {
+ Logger.msg(6, thisMod.getName()+" depends on "+dep);
+ if (!loadedModules.contains(dep)) {
+ Logger.error("UNMET MODULE DEPENDENCY: "+thisMod.getName()+" requires "+dep);
+ allDepsPresent = false;
+ }
+ else if (!prevModules.contains(dep)) {
+ Logger.msg(1, "ModuleManager: Shuffling "+thisMod.getName()+" to the end to fulfil dependency on "+dep);
+ modules.remove(i);
+ modules.add(thisMod);
+ thisMod = modules.get(i);
+ skipped++;
+ depClean = false;
+ break;
+ }
+ }
+ if (skipped > modules.size()-i) {
+ StringBuffer badMod = new StringBuffer();
+ for (Module mod : modules.subList(i, modules.size())) {
+ badMod.append(mod.getName()).append(" ");
+ }
+ Logger.die("Circular module dependencies involving: "+badMod);
+ }
+ }
+ // Current module is 'next', this is the correct order to load the properties
+ Properties modProp = thisMod.getProperties(isServer);
+ for (Enumeration<?> e = modProp.propertyNames(); e.hasMoreElements();) {
+ String propName = (String)e.nextElement();
+ props.put(propName, modProp.get(propName));
+ }
+ prevModules.add(thisMod.getName());
+ }
+ if (!allDepsPresent) Logger.die("Unmet module dependencies. Cannot continue");
+ }
+
+ public void setUser(AgentProxy user) {
+ this.user = user;
+ }
+
+ public String getModuleVersions() {
+ StringBuffer ver = new StringBuffer();
+ for (Module thisMod : modules) {
+ if (ver.length()>0) ver.append("; ");
+ ver.append(thisMod.getName()+" ("+thisMod.getVersion()+")");
+ }
+ return ver.toString();
+ }
+
+
+ public Properties getAllModuleProperties() {
+ return props;
+ }
+
+ public void runScripts(String event) {
+ for (Module thisMod : modules) {
+ try {
+ thisMod.runScript(event, user, isServer);
+ } catch (ScriptingEngineException e) {
+ Logger.error(e);
+ Logger.die(e.getMessage());
+ }
+ }
+ }
+
+ public void registerModules() throws ModuleException {
+ ItemProxy serverEntity;
+ try {
+ serverEntity = Gateway.getProxyManager().getProxy(new DomainPath("/servers/"+Gateway.getProperties().getString("ItemServer.name")));
+ } catch (ObjectNotFoundException e) {
+ throw new ModuleException("Cannot find local server name.");
+ }
+ Logger.debug(3, "Registering modules");
+
+ boolean reset = Gateway.getProperties().getBoolean("Module.reset", false);
+
+ for (Module thisMod : modules) {
+
+ Logger.msg("Registering module "+thisMod.getName());
+ try {
+ String thisResetKey = "Module."+thisMod.getNamespace()+".reset";
+ boolean thisReset = reset;
+ if (Gateway.getProperties().containsKey(thisResetKey))
+ thisReset = Gateway.getProperties().getBoolean(thisResetKey);
+ thisMod.importAll(serverEntity, user, modulesXML.get(thisMod.getNamespace()), thisReset);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new ModuleException("Error importing items for module "+thisMod.getName());
+ }
+ Logger.msg("Module "+thisMod.getName()+" registered");
+
+ try {
+ thisMod.runScript("startup", user, true);
+ } catch (ScriptingEngineException e) {
+ Logger.error(e);
+ throw new ModuleException("Error in startup script for module "+thisMod.getName());
+ }
+
+ }
+ }
+
+ public void dumpModules() {
+ for (Module thisMod : modules) {
+ try {
+ FileStringUtility.string2File(thisMod.getName()+".xml", Gateway.getMarshaller().marshall(thisMod));
+ } catch (Exception e) {
+ Logger.error(e);
+ }
+ }
+
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleResource.java b/src/main/java/org/cristalise/kernel/process/module/ModuleResource.java new file mode 100644 index 0000000..74b5673 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleResource.java @@ -0,0 +1,80 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.module;
+
+import org.cristalise.kernel.common.CannotManageException;
+import org.cristalise.kernel.common.ObjectAlreadyExistsException;
+import org.cristalise.kernel.common.ObjectCannotBeUpdated;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.lookup.AgentPath;
+import org.cristalise.kernel.process.Bootstrap;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class ModuleResource extends ModuleImport {
+
+ public int version;
+ public String resourceType;
+ public String resourceLocation;
+
+ public ModuleResource() {
+ // if not given, version defaults to 0
+ version = 0;
+ }
+
+ @Override
+ public void create(AgentPath agentPath, boolean reset)
+ throws ObjectNotFoundException, ObjectCannotBeUpdated,
+ CannotManageException, ObjectAlreadyExistsException {
+ try {
+ domainPath = Bootstrap.verifyResource(ns, name, version, resourceType, itemPath, resourceLocation, reset);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new CannotManageException("Exception verifying module resource "+ns+"/"+name);
+ }
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public void setVersion(int version) {
+ this.version = version;
+ }
+
+ public String getResourceType() {
+ return resourceType;
+ }
+
+ public void setResourceType(String resourceType) {
+ this.resourceType = resourceType;
+ }
+
+ public String getResourceLocation() {
+ return resourceLocation;
+ }
+
+ public void setResourceLocation(String resourceLocation) {
+ this.resourceLocation = resourceLocation;
+ }
+
+
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/process/module/ModuleScript.java b/src/main/java/org/cristalise/kernel/process/module/ModuleScript.java new file mode 100644 index 0000000..4e81864 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/module/ModuleScript.java @@ -0,0 +1,53 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.module;
+
+import org.cristalise.kernel.entity.proxy.AgentProxy;
+import org.cristalise.kernel.scripting.Script;
+import org.cristalise.kernel.scripting.ScriptingEngineException;
+
+public class ModuleScript {
+
+
+ public String target;
+ public String event;
+ public String lang;
+ public String script;
+ public ModuleScript() {
+ }
+
+ public ModuleScript(String target, String event, String lang, String script) {
+ super();
+ this.target = target;
+ this.event = event;
+ this.lang = lang;
+ this.script = script;
+ }
+
+ public Script getScript(String ns, AgentProxy user) throws ScriptingEngineException {
+ return new Script(lang, ns+" "+target+" "+event, script, user);
+ }
+
+ public boolean shouldRun(String event, boolean isServer) {
+ return ((this.target == null || this.target.length() == 0 || isServer == target.equals("server")) &&
+ (this.event == null || this.event.length() == 0 || event.equals(this.event)));
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/process/resource/BadArgumentsException.java b/src/main/java/org/cristalise/kernel/process/resource/BadArgumentsException.java new file mode 100644 index 0000000..d8d7dc9 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/BadArgumentsException.java @@ -0,0 +1,37 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.resource;
+
+public class BadArgumentsException extends Exception {
+
+ public BadArgumentsException() {
+ super();
+ }
+
+ public BadArgumentsException(String message) {
+ super(message);
+ }
+
+ public BadArgumentsException(Throwable cause) {
+ super(cause);
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/process/resource/DefaultResourceImportHandler.java b/src/main/java/org/cristalise/kernel/process/resource/DefaultResourceImportHandler.java new file mode 100644 index 0000000..dbd2d44 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/DefaultResourceImportHandler.java @@ -0,0 +1,106 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.resource;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.cristalise.kernel.lookup.DomainPath;
+import org.cristalise.kernel.persistency.outcome.Outcome;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.property.PropertyDescriptionList;
+
+
+public class DefaultResourceImportHandler implements ResourceImportHandler {
+
+ String schemaName;
+ String typeRoot;
+ DomainPath typeRootPath;
+ String wfDef;
+ PropertyDescriptionList props;
+
+ public DefaultResourceImportHandler(String resType) throws Exception {
+ if (resType.equals("CA")) {
+ wfDef = "ManageCompositeActDef";
+ schemaName = "CompositeActivityDef";
+ typeRoot = "/desc/ActivityDesc";
+ }
+ else if (resType.equals("EA")) {
+ wfDef = "ManageElementaryActDef";
+ schemaName = "ElementaryActivityDef";
+ typeRoot = "/desc/ActivityDesc";
+ }
+ else if (resType.equals("OD")) {
+ wfDef = "ManageSchema";
+ schemaName = "Schema";
+ typeRoot = "/desc/OutcomeDesc";
+ }
+ else if (resType.equals("SC")) {
+ wfDef = "ManageScript";
+ schemaName = "Script";
+ typeRoot = "/desc/Script";
+ }
+ else if (resType.equals("SM")) {
+ wfDef = "ManageStateMachine";
+ schemaName = "StateMachine";
+ typeRoot = "/desc/StateMachine";
+ }
+ else throw new Exception("Unknown bootstrap item type: "+resType);
+ typeRootPath = new DomainPath(typeRoot);
+ props = (PropertyDescriptionList)Gateway.getMarshaller().unmarshall(Gateway.getResource().getTextResource(null, "boot/property/"+resType+"Prop.xml"));
+ }
+
+ @Override
+ public DomainPath getTypeRoot() {
+ return typeRootPath;
+ }
+
+ @Override
+ public String getName() {
+ return schemaName;
+ }
+
+ @Override
+ public DomainPath getPath(String name, String ns) throws Exception {
+ return new DomainPath(typeRoot+"/system/"+(ns==null?"kernel":ns)+'/'+name);
+ }
+
+ @Override
+ public Set<Outcome> getResourceOutcomes(String name, String ns, String location, int version) throws Exception {
+ HashSet<Outcome> retArr = new HashSet<Outcome>();
+ String data = Gateway.getResource().getTextResource(ns, location);
+ if (data == null)
+ throw new Exception("No data found for "+schemaName+" "+name);
+ Outcome resOutcome = new Outcome(0, data, schemaName, 0);
+ retArr.add(resOutcome);
+ return retArr;
+ }
+
+ @Override
+ public PropertyDescriptionList getPropDesc() throws Exception {
+ return props;
+ }
+
+ @Override
+ public String getWorkflowName() throws Exception {
+ return wfDef;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/process/resource/Resource.java b/src/main/java/org/cristalise/kernel/process/resource/Resource.java new file mode 100644 index 0000000..25b1ee8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/Resource.java @@ -0,0 +1,196 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.resource;
+
+//Java
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.utils.FileStringUtility;
+import org.cristalise.kernel.utils.Logger;
+
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2005/10/05 07:39:36 $
+ * @version $Revision: 1.71 $
+ **************************************************************************/
+public class Resource implements ResourceLoader {
+
+ private final Hashtable<String, String> txtCache = new Hashtable<String, String>();
+ private final URL baseURL;
+ private final HashMap<String, URL> moduleBaseURLs = new HashMap<String, URL>();
+ private final HashMap<String, URL> allBaseURLs = new HashMap<String, URL>();
+
+ public Resource() throws InvalidDataException {
+ baseURL = getURLorResURL("org/cristalise/kernel/utils/resources/");
+ allBaseURLs.put(null, baseURL);
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.ResourceLoader#getKernelBaseURL()
+ */
+ @Override
+ public URL getKernelBaseURL() {
+ return baseURL;
+ }
+
+ @Override
+ public ClassLoader getClassLoader(String className) {
+ return Resource.class.getClassLoader();
+ }
+
+ @Override
+ public Class<?> getClassForName(String name) throws ClassNotFoundException {
+ return Class.forName(name);
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.ResourceLoader#getKernelResourceURL(java.lang.String)
+ */
+ @Override
+ public URL getKernelResourceURL(String resName) throws MalformedURLException {
+ return new URL(baseURL, resName);
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.ResourceLoader#addModuleBaseURL(java.lang.String, java.net.URL)
+ */
+ @Override
+ public void addModuleBaseURL(String ns, URL newBaseURL) {
+ moduleBaseURLs.put(ns, newBaseURL);
+ allBaseURLs.put(ns, newBaseURL);
+ Logger.msg("Adding resource URL for "+ns+": "+newBaseURL.toString());
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.ResourceLoader#addModuleBaseURL(java.lang.String, java.lang.String)
+ */
+ @Override
+ public void addModuleBaseURL(String ns, String newBaseURL) throws InvalidDataException {
+ addModuleBaseURL(ns, getURLorResURL(newBaseURL));
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.ResourceLoader#getModuleBaseURLs()
+ */
+ @Override
+ public HashMap<String, URL> getModuleBaseURLs() {
+ return moduleBaseURLs;
+ }
+
+ private HashMap<String, URL> getAllBaseURLs() {
+ return allBaseURLs;
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.ResourceLoader#getModuleResourceURL(java.lang.String, java.lang.String)
+ */
+ @Override
+ public URL getModuleResourceURL(String ns, String resName) throws MalformedURLException {
+ return new URL(moduleBaseURLs.get(ns), resName);
+ }
+
+ static private URL getURLorResURL(String newURL) throws InvalidDataException {
+ URL result;
+ try {
+ result = new URL(newURL);
+ } catch (java.net.MalformedURLException ex) {
+ //it is assumed that a 'wrong' URL denotes a directory
+ //of files resolvable from the CLASSPATH
+ result = Resource.class.getClassLoader().getResource(newURL);
+ }
+ if (result == null) {
+ Logger.error("URL "+newURL+" could not be found");
+ throw new InvalidDataException();
+ }
+ return result;
+ }
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.ResourceLoader#findTextResource(java.lang.String)
+ */
+
+ @Override
+ public String findTextResource(String resName) {
+ for (String ns : getAllBaseURLs().keySet()) {
+ try {
+ return getTextResource(ns, resName);
+ } catch (ObjectNotFoundException ex) { }
+ }
+ Logger.warning("Text resource '"+resName+"' not found.");
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.ResourceLoader#getAllTextResources(java.lang.String)
+ */
+ @Override
+ public HashMap<String, String> getAllTextResources(String resName) {
+ HashMap<String, String> results = new HashMap<String, String>();
+ for (String ns : getAllBaseURLs().keySet()) {
+ try {
+ results.put(ns, getTextResource(ns, resName));
+ } catch (ObjectNotFoundException ex) { }
+ }
+ return results;
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.ResourceLoader#getTextResource(java.lang.String, java.lang.String)
+ */
+ @Override
+ public String getTextResource(String ns, String resName) throws ObjectNotFoundException
+ // throws IOException
+ {
+ Logger.msg(8, "Resource::getTextResource() - Getting resource from "+ns+": " + resName);
+
+ if (txtCache.containsKey(ns+'/'+resName)) {
+ return txtCache.get(ns+'/'+resName);
+ }
+
+ try {
+
+ String newRes = null;
+ URL loc;
+
+ if (ns == null) // kernel
+ loc = getKernelResourceURL(resName);
+ else
+ loc = getModuleResourceURL(ns, resName);
+ Logger.msg(5, "Loading resource: "+loc.toString());
+ newRes = FileStringUtility.url2String(loc);
+ txtCache.put(ns+'/'+resName, newRes);
+ return newRes;
+ } catch (Exception e) {
+ throw new ObjectNotFoundException(e.getMessage());
+ }
+ }
+
+ @Override
+ public Enumeration<URL> getModuleDefURLs() throws Exception {
+ return ClassLoader.getSystemResources("META-INF/cristal/module.xml");
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/process/resource/ResourceImportHandler.java b/src/main/java/org/cristalise/kernel/process/resource/ResourceImportHandler.java new file mode 100644 index 0000000..9d37e31 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/ResourceImportHandler.java @@ -0,0 +1,68 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.resource;
+
+import java.util.Set;
+
+import org.cristalise.kernel.lookup.DomainPath;
+import org.cristalise.kernel.persistency.outcome.Outcome;
+import org.cristalise.kernel.property.PropertyDescriptionList;
+
+
+public interface ResourceImportHandler {
+
+
+ /** Returns the DomainPath for a specific resource
+ * @param ns - module namespace
+ * @param name - resource name
+ * @return
+ */
+ public DomainPath getPath(String name, String ns) throws Exception;
+
+ /** Generates the outcomes that the resource should contain.
+ * @param res - the module resource definition
+ * @return a set of outcomes to be synced with the resource item.
+ * @throws Exception - if the supplied resources are not valid
+ */
+ public Set<Outcome> getResourceOutcomes(String name, String ns, String location, int version) throws Exception;
+
+ /** Gives the CompActDef name to instantiate to provide the workflow for this type of resource.
+ * Should be found in the CA typeroot (/desc/ActivityDesc/)
+ * @return String workflow name
+ * @throws Exception
+ */
+ public String getWorkflowName() throws Exception;
+
+ /** Should return all of the Properties the resource Item
+ * will have on creation. The Property 'Name' will be created and populated automatically, even if not declared.
+ * @return a PropertyDescriptionList - an arraylist of PropertyDescriptions
+ * @throws Exception
+ */
+ public PropertyDescriptionList getPropDesc() throws Exception;
+
+ /** The directory context to search for existing resources. The name of the resource must be unique below this point.
+ * @return Root path
+ */
+ public DomainPath getTypeRoot();
+
+ public String getName();
+
+}
diff --git a/src/main/java/org/cristalise/kernel/process/resource/ResourceLoader.java b/src/main/java/org/cristalise/kernel/process/resource/ResourceLoader.java new file mode 100644 index 0000000..4ef0e9d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/process/resource/ResourceLoader.java @@ -0,0 +1,67 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.process.resource;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+
+
+public interface ResourceLoader {
+
+ public URL getKernelBaseURL();
+
+ public URL getKernelResourceURL(String resName)
+ throws MalformedURLException;
+
+ public void addModuleBaseURL(String ns, URL newBaseURL);
+
+ public void addModuleBaseURL(String ns, String newBaseURL)
+ throws InvalidDataException;
+
+ public HashMap<String, URL> getModuleBaseURLs();
+
+ public URL getModuleResourceURL(String ns, String resName)
+ throws MalformedURLException;
+
+ /**************************************************************************
+ * Gets any text resource files
+ **************************************************************************/
+
+ public String findTextResource(String resName);
+
+ public HashMap<String, String> getAllTextResources(String resName);
+
+ public String getTextResource(String ns, String resName)
+ throws ObjectNotFoundException;
+
+ public Class<?> getClassForName(String name)
+ throws ClassNotFoundException;
+
+ public ClassLoader getClassLoader(String className);
+
+ public Enumeration<URL> getModuleDefURLs() throws Exception;
+
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/property/Property.java b/src/main/java/org/cristalise/kernel/property/Property.java new file mode 100644 index 0000000..920574c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/property/Property.java @@ -0,0 +1,112 @@ +/**
+ * 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.property;
+
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.persistency.ClusterStorage;
+
+
+public class Property implements C2KLocalObject
+{
+ private String mName;
+ private String mValue;
+ private boolean mMutable = true;
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public Property()
+ {
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public Property( String name, String value, boolean mutable )
+ {
+ setName( name );
+ setValue( value );
+ setMutable( mutable );
+ }
+
+ public Property( String name, String value)
+ {
+ setName( name );
+ setValue( value );
+ }
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ @Override
+ public void setName(String name)
+ {
+ mName = name;
+ }
+
+
+ public boolean isMutable() {
+ return mMutable;
+ }
+
+
+ public void setMutable(boolean mMutable) {
+ this.mMutable = mMutable;
+ }
+
+
+/**************************************************************************
+ *
+ **************************************************************************/
+ @Override
+ public String getName()
+ {
+ return mName;
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public void setValue( String value )
+ {
+ mValue = value;
+ }
+
+
+ /**************************************************************************
+ *
+ **************************************************************************/
+ public String getValue()
+ {
+ return mValue;
+ }
+ /**
+ * @see org.cristalise.kernel.entity.C2KLocalObject#getClusterType()
+ */
+ @Override
+ public String getClusterType() {
+ return ClusterStorage.PROPERTY;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/property/PropertyArrayList.java b/src/main/java/org/cristalise/kernel/property/PropertyArrayList.java new file mode 100644 index 0000000..3e981a0 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/property/PropertyArrayList.java @@ -0,0 +1,54 @@ +/**
+ * 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.property;
+
+import java.util.ArrayList;
+
+import org.cristalise.kernel.utils.CastorArrayList;
+
+
+public class PropertyArrayList extends CastorArrayList<Property>
+{
+ public PropertyArrayList()
+ {
+ super();
+ }
+
+ public PropertyArrayList(ArrayList<Property> aList)
+ {
+ super();
+ // put all properties in order, so later ones with the same name overwrite earlier ones
+ for (Property property : aList) {
+ put(property);
+ }
+ }
+
+ /** Overwrite */
+ public void put(Property p) {
+ for (Property thisProp : list) {
+ if (thisProp.getName().equals(p.getName())) {
+ list.remove(thisProp);
+ break;
+ }
+ }
+ list.add(p);
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/property/PropertyDescription.java b/src/main/java/org/cristalise/kernel/property/PropertyDescription.java new file mode 100644 index 0000000..29b10b1 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/property/PropertyDescription.java @@ -0,0 +1,88 @@ +/**
+ * 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.property;
+
+public class PropertyDescription
+{
+ private String mName=null;
+ private String mDefaultValue=null;
+ private boolean mIsClassIdentifier=false;
+ private boolean mIsMutable=false;
+
+
+ public PropertyDescription()
+ {
+ }
+
+ public PropertyDescription(String name, String defaultValue, boolean isClassIdentifier, boolean isMutable )
+ {
+ setName(name);
+ setDefaultValue(defaultValue);
+ setIsClassIdentifier(isClassIdentifier);
+ setIsMutable(isMutable);
+ }
+
+ public void setName(String name)
+ {
+ mName = name;
+ }
+
+ public void setIsClassIdentifier(boolean classId)
+ {
+ mIsClassIdentifier = classId;
+ }
+
+ public void setDefaultValue(String defaultValue)
+ {
+ mDefaultValue = defaultValue;
+ }
+
+ public void setIsMutable(boolean mutable)
+ {
+ mIsMutable = mutable;
+ }
+
+ public String getName()
+ {
+ return mName;
+ }
+
+ public boolean getIsClassIdentifier()
+ {
+ return mIsClassIdentifier;
+ }
+
+ public String getDefaultValue()
+ {
+ return mDefaultValue;
+ }
+
+ public boolean getIsMutable()
+ {
+ return mIsMutable;
+ }
+
+ public Property getProperty()
+ {
+ return new Property(mName, mDefaultValue, mIsMutable);
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/property/PropertyDescriptionList.java b/src/main/java/org/cristalise/kernel/property/PropertyDescriptionList.java new file mode 100644 index 0000000..98df773 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/property/PropertyDescriptionList.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.property;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.utils.CastorArrayList;
+
+
+public class PropertyDescriptionList extends CastorArrayList<PropertyDescription>
+{
+ public PropertyDescriptionList()
+ {
+ super();
+ }
+
+ public PropertyDescriptionList(ArrayList<PropertyDescription> aList)
+ {
+ super(aList);
+ }
+
+ public String getClassProps() {
+ StringBuffer props = new StringBuffer();
+ for (PropertyDescription element : list) {
+ if (element.getIsClassIdentifier()) {
+ if (props.length()>0)
+ props.append(",");
+ props.append(element.getName());
+ }
+ }
+ return props.toString();
+ }
+
+ public boolean setDefaultValue(String name, String value) {
+ for (PropertyDescription element : list) {
+ if (element.getName().equals(name)) {
+ element.setDefaultValue(value);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean definesProperty(String name) {
+ for (PropertyDescription element : list) {
+ if (element.getName().equals(name))
+ return true;
+ }
+ return false;
+ }
+
+ public PropertyArrayList instantiate(PropertyArrayList initProps) throws InvalidDataException {
+ // check that supplied init properties exist in desc list
+ HashMap<String, String> validatedInitProps = new HashMap<String, String>();
+ for (Property initProp : initProps.list) {
+ if (!definesProperty(initProp.getName()))
+ throw new InvalidDataException("Property "+initProp.getName()+" has not been declared in the property descriptions");
+ else
+ validatedInitProps.put(initProp.getName(), initProp.getValue());
+ }
+
+ PropertyArrayList propInst = new PropertyArrayList();
+ for (int i = 0; i < list.size(); i++) {
+ PropertyDescription pd = list.get(i);
+ String propName = pd.getName();
+ String propVal = pd.getDefaultValue();
+ if (validatedInitProps.containsKey(propName))
+ propVal = validatedInitProps.get(propName);
+ boolean isMutable = pd.getIsMutable();
+ propInst.list.add( new Property(propName, propVal, isMutable));
+ }
+ return propInst;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/property/PropertyUtility.java b/src/main/java/org/cristalise/kernel/property/PropertyUtility.java new file mode 100644 index 0000000..39d399f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/property/PropertyUtility.java @@ -0,0 +1,96 @@ +/**
+ * 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.property;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.persistency.outcome.Outcome;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.CastorHashMap;
+import org.cristalise.kernel.utils.Logger;
+
+
+
+public class PropertyUtility
+{
+ static public String getValue(ArrayList<PropertyDescription> pdlist, String name)
+ {
+ for (PropertyDescription pd : pdlist) {
+ if ( name.equalsIgnoreCase(pd.getName()) )
+ return pd.getDefaultValue();
+ }
+ return null;
+ }
+
+ static public String getNames(ArrayList<PropertyDescription> pdlist)
+ {
+ StringBuffer names = new StringBuffer();
+ for (PropertyDescription value : pdlist)
+ names.append( value.getDefaultValue()).append(" ");
+ return names.toString();
+ }
+
+ static public String getClassIdNames(ArrayList<PropertyDescription> pdlist)
+ {
+ StringBuffer names = new StringBuffer();
+
+ for (Iterator<PropertyDescription> iter = pdlist.iterator(); iter.hasNext();) {
+ PropertyDescription pd = iter.next();
+ if (pd.getIsClassIdentifier())
+ names.append(pd.getName());
+ if (iter.hasNext())
+ names.append(",");
+ }
+ return names.toString();
+ }
+
+
+ static public PropertyDescriptionList getPropertyDescriptionOutcome(ItemPath itemPath, String descVer) throws ObjectNotFoundException
+ {
+ try
+ {
+ Outcome outc = (Outcome) Gateway.getStorage().get(itemPath, ClusterStorage.VIEWPOINT+"/PropertyDescription/"+descVer+"/data", null);
+ return (PropertyDescriptionList)Gateway.getMarshaller().unmarshall(outc.getData());
+ }
+ catch (Exception ex)
+ {
+ Logger.error(ex);
+ throw new ObjectNotFoundException("Could not fetch PropertyDescription from "+itemPath);
+ }
+ }
+
+ static public CastorHashMap createProperty(PropertyDescriptionList pdList)
+ {
+ CastorHashMap props = new CastorHashMap();
+ for (int i=0; i< pdList.list.size();i++)
+ {
+ PropertyDescription pd = pdList.list.get(i);
+ if (pd.getIsClassIdentifier())
+ props.put(pd.getName(),pd.getDefaultValue());
+ }
+ return props;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/scripting/ErrorInfo.java b/src/main/java/org/cristalise/kernel/scripting/ErrorInfo.java new file mode 100644 index 0000000..3ea4200 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/ErrorInfo.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.scripting;
+
+import java.util.ArrayList;
+
+/**************************************************************************
+ *
+ * $Revision: 1.2 $
+ * $Date: 2003/06/06 11:37:45 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class ErrorInfo {
+ ArrayList<String> msg;
+ boolean fatal = false;
+
+ public ErrorInfo() {
+ super();
+ msg = new ArrayList<String>();
+ }
+
+ public ErrorInfo(String error) {
+ this();
+ msg.add(error);
+ }
+
+ public void addError(String error) {
+ msg.add(error);
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer err = new StringBuffer();
+ for (String element : msg) {
+ err.append(element+"\n");
+ }
+ return err.toString();
+ }
+
+ public void setErrors(ArrayList<String> msg) {
+ this.msg = msg;
+ }
+
+ public ArrayList<String> getErrors() {
+ return msg;
+ }
+
+ public void setFatal() {
+ fatal=true;
+ }
+
+ public boolean getFatal() {
+ return fatal;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/scripting/Parameter.java b/src/main/java/org/cristalise/kernel/scripting/Parameter.java new file mode 100644 index 0000000..6b5e29a --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/Parameter.java @@ -0,0 +1,72 @@ +/**
+ * 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.scripting;
+
+
+/**************************************************************************
+* Place holder for the Parameter details to be passed to the script.
+**************************************************************************/
+public class Parameter {
+
+ private String name;
+ private Class<?> type;
+ private boolean initialised=false;
+
+ public Parameter(String name) {
+ this.name = name;
+ }
+
+ public Parameter(String name, Class<?> type) {
+ this.name = name;
+ this.type = type;
+ }
+
+ public void setName(String n)
+ {
+ name=n;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setType(Class<?> t)
+ {
+ type=t;
+ }
+
+ public Class<?> getType()
+ {
+ return type;
+ }
+
+ public void setInitialised(boolean state)
+ {
+ initialised=state;
+ }
+
+ public boolean getInitialised()
+ {
+ return initialised;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/scripting/ParameterException.java b/src/main/java/org/cristalise/kernel/scripting/ParameterException.java new file mode 100644 index 0000000..8ecf806 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/ParameterException.java @@ -0,0 +1,40 @@ +/**
+ * 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.scripting;
+
+public class ParameterException extends ScriptingEngineException {
+
+ /**
+ * Creates new <code>ParameterException</code> without detail message.
+ */
+ public ParameterException() {
+ }
+
+ /**
+ * Constructs an <code>ParameterException</code> with the specified detail message.
+ * @param msg the detail message.
+ */
+ public ParameterException(String msg) {
+ super(msg);
+ }
+}
+
+
diff --git a/src/main/java/org/cristalise/kernel/scripting/Script.java b/src/main/java/org/cristalise/kernel/scripting/Script.java new file mode 100644 index 0000000..9b0d402 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/Script.java @@ -0,0 +1,572 @@ +/**
+ * 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.scripting;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
+import javax.script.SimpleScriptContext;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.entity.agent.Job;
+import org.cristalise.kernel.entity.proxy.AgentProxy;
+import org.cristalise.kernel.entity.proxy.ItemProxy;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.LocalObjectLoader;
+import org.cristalise.kernel.utils.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+import org.xml.sax.InputSource;
+
+
+/**************************************************************************
+ *
+ * $Revision: 1.25 $
+ * $Date: 2005/10/05 07:39:37 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class Script
+{
+ String mScript = "";
+ CompiledScript mCompScript = null;
+ String mName;
+ Integer mVersion;
+ HashMap<String, Parameter> mInputParams = new HashMap<String, Parameter>();
+ HashMap<String, Parameter> mAllInputParams = new HashMap<String, Parameter>();
+ HashMap<String, Parameter> mOutputParams = new HashMap<String, Parameter>();
+ ArrayList<Script> mIncludes = new ArrayList<Script>();
+ ScriptEngine engine;
+ ScriptContext context;
+
+ /** For testing. Parses a given script xml, instead of loading it from Items.
+ * @param xml
+ * @throws ScriptParsingException
+ * @throws ParameterException
+ */
+ public Script(String name, int version, String xml) throws ScriptParsingException, ParameterException {
+ mName = name; mVersion = version;
+ parseScriptXML(xml);
+ }
+ /**
+ * Loads script xml and parses it for script source, parameters and output specifications.
+ * First tries to load the script from resource path /scriptFiles/scriptName_scriptVersion.xml
+ * If not found tries to find item at /desc/ScriptDesc/scriptName and load Viewpoint scriptVersion from it.
+ *
+ * For the specification of script xml, see the Script schema from resources.
+ *
+ * @param scriptName - name of the script
+ * @param scriptVersion - named version of the script (must be numbered viewpoint)
+ * @throws ScriptParsingException - when script not found (ScriptLoadingException) or xml is invalid (ScriptParsingException)
+ */
+ public Script(String scriptName, int scriptVersion, ScriptContext context) throws ScriptingEngineException
+ {
+ this(scriptName, scriptVersion);
+ this.context = context;
+ }
+
+ public Script(String scriptName, int scriptVersion) throws ScriptingEngineException
+ {
+ mName = scriptName;
+ mVersion = scriptVersion;
+ if (!scriptName.equals(""))
+ loadScript(mName, mVersion);
+ }
+
+ /**
+ * Creates a script executor for the supplied expression, bypassing the xml parsing bit
+ * Output class is forced to an object.
+ */
+ public Script(String lang, String expr, Class<?> returnType) throws ScriptingEngineException
+ {
+ mName = "<expr>";
+ setScriptEngine(lang);
+ mVersion = null;
+ addOutput(null, returnType);
+ setScript(expr);
+ }
+
+ /**
+ * Creates a script executor requiring an agent to be set. Used by module event scripts.
+ *
+ * @param lang - script language
+ * @param name - script name for debugging
+ * @param expr - the script to run
+ * @param agent - the agentproxy to pass into the script as 'agent'
+ * @throws ScriptingEngineException
+ */
+ public Script(String lang, String name, String expr, AgentProxy agent) throws ScriptingEngineException
+ {
+ this(lang, expr, Object.class);
+ mName = name;
+ addInputParam("agent", AgentProxy.class);
+ setInputParamValue("agent", agent);
+ }
+
+ public Script(String lang, String expr) throws ScriptingEngineException
+ {
+ this(lang, expr, Object.class);
+ }
+
+ public Script(ItemProxy object, AgentProxy subject, Job job) throws ScriptingEngineException
+ {
+ this(job.getActPropString("ScriptName"), getScriptVersion(job));
+ // set environment - this needs to be well documented for script developers
+ if (!mInputParams.containsKey("item"))
+ addInputParam("item", ItemProxy.class);
+ setInputParamValue("item", object);
+
+ if (!mInputParams.containsKey("agent"))
+ addInputParam("agent", AgentProxy.class);
+ setInputParamValue("agent", subject);
+
+ if (!mInputParams.containsKey("job"))
+ addInputParam("job", Job.class);
+ setInputParamValue("job", job);
+
+ if (!mOutputParams.containsKey("errors"))
+ addOutput("errors", ErrorInfo.class);
+ }
+
+ public static int getScriptVersion(Job job) {
+ String verStr = job.getActPropString("ScriptVersion");
+ if (verStr != null)
+ return Integer.parseInt(verStr);
+ else
+ return -1;
+ }
+
+ /**
+ * For consoles
+ *
+ * @param lang - script language
+ * @param agent - AgentProxy of the console user
+ * @param out - the output PrintStream for reporting results that don't go to the log
+ */
+ public Script(String lang, AgentProxy agent, PrintStream out) throws Exception {
+ setScriptEngine(lang);
+ Bindings beans = context.getBindings(ScriptContext.ENGINE_SCOPE);
+ beans.put("storage", Gateway.getStorage());
+ beans.put("db", Gateway.getStorage().getDb());
+ beans.put("proxy", Gateway.getProxyManager());
+ beans.put("lookup", Gateway.getLookup());
+ beans.put("orb", Gateway.getORB());
+ beans.put("agent", agent);
+ beans.put("output", out);
+ PrintWriter output = new PrintWriter(out);
+ context.setWriter(output);
+ context.setErrorWriter(output);
+ HashMap<String, String> consoleScripts = Gateway.getResource().getAllTextResources("textFiles/consoleScript."+lang+".txt");
+ for (String ns : consoleScripts.keySet()) {
+ try {
+ engine.put(ScriptEngine.FILENAME, ns+" init script");
+ engine.eval(consoleScripts.get(ns));
+ } catch (ScriptException ex) {
+ out.println("Exception parsing console script for "+(ns==null?"kernel":ns+" module"));
+ ex.printStackTrace(out);
+ }
+ }
+ addOutput(null, Object.class);
+
+ }
+
+ public void setScriptEngine(String lang) throws ScriptingEngineException {
+ engine = new ScriptEngineManager(getClass().getClassLoader()).getEngineByName(lang);
+ if (engine==null)
+ throw new ScriptingEngineException("No script engine for '"+lang+"' found.");
+ Bindings beans = engine.createBindings();
+ context = new SimpleScriptContext();
+ context.setBindings(beans, ScriptContext.ENGINE_SCOPE);
+ engine.setContext(context);
+ }
+
+ private void loadScript(String scriptName, int scriptVersion) throws ScriptingEngineException
+ {
+ try
+ {
+ mName = scriptName;
+ mVersion = scriptVersion;
+ parseScriptXML(LocalObjectLoader.getScript(scriptName, scriptVersion));
+ }
+ catch (ObjectNotFoundException e)
+ {
+ throw new ScriptingEngineException("Script '"+scriptName+"' not found");
+ }
+ }
+
+ /**
+ * Extracts script data from script xml.
+ *
+ * @param scriptXML
+ * @throws ScriptParsingException - when script is invalid
+ */
+ private void parseScriptXML(String scriptXML) throws ScriptParsingException, ParameterException
+ {
+ Document scriptDoc = null;
+
+ // get the DOM document from the XML
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ try
+ {
+ DocumentBuilder domBuilder = factory.newDocumentBuilder();
+ scriptDoc = domBuilder.parse(new InputSource(new StringReader(scriptXML)));
+ }
+ catch (Exception ex)
+ {
+ throw new ScriptParsingException("Error parsing Script XML : " + ex.toString());
+ }
+
+ Element root = scriptDoc.getDocumentElement();
+ NodeList scriptNodes = root.getChildNodes();
+ for (int i = 0; i < scriptNodes.getLength(); i++)
+ {
+ Element currentParam;
+ String paramName;
+
+ try
+ {
+ currentParam = (Element) scriptNodes.item(i);
+ }
+ catch (ClassCastException ex)
+ {
+ // not an element, skip
+ continue;
+ }
+ paramName = currentParam.getTagName();
+ Logger.msg(9, "Script.parseScriptXML() - Found element " + paramName);
+
+ // Process script parameters
+
+ // input parameter
+ if (paramName.equals("param"))
+ {
+ if (!(currentParam.hasAttribute("name") && currentParam.hasAttribute("type")))
+ throw new ScriptParsingException("Script Input Param incomplete, must have name and type");
+ addInputParam(currentParam.getAttribute("name"), currentParam.getAttribute("type"));
+ }
+
+ //load output type
+ else if (paramName.equals("output"))
+ {
+ if (!currentParam.hasAttribute("type"))
+ throw new ScriptParsingException("Script Output declaration incomplete, must have type");
+ addOutput(currentParam.getAttribute("name"), currentParam.getAttribute("type"));
+ }
+
+ //load any included scripts
+ else if (paramName.equals("include"))
+ {
+ if (!(currentParam.hasAttribute("name") && currentParam.hasAttribute("version")))
+ throw new ScriptParsingException("Script include declaration incomplete, must have name and version");
+ String includeName = currentParam.getAttribute("name");
+ String includeVersion = currentParam.getAttribute("version");
+ try {
+ Script includedScript = new Script(includeName, Integer.parseInt(includeVersion), context);
+ mIncludes.add(includedScript);
+ for (Parameter includeParam : includedScript.getInputParams().values()) {
+ addIncludedInputParam(includeParam.getName(), includeParam.getType());
+ }
+ } catch (NumberFormatException e) {
+ throw new ScriptParsingException("Invalid version in imported script name:'"+includeName+"', version:'"+includeVersion+"'");
+ } catch (ScriptingEngineException e) {
+ throw new ScriptParsingException("Error parsing imported script '"+includeName+"', version '"+includeVersion+"': "+e.getMessage());
+ }
+
+ }
+ //load Script
+ else if (paramName.equals("script"))
+ {
+ if (!currentParam.hasAttribute("language"))
+ throw new ScriptParsingException("Script data incomplete, must specify scripting language");
+ Logger.msg(6, "Script.parseScriptXML() - Script Language: " + currentParam.getAttribute("language"));
+ try {
+ setScriptEngine(currentParam.getAttribute("language"));
+ } catch (ScriptingEngineException ex) {
+ throw new ScriptParsingException(ex.getMessage());
+ }
+
+ // get script source
+ NodeList scriptChildNodes = currentParam.getChildNodes();
+ if (scriptChildNodes.getLength() != 1)
+ throw new ScriptParsingException("More than one child element found under script tag. Script characters may need escaping - suggest convert to CDATA section");
+ if (scriptChildNodes.item(0) instanceof Text)
+ setScript(((Text) scriptChildNodes.item(0)).getData());
+ else
+ throw new ScriptParsingException("Child element of script tag was not text");
+ Logger.msg(6, "Script.parseScriptXML() - script:" + mScript);
+ }
+ }
+ }
+
+ protected void addInputParam(String name, String type) throws ParameterException
+ {
+ try
+ {
+ addInputParam(name, Gateway.getResource().getClassForName(type));
+ }
+ catch (ClassNotFoundException ex)
+ {
+ throw new ParameterException("Input parameter " + name + " specifies class " + type + " which was not found.");
+ }
+ }
+
+ protected void addInputParam(String name, Class<?> type) throws ParameterException
+ {
+ Parameter inputParam = new Parameter(name, type);
+
+
+
+ Logger.msg(6, "ScriptExecutor.parseScriptXML() - declared parameter " + name + " (" + type + ")");
+ //add parameter to hashtable
+ mInputParams.put(inputParam.getName(), inputParam);
+ mAllInputParams.put(inputParam.getName(), inputParam);
+
+ }
+
+ protected void addIncludedInputParam(String name, Class<?> type) throws ParameterException
+ {
+ // check if we already have it
+ if (mAllInputParams.containsKey(name)) {
+ Parameter existingParam = mAllInputParams.get(name);
+ // check the types match
+ if (existingParam.getType() == type)
+ return; // matches
+ else // error
+ throw new ParameterException("Parameter conflict. Parameter'"+name+"' is declared as "
+ +existingParam.getType().getName()+" is declared in another script as "+type.getName());
+ }
+
+ Parameter inputParam = new Parameter(name);
+ inputParam.setType(type);
+
+ //add parameter to hashtable
+ mAllInputParams.put(inputParam.getName(), inputParam);
+
+ }
+
+ protected void addOutput(String name, String type) throws ParameterException
+ {
+ try
+ {
+ addOutput(name, Gateway.getResource().getClassForName(type));
+ }
+ catch (ClassNotFoundException ex) {
+ throw new ParameterException("Output parameter " + name + " specifies class " + type + " which was not found.");
+ }
+ }
+
+ protected void addOutput(String name, Class<?> type) throws ParameterException
+ {
+ String outputName = name;
+
+ Parameter outputParam = new Parameter(name, type);
+
+ if (mOutputParams.containsKey(outputName))
+ throw new ParameterException("Output parameter '"+outputName+"' declared more than once.");
+
+ mOutputParams.put(outputName, outputParam);
+
+ }
+
+ /**
+ * Gets all declared parameters
+ * @return HashMap of String (name), org.cristalise.kernel.scripting.Parameter (param)
+ * @see org.cristalise.kernel.scripting.Parameter
+ */
+ public HashMap<String, Parameter> getInputParams()
+ {
+ return mInputParams;
+ }
+
+ /**
+ * Gets all declared parameters, including those of imported scripts
+ * @return HashMap of String (name), org.cristalise.kernel.scripting.Parameter (param)
+ * @see org.cristalise.kernel.scripting.Parameter
+ */
+ public HashMap<String, Parameter> getAllInputParams()
+ {
+ return mAllInputParams;
+ }
+
+ /**
+ * Submits an input parameter to the script. Must be declared by name and type in the script XML.
+ *
+ * @param name - input parameter name from the script xml
+ * @param value - object to use for this parameter
+ * @throws ParameterException - name not found or wrong type
+ */
+ public void setInputParamValue(String name, Object value) throws ParameterException
+ {
+ Parameter param = mInputParams.get(name);
+
+ if (!mAllInputParams.containsKey(name))
+ throw new ParameterException("Parameter " + name + " not found in parameter list");
+
+ if (param != null) { // param is in this script
+ if (value.getClass() != param.getType())
+ throw new ParameterException(
+ "Parameter " + name + " is wrong type \n" + "Required: " + param.getType().toString() + "\n" + "Supplied: " + value.getClass().toString());
+ context.getBindings(ScriptContext.ENGINE_SCOPE).put(name, value);
+ Logger.msg(7, "Script.setInputParamValue() - " + name + ": " + value.toString());
+ param.setInitialised(true);
+ }
+
+ // pass param down to child scripts
+ for (Script importScript : mIncludes) {
+ importScript.setInputParamValue(name, value);
+ }
+ }
+
+ /**
+ * Executes the script with the submitted parameters. All declared input parametes should have been set first.
+ *
+ * @return The return value depends on the way the output type was declared in the script xml.
+ * <ul><li>If there was no output class declared then null is returned
+ * <li>If a class was declared, but not named, then the object returned by the script is checked
+ * to be of that type, then returned.
+ * <li>If the output value was named and typed, then an object of that class is created and
+ * passed to the script as an input parameter. The script should set this before it returns.
+ * </ul>
+ * @throws ScriptingEngineException - input parameters weren't set, there was an error executing the script, or the output was invalid
+ */
+ public Object execute() throws ScriptingEngineException
+ {
+
+ // check input params
+ StringBuffer missingParams = new StringBuffer();
+ for (Parameter thisParam : mInputParams.values()) {
+ if (!thisParam.getInitialised())
+ missingParams.append(thisParam.getName()).append("\n");
+ }
+ // croak if any missing
+ if (missingParams.length() > 0)
+ throw new ScriptingEngineException("Execution aborted, the following declared parameters were not set: \n" + missingParams.toString());
+
+ for (Parameter outputParam : mOutputParams.values()) {
+ if (outputParam.getName() == null || outputParam.getName().length()==0) continue; // If the name is null then it's the return type. don't pre-register it
+ Logger.msg(8, "Script.setOutput() - Initialising output bean '" + outputParam.getName() + "'");
+ Object emptyObject;
+ try {
+ emptyObject = outputParam.getType().newInstance();
+ } catch (Exception e) {
+ emptyObject = null;
+ }
+ context.getBindings(ScriptContext.ENGINE_SCOPE).put(outputParam.getName(), emptyObject);
+
+ }
+
+ // execute the child scripts
+ for (Script importScript : mIncludes) {
+ if (Logger.doLog(8))
+ Logger.msg(8, "Import script:\n"+importScript.mScript);
+ importScript.execute();
+ }
+
+ // run the script
+ Object returnValue = null;
+ try
+ {
+ Logger.msg(7, "Script.execute() - Executing script");
+ if (Logger.doLog(8))
+ Logger.msg(8, "Script:\n"+mScript);
+
+ if (engine == null)
+ throw new ScriptingEngineException("Script engine not set. Cannot execute scripts.");
+ engine.put(ScriptEngine.FILENAME, mName);
+ if (mCompScript != null)
+ returnValue = mCompScript.eval();
+ else
+ returnValue = engine.eval(mScript);
+ Logger.msg(7, "Script.execute() - script returned \"" + returnValue + "\"");
+ }
+ catch (Throwable ex)
+ {
+ throw new ScriptingEngineException("Error executing script: " + ex.getMessage());
+ }
+
+ // if no outputs are defined, return null
+ if (mOutputParams.size() == 0) {
+ Logger.msg(4, "Script.execute() - No output params. Returning null.");
+ return null;
+ }
+
+ HashMap<String, Object> outputs = new HashMap<String, Object>();
+
+ for (Parameter outputParam : mOutputParams.values()) {
+ String outputName = outputParam.getName();
+ Object outputValue;
+ if (outputName == null || outputName.length()==0)
+ outputValue = returnValue;
+ else
+ outputValue = context.getBindings(ScriptContext.ENGINE_SCOPE).get(outputParam.getName());
+ Logger.msg(4, "Script.execute() - Output parameter "+outputName+"="+(outputValue==null?"null":outputValue.toString()));
+
+ // check the class
+ if (outputValue!=null && !(outputParam.getType().isInstance(outputValue)))
+ throw new ScriptingEngineException(
+ "Script output "+outputName+" was not null or instance of " + outputParam.getType().getName() + ", it was a " + outputValue.getClass().getName());
+
+ Logger.msg(8, "Script.execute() - output "+outputValue);
+ if (mOutputParams.size() == 1) {
+ Logger.msg(6, "Script.execute() - only one parameter, returning "+(outputValue==null?"null":outputValue.toString()));
+ return outputValue;
+ }
+ outputs.put(outputParam.getName(), outputValue);
+ }
+
+ return outputs;
+ }
+
+ public void setScript(String script) throws ScriptParsingException {
+ mScript = script;
+ if (engine instanceof Compilable) {
+ try {
+ Logger.msg(1, "Compiling script "+mName);
+ engine.put(ScriptEngine.FILENAME, mName);
+ mCompScript = ((Compilable)engine).compile(mScript);
+ } catch (ScriptException e) {
+ throw new ScriptParsingException(e.getMessage());
+ }
+ }
+ }
+
+ static public void main(String[] args) {
+ for(ScriptEngineFactory sef: new ScriptEngineManager().getEngineFactories()) {
+ System.out.println(sef.getEngineName()+" v"+sef.getEngineVersion()+" using "+sef.getLanguageName()+" v"+sef.getLanguageVersion()+" "+sef.getNames());
+ }
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/scripting/ScriptConsole.java b/src/main/java/org/cristalise/kernel/scripting/ScriptConsole.java new file mode 100644 index 0000000..51c8496 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/ScriptConsole.java @@ -0,0 +1,234 @@ +/**
+ * 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.scripting;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.InterruptedIOException;
+import java.io.PrintStream;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+import java.util.StringTokenizer;
+
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+
+import org.cristalise.kernel.process.AbstractMain;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.utils.Logger;
+import org.cristalise.kernel.utils.server.SocketHandler;
+
+
+/**************************************************************************
+ *
+ * $Revision: 1.16 $
+ * $Date: 2005/08/31 07:20:40 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+
+
+
+public class ScriptConsole implements SocketHandler {
+ BufferedReader input;
+ PrintStream output;
+ Socket socket = null;
+ ScriptEngine engine;
+ Bindings beans;
+ static ArrayList<String> securityHosts = new ArrayList<String>();
+ public static final short NONE = 0;
+ public static final short ALLOW = 1;
+ public static final short DENY = 2;
+ static short securityMode;
+
+ static {
+ securityMode = ALLOW;
+ String hosts = Gateway.getProperties().getString("ItemServer.Console.allow");
+ if (hosts == null || hosts.equals("")) {
+ securityMode = DENY;
+ hosts = Gateway.getProperties().getString("ItemServer.Console.deny");
+ }
+ if (hosts == null || hosts.equals("")) { // by default only allow localhost
+ securityMode = ALLOW;
+ securityHosts.add("localhost");
+ securityHosts.add("127.0.0.1");
+ securityHosts.add("0:0:0:0:0:0:0:1");//ipv6
+ }
+ else {
+ StringTokenizer tok = new StringTokenizer(hosts, ",");
+ while(tok.hasMoreTokens()) {
+ String wHostName = tok.nextToken();
+ try {
+ securityHosts.add(InetAddress.getByName(wHostName).getHostAddress());
+ if ("localhost".equals(wHostName)){
+ securityHosts.add("127.0.0.1");
+ securityHosts.add("0:0:0:0:0:0:0:1");//ipv6
+ }
+ } catch (UnknownHostException ex) {
+ Logger.error("Host not found "+ex.getMessage());
+ }
+ }
+ }
+ }
+ public ScriptConsole() {
+ }
+
+ @Override
+ public String getName() {
+ return "Script Console";
+ }
+
+ @Override
+ public boolean isBusy() {
+ return (socket != null);
+ }
+
+ @Override
+ public void setSocket(Socket newSocket) {
+ try {
+ input = new BufferedReader(new InputStreamReader(newSocket.getInputStream()));
+ output = new PrintStream(newSocket.getOutputStream());
+ newSocket.setSoTimeout(0);
+ socket = newSocket;
+ } catch (IOException ex) {
+ try {
+ newSocket.close();
+ } catch (IOException ex2) {
+ }
+ socket = null;
+ return;
+ }
+ }
+
+ @Override
+ public void shutdown() {
+ Socket closingSocket = socket;
+ socket = null;
+ if (closingSocket == null)
+ return;
+ try {
+ Logger.removeLogStream(output);
+ closingSocket.shutdownInput();
+ closingSocket.shutdownOutput();
+ closingSocket.close();
+ Logger.msg("Script console to "+closingSocket.getInetAddress()+" closed");
+ } catch (IOException e) {
+ Logger.error("Script Console to " + closingSocket.getInetAddress() + " - Error closing.");
+ Logger.error(e);
+ }
+ }
+
+
+ @Override
+ public void run() {
+ // check permission
+ boolean allowed = true;
+ if (securityMode!=NONE) {
+ //ogattaz
+ String wHostAddress = socket.getInetAddress().getHostAddress();
+ if (securityHosts.contains(wHostAddress)) {
+ if (securityMode==DENY)
+ allowed = false;
+ }
+ else if (securityMode==ALLOW)
+ allowed = false;
+ }
+
+ if (!allowed) {
+ Logger.error("Host "+socket.getInetAddress()+" access denied");
+ output.println("Host "+socket.getInetAddress()+" access denied");
+ shutdown();
+ return;
+ }
+
+ // get system objects
+ try {
+ Logger.addLogStream(output, 0);
+ Script context;
+ try {
+ context = new Script("javascript", null, output);
+ } catch (Exception ex) {
+ output.println("Error initializing console script context");
+ ex.printStackTrace(output);
+ shutdown();
+ return;
+ }
+
+ StringBuffer commandBuffer = new StringBuffer();
+ while (socket != null) {
+
+ output.println();
+ output.print('>');
+
+ String command = null;
+ boolean gotCommand = false;
+ while (!gotCommand) {
+ try {
+ command = input.readLine();
+ gotCommand = true;
+ } catch (InterruptedIOException ex) {
+ }
+ }
+ if (command == null) // disconnected
+ shutdown();
+ else {
+ if (command.equals("exit")) {
+ shutdown();
+ continue;
+ }
+ try {
+ if (command.endsWith("\\")) {
+ commandBuffer.append(command.substring(0,command.length()-1));
+ continue;
+ }
+ commandBuffer.append(command);
+ command = commandBuffer.toString();
+ commandBuffer = new StringBuffer();
+ Logger.msg("Console command from "+socket.getInetAddress()+": "+command);
+
+ // process control
+ if (command.equals("shutdown")) {
+ AbstractMain.shutdown(0);
+ }
+ else {
+ context.setScript(command);
+ Object response = context.execute();
+ if (response == null)
+ output.println("Ok");
+ else
+ output.println(response);
+ }
+ } catch (Throwable ex) {
+ ex.printStackTrace(output);
+ }
+ output.flush();
+ }
+ }
+ } catch (IOException ex) {
+ Logger.error("IO Exception reading from script console socket");
+ shutdown();
+ }
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/scripting/ScriptErrorException.java b/src/main/java/org/cristalise/kernel/scripting/ScriptErrorException.java new file mode 100644 index 0000000..34e58de --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/ScriptErrorException.java @@ -0,0 +1,50 @@ +/**
+ * 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.scripting;
+
+public class ScriptErrorException extends java.lang.Exception {
+
+ /**
+ * Creates new <code>sciptingEngineException</code> without detail message.
+ */
+ ErrorInfo errors;
+ public ScriptErrorException() {
+ }
+
+ /**
+ * Constructs an <code>sciptingEngineException</code> with the specified detail message.
+ * @param msg the detail message.
+ */
+ public ScriptErrorException(String msg) {
+ super(msg);
+ }
+
+ public ScriptErrorException(ErrorInfo errors) {
+ super(errors.toString());
+ this.errors = errors;
+ }
+
+ public ErrorInfo getErrors() {
+ return errors;
+ }
+}
+
+
diff --git a/src/main/java/org/cristalise/kernel/scripting/ScriptLoadingException.java b/src/main/java/org/cristalise/kernel/scripting/ScriptLoadingException.java new file mode 100644 index 0000000..933aca6 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/ScriptLoadingException.java @@ -0,0 +1,44 @@ +/**
+ * 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.scripting;
+
+/**************************************************************************
+ *
+ * $Revision: 1.1 $
+ * $Date: 2003/04/06 12:32:51 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public class ScriptLoadingException extends ScriptingEngineException {
+ /**
+ *
+ */
+ public ScriptLoadingException() {
+ super();
+ }
+ /**
+ *
+ */
+ public ScriptLoadingException(String msg) {
+ super(msg);
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/scripting/ScriptParsingException.java b/src/main/java/org/cristalise/kernel/scripting/ScriptParsingException.java new file mode 100644 index 0000000..bcbf384 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/ScriptParsingException.java @@ -0,0 +1,41 @@ +/**
+ * 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.scripting;
+
+public class ScriptParsingException extends ScriptingEngineException {
+
+ /**
+ * Creates new <code>ScriptParsingException</code> without detail message.
+ */
+ public ScriptParsingException() {
+ }
+
+
+ /**
+ * Constructs an <code>ScriptParsingException</code> with the specified detail message.
+ * @param msg the detail message.
+ */
+ public ScriptParsingException(String msg) {
+ super(msg);
+ }
+}
+
+
diff --git a/src/main/java/org/cristalise/kernel/scripting/ScriptingEngineException.java b/src/main/java/org/cristalise/kernel/scripting/ScriptingEngineException.java new file mode 100644 index 0000000..e06e022 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/scripting/ScriptingEngineException.java @@ -0,0 +1,40 @@ +/**
+ * 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.scripting;
+
+public class ScriptingEngineException extends java.lang.Exception {
+
+ /**
+ * Creates new <code>sciptingEngineException</code> without detail message.
+ */
+ public ScriptingEngineException() {
+ }
+
+ /**
+ * Constructs an <code>sciptingEngineException</code> with the specified detail message.
+ * @param msg the detail message.
+ */
+ public ScriptingEngineException(String msg) {
+ super(msg);
+ }
+}
+
+
diff --git a/src/main/java/org/cristalise/kernel/utils/ActDefCache.java b/src/main/java/org/cristalise/kernel/utils/ActDefCache.java new file mode 100644 index 0000000..4cb5c8f --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/ActDefCache.java @@ -0,0 +1,68 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+/**
+ *
+ */
+package org.cristalise.kernel.utils;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.proxy.ItemProxy;
+import org.cristalise.kernel.lifecycle.ActivityDef;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.persistency.outcome.Viewpoint;
+import org.cristalise.kernel.process.Gateway;
+
+
+public class ActDefCache extends DescriptionObjectCache<ActivityDef> {
+
+
+ @Override
+ public String getDefRoot() {
+ return "/desc/ActivityDesc";
+ }
+
+ @Override
+ public ActivityDef loadObject(String name, int version, ItemProxy proxy) throws ObjectNotFoundException, InvalidDataException {
+ ActivityDef thisActDef;
+ String actType = proxy.getProperty("Complexity");
+ Viewpoint actView = (Viewpoint)proxy.getObject(ClusterStorage.VIEWPOINT + "/" + actType + "ActivityDef/" + version);
+ String marshalledAct;
+ try {
+ marshalledAct = actView.getOutcome().getData();
+ } catch (PersistencyException ex) {
+ Logger.error(ex);
+ throw new ObjectNotFoundException("Problem loading "+name+" v"+version+": "+ex.getMessage());
+ }
+ try {
+ thisActDef = (ActivityDef)Gateway.getMarshaller().unmarshall(marshalledAct);
+ thisActDef.getProperties().put("Version", version);
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new InvalidDataException("Could not unmarshall '"+name+"' v"+version+": "+ex.getMessage());
+ }
+ thisActDef.setName(name);
+ thisActDef.setVersion(version);
+ return thisActDef;
+ }
+
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/utils/CastorArrayList.java b/src/main/java/org/cristalise/kernel/utils/CastorArrayList.java new file mode 100644 index 0000000..4a57bff --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/CastorArrayList.java @@ -0,0 +1,74 @@ +/**
+ * 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.utils;
+
+import java.util.ArrayList;
+
+/**************************************************************************
+ * Wrapper for a root element to an ArrayList. Castor Marshalls arraylists
+ * as multiple elements, so this class is needed to provide a root element
+ * to stop it crashing.
+ *
+ * $Revision: 1.4 $
+ * $Date: 2004/01/22 11:17:42 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+//
+abstract public class CastorArrayList<E> {
+ public ArrayList<E> list;
+
+ public CastorArrayList() {
+ super();
+ list = new ArrayList<E>();
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((list == null) ? 0 : list.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;
+ CastorArrayList<?> other = (CastorArrayList<?>) obj;
+ if (list == null) {
+ if (other.list != null)
+ return false;
+ } else if (!list.equals(other.list))
+ return false;
+ return true;
+ }
+
+ public CastorArrayList(ArrayList<E> list) {
+ this();
+ this.list = list;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/CastorHashMap.java b/src/main/java/org/cristalise/kernel/utils/CastorHashMap.java new file mode 100644 index 0000000..16dc90e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/CastorHashMap.java @@ -0,0 +1,101 @@ +/**
+ * 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.utils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+
+// This subclass of hashtable can be marshalled
+// and unmarshalled with Castor
+public class CastorHashMap extends HashMap<String,Object>
+{
+ public CastorHashMap()
+ {
+ clear();
+ }
+
+ ArrayList<String> abstractPropNames = new ArrayList<String>();
+
+ public KeyValuePair[] getKeyValuePairs()
+ {
+ int numKeys = size();
+
+ KeyValuePair[] keyValuePairs = new KeyValuePair[numKeys];
+ Iterator<String> keyIter = keySet().iterator();
+ int i = 0;
+
+ for(i=0; i<numKeys; i++)
+ if (keyIter.hasNext())
+ {
+ String name = keyIter.next();
+ keyValuePairs[i] = new KeyValuePair(name ,get(name), abstractPropNames.contains(name));
+ }
+
+ return keyValuePairs;
+ }
+
+
+ public void setKeyValuePairs(KeyValuePair[] keyValuePairs)
+ {
+ int i = 0;
+
+ // Clears this hashtable so that it contains no keys
+ clear();
+
+ // Put each key value pair into this hashtable
+ for(i=0; i<keyValuePairs.length; i++)
+ {
+ setKeyValuePair(keyValuePairs[i]);
+ }
+ }
+
+ @Override
+ public void clear() {
+ super.clear();
+ abstractPropNames = new ArrayList<String>();
+ }
+
+
+ public void setKeyValuePair(KeyValuePair keyValuePair)
+ {
+ put(keyValuePair.getKey(), keyValuePair.getValue());
+ if (keyValuePair.isAbstract())
+ abstractPropNames.add(keyValuePair.getKey());
+ else
+ abstractPropNames.remove(keyValuePair.getKey());
+ }
+
+ public ArrayList<String> getAbstract() {
+ return abstractPropNames;
+ }
+
+
+ public void put(String key, Object value, boolean isAbstract) {
+ super.put(key, value);
+ if (isAbstract)
+ abstractPropNames.add(key);
+ else
+ abstractPropNames.remove(key);
+
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/CastorXMLUtility.java b/src/main/java/org/cristalise/kernel/utils/CastorXMLUtility.java new file mode 100644 index 0000000..2d8ec9d --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/CastorXMLUtility.java @@ -0,0 +1,188 @@ +/**
+ * 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.utils;
+
+//Java
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.HashSet;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.persistency.outcome.Outcome;
+import org.cristalise.kernel.process.resource.ResourceLoader;
+import org.exolab.castor.mapping.Mapping;
+import org.exolab.castor.mapping.MappingException;
+import org.exolab.castor.xml.MarshalException;
+import org.exolab.castor.xml.Marshaller;
+import org.exolab.castor.xml.Unmarshaller;
+import org.exolab.castor.xml.ValidationException;
+import org.exolab.castor.xml.XMLContext;
+
+
+
+/**************************************************************************
+ * Loads all mapfiles, and wraps marshalling/unmarshalling
+ *
+ * @author $Author: abranson $ $Date: 2004/10/20 14:10:21 $
+ * @version $Revision: 1.12 $
+ **************************************************************************/
+public class CastorXMLUtility
+{
+
+ public static final String CASTOR_XML_SERIALIZER_FACTORY = "org.exolab.castor.xml.serializer.factory";
+ private XMLContext mappingContext;
+
+ /**
+ * Looks for a file called 'index.xml' at the given URL, and loads every
+ * file listed in there by relative path
+ *
+ * @param aResourceLoader
+ * the resource loader able to return the right class loader
+ * @param aAppProperties
+ * the application properties containing optional castor
+ * configuration
+ * @param mapURL
+ * the root URL for the mapfiles
+ * @throws InvalidDataException
+ */
+ public CastorXMLUtility(final ResourceLoader aResourceLoader,
+ final Properties aAppProperties, final URL mapURL)
+ throws InvalidDataException {
+
+
+ // load index
+ Logger.msg(3,String.format( "CastorXMLUtility.<init> Loading maps from [%s]",mapURL));
+ String index;
+ try {
+ index = FileStringUtility.url2String( new URL(mapURL, "index") );
+ } catch (Exception e) {
+ throw new InvalidDataException(String.format("Could not load map index from [%s]",mapURL));
+ }
+
+ // retrieve the class loader of the class "CastorXMLUtility"
+ ClassLoader defaultClassLoader = aResourceLoader
+ .getClassLoader(CastorXMLUtility.class.getName());
+
+ Logger.msg(3, String.format(
+ "CastorXMLUtility.<init>: defaultClassLoader=[%s]",
+ defaultClassLoader));
+
+
+ StringTokenizer sTokenizer = new StringTokenizer(index);
+ int wNbMap = sTokenizer.countTokens();
+
+ // init the castor mapping using the classloader of the class "CastorXMLUtility"
+ Mapping thisMapping = new Mapping(defaultClassLoader);
+ HashSet<String> loadedMapURLs = new HashSet<String>();
+ try {
+ int wMapIdx=0;
+ while( sTokenizer.hasMoreTokens() ) {
+ String thisMap = sTokenizer.nextToken();
+ String thisMapURL = new URL(mapURL, thisMap).toString();
+ wMapIdx++;
+ if( !loadedMapURLs.contains(thisMapURL) ) {
+ Logger.msg( 3,
+ String.format("CastorXMLUtility.<init>: Adding mapping file (%d/%d):[%s]", wMapIdx, wNbMap, thisMapURL));
+ thisMapping.loadMapping( new URL(thisMapURL) );
+ loadedMapURLs.add( thisMapURL );
+ }
+ else {
+ Logger.msg(3,"Map file already loaded:"+thisMapURL);
+ }
+ }
+
+ mappingContext = new XMLContext();
+
+ mappingContext.setClassLoader(defaultClassLoader);
+
+ // if the aAppProperties contains castor properties then
+ if (aAppProperties!= null && aAppProperties.containsKey(CASTOR_XML_SERIALIZER_FACTORY)) {
+
+ mappingContext.setProperty(CASTOR_XML_SERIALIZER_FACTORY,
+ aAppProperties
+ .getProperty(CASTOR_XML_SERIALIZER_FACTORY));
+
+ Logger.msg(3, String.format(
+ "CastorXMLUtility.<init>: castor prop: %s=[%s]",
+ CASTOR_XML_SERIALIZER_FACTORY, mappingContext
+ .getProperty(CASTOR_XML_SERIALIZER_FACTORY)));
+
+ }
+
+ mappingContext.addMapping(thisMapping);
+ } catch (MappingException ex) {
+ Logger.error(ex);
+ throw new InvalidDataException("XML Mapping files are not valid: "+ex.getMessage());
+ } catch (MalformedURLException ex) {
+ Logger.error(ex);
+ throw new InvalidDataException("Mapping file location invalid: "+ex.getMessage());
+ } catch (IOException ex) {
+ Logger.error(ex);
+ throw new InvalidDataException("Could not read XML mapping files: "+ex.getMessage());
+ }
+
+ Logger.msg(1, String.format("Loaded [%d] maps from [%s]", loadedMapURLs.size(), mapURL));
+ }
+
+ /**************************************************************************
+ * Marshalls a mapped object to string. The mapping must be loaded before.
+ * See updateMapping().
+ **************************************************************************/
+ public String marshall( Object obj )
+ throws IOException,
+ MappingException,
+ MarshalException,
+ ValidationException
+ {
+ if (obj == null) return "<NULL/>";
+ if (obj instanceof Outcome)
+ return ((Outcome)obj).getData();
+ StringWriter sWriter = new StringWriter();
+ Marshaller marshaller = mappingContext.createMarshaller();
+
+ marshaller.setWriter(sWriter);
+ marshaller.setMarshalAsDocument( false );
+ marshaller.marshal( obj );
+
+ return sWriter.toString();
+ }
+
+ /**************************************************************************
+ * Unmarshalls a mapped object from string. The mapping must be loaded before.
+ * See updateMapping().
+ **************************************************************************/
+ public Object unmarshall( String data )
+ throws IOException,
+ MappingException,
+ MarshalException,
+ ValidationException
+ {
+ if (data.equals("<NULL/>")) return null;
+ StringReader sReader = new StringReader( data );
+ Unmarshaller unmarshaller = mappingContext.createUnmarshaller();
+ return unmarshaller.unmarshal( sReader );
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/DateUtility.java b/src/main/java/org/cristalise/kernel/utils/DateUtility.java new file mode 100644 index 0000000..faa77e3 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/DateUtility.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.utils;
+import org.cristalise.kernel.common.GTimeStamp;
+/**
+ * @version $Revision: 1.8 $ $Date: 2005/05/10 15:14:55 $
+ * @author $Author: abranson $
+ */
+public class DateUtility
+{
+ public static GTimeStamp setToNow(GTimeStamp date)
+ {
+ java.util.Calendar now = java.util.Calendar.getInstance();
+ date.mYear = now.get(java.util.Calendar.YEAR);
+ date.mMonth = now.get(java.util.Calendar.MONTH) + 1;
+ date.mDay = now.get(java.util.Calendar.DAY_OF_MONTH);
+ date.mHour = now.get(java.util.Calendar.HOUR_OF_DAY);
+ date.mMinute = now.get(java.util.Calendar.MINUTE);
+ date.mSecond = now.get(java.util.Calendar.SECOND);
+ date.mTimeOffset = now.get(java.util.Calendar.ZONE_OFFSET);
+ return date;
+ }
+
+ public static String getSQLFormat(GTimeStamp timeStamp)
+ {
+ StringBuffer time = new StringBuffer().append(timeStamp.mYear).append("-");
+ if (timeStamp.mMonth < 10)
+ time.append("0");
+ time.append(timeStamp.mMonth).append("-");
+ if (timeStamp.mDay < 10)
+ time.append("0");
+ time.append(timeStamp.mDay).append(" ");
+ if (timeStamp.mHour < 10)
+ time.append("0");
+ time.append(timeStamp.mHour).append(":");
+ if (timeStamp.mMinute < 10)
+ time.append("0");
+ time.append(timeStamp.mMinute).append(":");
+ if (timeStamp.mSecond < 10)
+ time.append("0");
+ time.append(timeStamp.mSecond);
+ return time.toString();
+ }
+
+ public static int getNbDayInYear(GTimeStamp date)
+ {
+ int centuary = date.mYear / 100;
+ int cdivby4 = centuary / 4;
+ int ydivby4 = date.mYear / 4;
+ if (centuary * 100 - date.mYear == 0)
+ {
+ if (centuary == cdivby4 * 4)
+ return 366;
+ else
+ return 365;
+ }
+ else if (date.mYear == ydivby4 * 4)
+ return 366;
+ else
+ return 365;
+ }
+ public static int getNbDayInMonth(GTimeStamp date)
+ {
+ switch (date.mMonth)
+ {
+ case 2 :
+ if (getNbDayInYear(date) == 365)
+ return 28;
+ else
+ return 29;
+ case 4 :
+ return 30;
+ case 6 :
+ return 30;
+ case 9 :
+ return 30;
+ case 11 :
+ return 30;
+ default :
+ return 31;
+ }
+ }
+
+ public static long diff(GTimeStamp date1, GTimeStamp date2)
+ {
+ GTimeStamp tmp = new GTimeStamp(date1.mYear, date1.mMonth, date1.mDay, date1.mHour, date1.mMinute, date1.mSecond, date1.mTimeOffset);
+ while (tmp.mYear - date2.mYear < 0)
+ {
+ while (tmp.mMonth < 13)
+ {
+ tmp.mDay = tmp.mDay - getNbDayInMonth(tmp);
+ tmp.mMonth++;
+ }
+ tmp.mMonth = 1;
+ tmp.mYear++;
+ }
+ while (tmp.mYear - date2.mYear > 0)
+ {
+ while (tmp.mMonth > 1)
+ {
+ tmp.mMonth--;
+ tmp.mDay = tmp.mDay + getNbDayInMonth(tmp);
+ }
+ tmp.mMonth = 12;
+ tmp.mDay = tmp.mDay + getNbDayInMonth(tmp);
+ tmp.mYear--;
+ }
+ while (tmp.mMonth - date2.mMonth < 0)
+ {
+ tmp.mDay = tmp.mDay - getNbDayInMonth(tmp);
+ tmp.mMonth++;
+ }
+ while (tmp.mMonth - date2.mMonth > 0)
+ {
+ tmp.mMonth--;
+ tmp.mDay = tmp.mDay + getNbDayInMonth(tmp);
+ }
+ return (((tmp.mDay - date2.mDay) * 24 + tmp.mHour - date2.mHour) * 60 + tmp.mMinute - date2.mMinute) * 60 + tmp.mSecond - date2.mSecond;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/DescriptionObject.java b/src/main/java/org/cristalise/kernel/utils/DescriptionObject.java new file mode 100644 index 0000000..5ae0dce --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/DescriptionObject.java @@ -0,0 +1,31 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.kernel.utils;
+
+public interface DescriptionObject {
+
+ public String getName();
+ public int getVersion();
+
+ public void setName(String name);
+ public void setVersion(int version);
+
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/DescriptionObjectCache.java b/src/main/java/org/cristalise/kernel/utils/DescriptionObjectCache.java new file mode 100644 index 0000000..e5d0252 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/DescriptionObjectCache.java @@ -0,0 +1,105 @@ +/**
+ * 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.utils;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.entity.proxy.ItemProxy;
+import org.cristalise.kernel.entity.proxy.MemberSubscription;
+import org.cristalise.kernel.entity.proxy.ProxyObserver;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.persistency.outcome.Viewpoint;
+
+
+public abstract class DescriptionObjectCache<D extends DescriptionObject> {
+
+ SoftCache<String, CacheEntry<D>> cache = new SoftCache<String, CacheEntry<D>>();
+
+ public D get(String name, int version) throws ObjectNotFoundException, InvalidDataException {
+ D thisDef;
+ synchronized(cache) {
+ CacheEntry<D> thisDefEntry = cache.get(name+"_"+version);
+ if (thisDefEntry == null) {
+ Logger.msg(6, name+" v"+version+" not found in cache. Retrieving.");
+ ItemProxy defItem = LocalObjectLoader.loadLocalObjectDef(getDefRoot(), name);
+ thisDef = loadObject(name, version, defItem);
+ cache.put(name+"_"+version, new CacheEntry<D>(thisDef, defItem, this));
+ }
+ else {
+ Logger.msg(6, name+" v"+version+" found in cache.");
+ thisDef = thisDefEntry.def;
+ }
+ }
+ return thisDef;
+ }
+
+ public abstract String getDefRoot();
+
+ public abstract D loadObject(String name, int version, ItemProxy proxy) throws ObjectNotFoundException, InvalidDataException;
+
+ public void removeObject(String id) {
+ synchronized(cache) {
+ if (cache.keySet().contains(id)) {
+ Logger.msg(7, "ActDefCache: Removing activity def "+id+" from cache");
+ cache.remove(id);
+ }
+ }
+ }
+
+ public class CacheEntry<E extends DescriptionObject> implements ProxyObserver<Viewpoint> {
+ public String id;
+ public ItemProxy proxy;
+ public E def;
+ public DescriptionObjectCache<E> parent;
+ public CacheEntry(E def, ItemProxy proxy, DescriptionObjectCache<E> parent) {
+ this.id = def.getName()+"_"+def.getVersion();
+ this.def = def;
+ this.parent = parent;
+ this.proxy = proxy;
+ proxy.subscribe(new MemberSubscription<Viewpoint>(this, ClusterStorage.VIEWPOINT, false));
+ }
+ @Override
+ public void finalize() {
+ parent.removeObject(id);
+ proxy.unsubscribe(this);
+ }
+ @Override
+ public void add(Viewpoint contents) {
+ parent.removeObject(id);
+ }
+
+ @Override
+ public void remove(String oldId) {
+ parent.removeObject(oldId);
+ }
+
+ @Override
+ public String toString() {
+ return "Cache entry: "+id;
+ }
+ @Override
+ public void control(String control, String msg) {
+ }
+ }
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/utils/FileStringUtility.java b/src/main/java/org/cristalise/kernel/utils/FileStringUtility.java new file mode 100644 index 0000000..3a87e74 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/FileStringUtility.java @@ -0,0 +1,450 @@ +/**
+ * 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.utils;
+
+//Java
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.Array;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+/**************************************************************************
+ *
+ * @author $Author: abranson $ $Date: 2004/10/20 14:10:21 $
+ * @version $Revision: 1.31 $
+ **************************************************************************/
+public class FileStringUtility
+{
+ /**************************************************************************
+ * Reads a file and converts it to String
+ **************************************************************************/
+ static public String file2String(File file) throws FileNotFoundException, IOException
+ {
+ FileInputStream fis = new FileInputStream(file);
+ byte[] bArray = (byte[]) Array.newInstance(byte.class, (int) file.length());
+ Logger.msg(8, "FileStringUtility.file2String() - Reading file '" + file.getAbsolutePath()+"'");
+
+ fis.read(bArray, 0, (int) file.length());
+ fis.close();
+
+ Logger.msg(9, "FileStringUtility.file2String() - file '" + file.getAbsolutePath() + "' read.");
+
+ return new String(bArray);
+ }
+
+ /**************************************************************************
+ * Reads a file and converts it to String
+ **************************************************************************/
+ static public String file2String(String fileName) throws FileNotFoundException, IOException
+ {
+ return file2String(new File(fileName));
+ }
+
+ /**************************************************************************
+ * Reads a file and converts it to String
+ **************************************************************************/
+ static public String url2String(java.net.URL location) throws IOException
+ {
+ BufferedReader in = new BufferedReader(new InputStreamReader(location.openStream(), "UTF-8"));
+ StringBuffer strbuf = new StringBuffer();
+ String line = in.readLine();
+ while (line != null) {
+ strbuf.append(line).append('\n');
+ line = in.readLine();
+ }
+ return strbuf.toString();
+ }
+
+ /**************************************************************************
+ * Reads a file and converts each line to String[]
+ **************************************************************************/
+ static public String[] file2StringArray(File file) throws FileNotFoundException, IOException
+ {
+ FileReader fr = new FileReader(file);
+ BufferedReader buf = new BufferedReader(fr);
+ Vector<String> lines = new Vector<String>();
+ String thisLine = null;
+ while ((thisLine = buf.readLine()) != null)
+ lines.addElement(thisLine);
+ buf.close();
+ String[] lineArray = new String[lines.size()];
+ for (int i = 0; i < lines.size(); i++)
+ lineArray[i] = lines.get(i);
+ return lineArray;
+ }
+
+ /**************************************************************************
+ * Reads a file and converts it to String[]
+ **************************************************************************/
+ static public String[] file2StringArray(String fileName) throws FileNotFoundException, IOException
+ {
+ return file2StringArray(new File(fileName));
+ }
+
+ /**************************************************************************
+ * Saves a string to a text file
+ **************************************************************************/
+ static public void string2File(File file, String data) throws FileNotFoundException, IOException
+ {
+ FileWriter thisFile = new FileWriter(file);
+ BufferedWriter thisFileBuffer = new BufferedWriter(thisFile);
+
+ Logger.msg(9, "FileStringUtility.string2File() - writing file '" + file.getAbsolutePath()+"'");
+
+ thisFileBuffer.write(data);
+ thisFileBuffer.close();
+
+ Logger.msg(9, "FileStringUtility.string2File() - file '" + file.getAbsolutePath() + "' complete.");
+ }
+
+ /**************************************************************************
+ * Saves a string to a text file
+ **************************************************************************/
+ static public void string2File(String fileName, String data) throws FileNotFoundException, IOException
+ {
+ string2File(new File(fileName), data);
+ }
+
+ /**************************************************************************
+ * checks for existing directory
+ **************************************************************************/
+ static public boolean checkDir(String dirPath)
+ {
+ File dir = new File(dirPath);
+
+ if (dir.isFile())
+ {
+ Logger.error("FileStringUtility.checkDir() - '" + dir.getAbsolutePath() + "' is a file.");
+ return false;
+ }
+ else if (!dir.exists())
+ {
+ Logger.msg(9, "FileStringUtility.checkDir() - directory '" + dir.getAbsolutePath() + "' does not exist.");
+ return false;
+ }
+
+ return true;
+ }
+
+ /**************************************************************************
+ * creating a new directory
+ **************************************************************************/
+ static public boolean createNewDir(String dirPath)
+ {
+ File dir = new File(dirPath);
+
+ if (dir.isFile())
+ {
+ Logger.error("FileStringUtility.createNewDir() - '" + dir.getAbsolutePath() + "' is a file.");
+ return false;
+ }
+ else if (dir.exists())
+ {
+ Logger.msg(8, "FileStringUtility.createNewDir() - '" + dir.getAbsolutePath() + "' already exists.");
+ return false;
+ }
+ else
+ {
+ if (!dir.mkdirs())
+ {
+ Logger.error("FileStringUtility - Could not create new directory '" + dir.getAbsolutePath() + "'");
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**************************************************************************
+ * deleting a existing directory
+ **************************************************************************/
+ static public boolean deleteDir(String dirPath)
+ {
+ File dir = new File(dirPath);
+
+ if (!checkDir(dirPath))
+ {
+ Logger.msg(8, "FileStringUtility.deleteDir() - directory '" + dir.getAbsolutePath() + "' does not exist.");
+ return false;
+ }
+
+ if (!dir.delete())
+ {
+ //prints the possible reason
+ if (dir.list().length != 0)
+ {
+ Logger.error("FileStringUtility.deleteDir() - cannot delete non-empty directory '" + dir.getAbsolutePath() + "'");
+ }
+ else
+ {
+ Logger.error("FileStringUtility.deleteDir() - directory '" + dir.getAbsolutePath() + "' could not be deleted.");
+ }
+ return false;
+ }
+
+ return true;
+ }
+
+ /**************************************************************************
+ * deleting a existing directory with its structure
+ *
+ * @param dirPath the directory which should be deleted
+ * @param force if true forces to delete the entry (ie. the dirPath) even if
+ * it is a file
+ * @param recursive if true deletes the complete directory structure
+ **************************************************************************/
+ static public boolean deleteDir(String dirPath, boolean force, boolean recursive)
+ {
+ File dir = new File(dirPath);
+ File files[];
+
+ if (!dir.exists())
+ {
+ Logger.error("FileStringUtility.deleteDir() - directory '" + dir.getAbsolutePath() + "' does not exist.");
+ return false;
+ }
+
+ if (dir.isFile())
+ {
+
+ if (force)
+ { //delete the entry even if it is a file
+ dir.delete();
+ return true;
+ }
+ else
+ {
+ Logger.error("FileStringUtility.deleteDir() - '" + dir.getAbsolutePath() + "' was a file.");
+ return false;
+ }
+ }
+
+ if (recursive)
+ {
+ files = dir.listFiles();
+
+ for (File file : files)
+ deleteDir(file.getAbsolutePath(), true, true);
+ }
+
+ return deleteDir(dirPath);
+ }
+
+ /**************************************************************************
+ * List all file names in the directory recursively, relative to the
+ * starting directory.
+ *
+ * @param dirPath starting directory
+ * @param recursive goes into the subdirectories
+ **************************************************************************/
+ static public ArrayList<String> listDir(String dirPath, boolean withDirs, boolean recursive)
+ {
+ ArrayList<String> fileNames = new ArrayList<String>();
+ File dir = new File(dirPath);
+ File files[];
+ String fileName;
+
+ if (!checkDir(dirPath))
+ {
+ Logger.msg(8, "FileStringUtility.listDir() - directory '" + dir.getAbsolutePath() + "' does not exist.");
+ return null;
+ }
+
+ files = dir.listFiles();
+
+ for (File file : files) {
+ fileName = file.getName();
+
+ if (file.isFile())
+ {
+ fileNames.add(dirPath + "/" + fileName);
+ }
+ else
+ {
+ if (recursive)
+ fileNames.addAll(listDir(dirPath + "/" + fileName, withDirs, recursive));
+
+ if (withDirs)
+ fileNames.add(dirPath + "/" + fileName);
+ }
+ }
+
+ return fileNames;
+ }
+
+ /**************************************************************************
+ * Open a URL or File as an InputStream
+ **************************************************************************/
+ static public InputStream openTextStream(String source)
+ {
+ java.io.InputStream in = null;
+ java.net.URL url = null;
+
+ // Try to open URL connection first
+ try
+ {
+ try
+ {
+ url = new URL(source);
+ in = url.openStream();
+ }
+ catch (MalformedURLException e)
+ {
+ // Try to open plain file, if `configFile' is not a
+ // URL specification
+ in = new FileInputStream(source);
+ }
+ }
+ catch (java.io.IOException ex)
+ {
+ Logger.error("FileStringUtility.openTextStream() - could not load text stream:" + source);
+ }
+ return in;
+ }
+
+ /**************************************************************************
+ * Load the contents of the configuration file
+ **************************************************************************/
+ static public java.util.Properties loadConfigFile(String configFile)
+ {
+ java.io.BufferedInputStream bin = null;
+ java.io.InputStream in = openTextStream(configFile);
+ java.util.Properties props = new java.util.Properties();
+
+ if (in != null)
+ {
+ try
+ {
+ bin = new java.io.BufferedInputStream(in);
+ props.load(bin);
+ in.close();
+ }
+ catch (IOException ex)
+ {
+ Logger.error("FileStringUtility.loadConfigFile() - could not load configuration file '" + configFile+"'");
+ }
+ }
+ return props;
+ }
+
+ /**************************************************************************
+ * Load the contents of the language file
+ * *************************************************************************/
+ static public Hashtable<String, String> loadLanguageFile(String configFile)
+ {
+ try
+ {
+ String language = FileStringUtility.file2String(configFile);
+ Hashtable<String, String> props = new Hashtable<String, String>();
+ StringTokenizer tok = new StringTokenizer(language, "\n");
+ while (tok.hasMoreTokens())
+ {
+ String t = tok.nextToken();
+ int sep = t.indexOf("=");
+ if (sep >0)props.put(t.substring(0,sep),t.substring(sep+1));
+ }
+ return props;
+ }
+ catch (Exception e)
+ {
+ Logger.error("FileStringUtility.loadLanguageFile() - could not load language file '" + configFile+"'");
+ Logger.error(e);
+ return new Hashtable<String, String>();
+ }
+
+ }
+
+ /**************************************************************************
+ * Load the contents of the configuration file
+ **************************************************************************/
+ static public void appendConfigFile(java.util.Properties props, String configFile)
+ {
+ java.io.BufferedInputStream bin = null;
+ java.io.InputStream in = openTextStream(configFile);
+
+ if (in != null)
+ {
+ try
+ {
+ bin = new java.io.BufferedInputStream(in);
+ props.load(bin);
+ in.close();
+ }
+ catch (java.io.IOException ex)
+ {
+ Logger.error("FileStringUtility.appendConfigFile() - could not append configuration file '" + configFile+"'");
+ }
+ }
+ }
+ public static String convert(String init)
+ {
+ if (init==null) return null;
+ return init
+ .replace('\'', '_')
+ .replace('\\', '_')
+ .replace('/', '_')
+ .replace('\"', '_')
+ .replace(':', '_')
+ .replace('*', '_')
+ .replace('?', '_')
+ .replace('<', '_')
+ .replace('>', '_')
+ .replace('|', '_')
+ .replace('(', '[')
+ .replace(')', ']')
+ .replace(',','_'); }
+ public static String replaceall(String src,String from,String to)
+ {
+ StringBuffer tmp=new StringBuffer(src);
+ int length = from.length();
+ int index = tmp.toString().indexOf(from);
+ while (index>0)
+ {
+ tmp.replace(index,index+length,to);
+ index = tmp.toString().indexOf(from);
+ }
+ return tmp.toString();
+ }
+ public static String toAlphaNum(String source)
+ {
+ byte[] sourceb = source.getBytes();
+ for (int i=0;i<sourceb.length;i++)
+ {
+ if (sourceb[i]<'0'||(sourceb[i]>'9'&&sourceb[i]<'A')||(sourceb[i]>'Z'&&sourceb[i]<'_')||sourceb[i]>'z')
+ sourceb[i]='_';
+ }
+ return new String(sourceb);
+
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/GTimeStampComparator.java b/src/main/java/org/cristalise/kernel/utils/GTimeStampComparator.java new file mode 100644 index 0000000..4a8dd04 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/GTimeStampComparator.java @@ -0,0 +1,46 @@ +/**
+ * 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.utils;
+
+import java.util.Comparator;
+
+import org.cristalise.kernel.common.GTimeStamp;
+
+
+public class GTimeStampComparator implements Comparator<GTimeStamp> {
+
+ @Override
+ public int compare(GTimeStamp t0, GTimeStamp t1) {
+
+ int retVal = compareInt(t0.mYear, t1.mYear);
+ if (retVal == 0) retVal = compareInt(t0.mMonth, t1.mMonth);
+ if (retVal == 0) retVal = compareInt(t0.mDay, t1.mDay);
+ if (retVal == 0) retVal = compareInt(t0.mHour-(t0.mTimeOffset/3600), t1.mHour-(t1.mTimeOffset/3600));
+ if (retVal == 0) retVal = compareInt(t0.mMinute, t1.mMinute);
+ if (retVal == 0) retVal = compareInt(t0.mSecond, t1.mSecond);
+
+ return retVal;
+ }
+
+ private static int compareInt(int i, int j) {
+ return i-j;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/KeyValuePair.java b/src/main/java/org/cristalise/kernel/utils/KeyValuePair.java new file mode 100644 index 0000000..67c5fad --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/KeyValuePair.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.utils;
+
+
+public class KeyValuePair
+{
+ private String mKey = null;
+ private Object mValue = null;
+ private boolean mAbstract = false;
+
+ public KeyValuePair() {}
+
+ public KeyValuePair(String key, Object value, boolean isAbstract)
+ {
+ mKey = key;
+ mValue = value;
+ mAbstract = isAbstract;
+ }
+
+ public String getKey() {
+ return mKey;
+ }
+
+ public void setKey(String key) {
+ mKey = key;
+ }
+
+ public Object getValue() {
+ return mValue;
+ }
+
+ public void setValue(Object value) {
+ mValue = value;
+ }
+
+ public void setAbstract(boolean isAbstract) {
+ mAbstract = isAbstract;
+ }
+
+ public boolean isAbstract() {
+ return mAbstract;
+ }
+
+ public String getStringValue() {
+ if (mValue instanceof String)
+ return (String)mValue;
+ else
+ return null;
+ }
+
+ public void setStringValue(String value) {
+ mValue = value;
+ }
+
+ public Integer getIntegerValue() {
+ if (mValue instanceof Integer)
+ return (Integer)mValue;
+ else
+ return null;
+ }
+
+ public void setIntegerValue(Integer value) {
+ mValue = value;
+ }
+
+ public Boolean getBooleanValue() {
+ if (mValue instanceof Boolean)
+ return (Boolean)mValue;
+ else
+ return null;
+ }
+
+ public void setBooleanValue(Boolean value) {
+ mValue = value;
+ }
+
+ public Double getFloatValue() {
+ if (mValue instanceof Double)
+ return (Double)mValue;
+ else
+ return null;
+ }
+
+ public void setFloatValue(Double value) {
+ mValue = value;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/Language.java b/src/main/java/org/cristalise/kernel/utils/Language.java new file mode 100644 index 0000000..9f039e8 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/Language.java @@ -0,0 +1,86 @@ +/**
+ * 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.utils;
+
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**************************************************************************
+ *
+ * @author $Author: sgaspard $ $Date: 2004/09/21 13:17:40 $
+ * @version $Revision: 1.9 $
+ **************************************************************************/
+
+public class Language
+{
+ public static Hashtable<?, ?> mTableOfTranslation = new Hashtable<Object, Object>();
+ public static Hashtable<String, String> mTableOfUntranslated = new Hashtable<String, String>();
+ public static boolean isTranlated=false;
+ private Hashtable<?, ?> tableOfTranslation = new Hashtable<Object, Object>();
+
+ public static String translate(String english)
+ {
+ if (!isTranlated) return english;
+ String rep = english;
+ if (rep != null && !rep.equals("")) {
+ String translated = (String) mTableOfTranslation.get(english);
+ if (translated != null) return translated;
+ else
+ {
+ mTableOfUntranslated.put(english,"");
+ try
+ {
+ String s = "";
+ Enumeration<String> e = mTableOfUntranslated.keys();
+ while (e.hasMoreElements()) s =s+"\n"+e.nextElement();
+ FileStringUtility.string2File("untranslated.txt",s);
+ }
+ catch (Exception ex)
+ {
+ Logger.warning("Could not write to preferences file. Preferences have not been updated.");
+ }
+ }
+
+ }
+ return rep;
+ }
+
+ public Language(String filePath)
+ {
+ String languageFile = filePath;
+ if (languageFile == null || languageFile.length() == 0)
+ // no language file defined for this process
+ return;
+ tableOfTranslation = FileStringUtility.loadLanguageFile(languageFile);
+ }
+ public String insTranslate(String english)
+ {
+ String rep = english;
+ if (rep != null && !rep.equals("")) {
+ String translated = (String) tableOfTranslation.get(english);
+ if (translated != null)
+ rep = translated;
+ }
+ return rep;
+ }
+
+
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/LocalObjectLoader.java b/src/main/java/org/cristalise/kernel/utils/LocalObjectLoader.java new file mode 100644 index 0000000..416d0a5 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/LocalObjectLoader.java @@ -0,0 +1,111 @@ +/**
+ * 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.utils;
+ +import java.util.Iterator;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.proxy.ItemProxy;
+import org.cristalise.kernel.lifecycle.ActivityDef;
+import org.cristalise.kernel.lifecycle.instance.stateMachine.StateMachine;
+import org.cristalise.kernel.lookup.DomainPath;
+import org.cristalise.kernel.lookup.Path;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.persistency.outcome.Schema;
+import org.cristalise.kernel.persistency.outcome.Viewpoint;
+import org.cristalise.kernel.process.Gateway;
+
+
+public class LocalObjectLoader {
+ private static ActDefCache actCache = new ActDefCache();
+ private static StateMachineCache smCache = new StateMachineCache();
+
+ static public ItemProxy loadLocalObjectDef(String root, String name)
+ throws ObjectNotFoundException
+ {
+ DomainPath defRoot = new DomainPath(root);
+ Iterator<Path> e = Gateway.getLookup().search(defRoot, name);
+ if (e.hasNext()) {
+ DomainPath defPath = (DomainPath)e.next();
+ if (e.hasNext()) throw new ObjectNotFoundException("Too many matches for "+name+" in "+root);
+ return Gateway.getProxyManager().getProxy(defPath);
+ }
+ else {
+ throw new ObjectNotFoundException("No match for "+name+" in "+root);
+ }
+ + }
+
+ static public String getScript(String scriptName, int scriptVersion) throws ObjectNotFoundException {
+ Logger.msg(5, "Loading script "+scriptName+" v"+scriptVersion);
+ try {
+ ItemProxy script = loadLocalObjectDef("/desc/Script/", scriptName);
+ Viewpoint scriptView = (Viewpoint)script.getObject(ClusterStorage.VIEWPOINT + "/Script/" + scriptVersion);
+ return scriptView.getOutcome().getData();
+ } catch (PersistencyException ex) {
+ Logger.error(ex);
+ throw new ObjectNotFoundException("Error loading script " + scriptName + " version " + scriptVersion);
+ }
+
+ }
+
+ static public Schema getSchema(String schemaName, int schemaVersion) throws ObjectNotFoundException {
+ Logger.msg(5, "Loading schema "+schemaName+" v"+schemaVersion);
+
+ String docType = schemaName;
+ int docVersion = schemaVersion;
+ String schemaData;
+
+ // don't bother if this is the Schema schema - for bootstrap esp.
+ if (schemaName.equals("Schema") && schemaVersion == 0)
+ return new Schema(docType, docVersion, "");
+
+ ItemProxy schema = loadLocalObjectDef("/desc/OutcomeDesc/", schemaName);
+ Viewpoint schemaView = (Viewpoint)schema.getObject(ClusterStorage.VIEWPOINT + "/Schema/" + schemaVersion);
+ try {
+ schemaData = schemaView.getOutcome().getData();
+ } catch (PersistencyException ex) {
+ Logger.error(ex);
+ throw new ObjectNotFoundException("Problem loading schema "+schemaName+" v"+schemaVersion+": "+ex.getMessage());
+ }
+ return new Schema(docType, docVersion, schemaData);
+ }
+
+ /**
+ * Retrieves a named version of activity def from the database
+ *
+ * @param actName - activity name
+ * @param version - named version (String)
+ * @return ActivityDef
+ * @throws ObjectNotFoundException - When activity or version does not exist
+ */
+ static public ActivityDef getActDef(String actName, int actVersion) throws ObjectNotFoundException, InvalidDataException {
+ Logger.msg(5, "Loading activity def "+actName+" v"+actVersion);
+ return actCache.get(actName, actVersion);
+ }
+
+ static public StateMachine getStateMachine(String smName, int smVersion) throws ObjectNotFoundException, InvalidDataException {
+ Logger.msg(5, "Loading activity def "+smName+" v"+smVersion);
+ return smCache.get(smName, smVersion);
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/Logger.java b/src/main/java/org/cristalise/kernel/utils/Logger.java new file mode 100644 index 0000000..244cf4c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/Logger.java @@ -0,0 +1,207 @@ +/**
+ * 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.utils;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.sql.Timestamp;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.cristalise.kernel.process.AbstractMain;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.scripting.ScriptConsole;
+import org.cristalise.kernel.utils.server.SimpleTCPIPServer;
+
+/**
+ * <pre>- message string should always contain the class name and the method name: Logger.msg(1,"ItemFact::createDir() - LifeCycle DB created"); - use meaningfull abbreviation and also use the dash to separate the 'header' from the message! - each method should start with this 'method signature' debug: Logger.msg(1,"ItemFact::createDir() - path:" + path);
+*</pre>
+ */
+public class Logger
+{
+ /**
+ * logging level 0 (only error & warning) => no logging ; 9 => maximum logging
+ * add ten to output time before each message
+ */
+ private static int mHighestLogLevel = 0;
+ private static long startTime = System.currentTimeMillis();
+ private static HashMap<PrintStream, Integer> logStreams = new HashMap<PrintStream, Integer>();
+ static protected SimpleTCPIPServer mConsole = null;
+
+ static private void printMessage(String message, int msgLogLevel)
+ {
+ synchronized(logStreams) {
+ for (Iterator<PrintStream> iter = logStreams.keySet().iterator(); iter.hasNext();) {
+ PrintStream element = iter.next();
+ int logLevel = logStreams.get(element);
+
+ if ( (logLevel > 9 && logLevel - 10 < msgLogLevel) ||
+ (msgLogLevel > 9 && logLevel < msgLogLevel - 10) ||
+ (logLevel < 10 && msgLogLevel < 10 && logLevel < msgLogLevel) )
+ continue;
+
+ if (logLevel > 9 || msgLogLevel > 9) {
+ message = reportTime() + " - " + message;
+ }
+
+ try {
+ element.println(message);
+ } catch (Exception ex) {
+ iter.remove();
+ }
+ }
+ }
+ }
+
+ static private String reportTime() {
+ long now = System.currentTimeMillis();
+ Timestamp ts = new Timestamp(now);
+ double since = (now - startTime) / 1000.0;
+ return ts.toString() + " ("+since+"s)";
+ }
+
+ static private void printMessage(Throwable ex) {
+ StringWriter msgString = new StringWriter();
+ PrintWriter msg = new PrintWriter(msgString);
+ msg.print(ex instanceof Exception ? "EXCEPTION:" : "JVM ERROR:");
+ ex.printStackTrace(msg);
+ printMessage(msgString.toString(), 0);
+ }
+
+ static public boolean doLog(int logLevel)
+ {
+ if (logLevel > 9) logLevel -= 10;
+ return mHighestLogLevel >= logLevel;
+ }
+ /**
+ * Use this only for temporary messages while developing/debugging. When the code is stable, change calls to debug to
+ * message/warning/error with an appropriate log level. Is is marked deprecated to highlight stray calls. This makes
+ * it easier to manage debug calls in the source.
+ *
+ * @param msg -
+ * the string to write to the console, or log file if specified in cmd line
+ * @deprecated
+ */
+ @Deprecated
+ static public void debug(String msg)
+ {
+ msg("DEBUG : " + msg);
+ }
+ static public void debug(int logLevel, String msg)
+ {
+ msg(logLevel, "DEBUG : " + msg);
+ }
+ /**
+ * Use Logger.message to report information that will be useful for debugging a release
+ *
+ * @param level -
+ * log level of this message. If the current log level has been on the cmd line to be less that this number, the log message
+ * will not be displayed
+ * @param msg -
+ * the string to write to the console, or log file if specified in cmd line
+ */
+ static public void msg(int level, String msg)
+ {
+ printMessage(msg, level);
+ }
+ static public void msg(String msg)
+ {
+ printMessage(msg, 0);
+ }
+ static public void error(String msg)
+ {
+ printMessage("ERROR : " + msg, 0);
+ }
+ static public void error(Throwable ex)
+ {
+ printMessage(ex);
+ }
+ static public void warning(String msg)
+ {
+ printMessage("WARNING: " + msg, 0);
+ }
+ static public void die(String msg)
+ {
+ printMessage("FATAL : " + msg, 0);
+ AbstractMain.shutdown(1);
+ }
+ /**
+ * @param console
+ */
+ public static void addLogStream(PrintStream console, int logLevel) {
+ try {
+ console.println("***********************************************************");
+ console.println(" CRISTAL log started at level "+logLevel+" @"+new Timestamp(System.currentTimeMillis()).toString());
+ console.println("***********************************************************");
+ } catch (Exception ex) {
+ System.out.println("Exception accessing log stream");
+ ex.printStackTrace();
+ }
+
+ synchronized(logStreams) {
+ logStreams.put(console, logLevel);
+ if ((logLevel>10?logLevel-10:logLevel) > mHighestLogLevel) mHighestLogLevel = logLevel;
+ }
+
+ }
+ /**
+ * @param console
+ */
+ public static void removeLogStream(PrintStream console) {
+ synchronized(logStreams) {
+ Integer logIntObj = logStreams.get(console);
+ if (logIntObj == null) return; // not registered
+ int logLevel = (logIntObj).intValue();
+ logStreams.remove(console);
+
+ // recalculate lowest log level
+ if (logLevel == mHighestLogLevel || (logLevel > 9 && logLevel-10 == mHighestLogLevel)) {
+ mHighestLogLevel = 0;
+ for (Integer element : logStreams.values()) {
+ int thisLogLevel = element>9?element-10:element;
+ if (thisLogLevel > mHighestLogLevel)
+ mHighestLogLevel = thisLogLevel;
+ }
+ }
+ }
+ }
+
+ static public void initConsole(String id)
+ {
+ int port = Gateway.getProperties().getInt(id+".Console.port", 0);
+ if (port == 0)
+ Logger.msg("No port defined for "+id+" console. Using any port.");
+
+ mConsole = new SimpleTCPIPServer(port, ScriptConsole.class, 5);
+ mConsole.startListening();
+ Gateway.getProperties().setProperty(id+".Console.port", String.valueOf(mConsole.getPort()));
+ }
+
+ static public int getConsolePort() {
+ return mConsole.getPort();
+ }
+
+ static public void closeConsole()
+ {
+ if (mConsole != null)
+ mConsole.stopListening();
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/ObjectProperties.java b/src/main/java/org/cristalise/kernel/utils/ObjectProperties.java new file mode 100644 index 0000000..31ff57c --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/ObjectProperties.java @@ -0,0 +1,215 @@ +/**
+ * 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.utils;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+public class ObjectProperties extends Properties {
+
+ public ObjectProperties() {
+ }
+
+ public ObjectProperties(Properties defaults) {
+ super(defaults);
+ }
+
+ public String getString(String propName) {
+ return getString(propName, null);
+ }
+
+ public String getString(String propName, String defaultValue) {
+ String value = super.getProperty(propName, defaultValue);
+ if (value!=null) value = value.trim();
+ return value;
+ }
+
+ /**
+ * ogattaz proposal
+ *
+ * @param propName
+ * the name of the property
+ * @return the object value of the property. Returns null if the property
+ * doesn't exist or if the properties of the gateway is null
+ */
+ public Object getObject(String propName) {
+ return getObject(propName, null);
+ }
+
+ /**
+ * ogattaz proposal
+ *
+ * @param aPropertyName
+ * the name of the property
+ * @param defaultValue
+ * the default value.
+ * @return the object value of the property. Returns the default value if the property
+ * doesn't exist or if the properties of the gateway is null.
+ * @return
+ */
+ public Object getObject(String propName,
+ Object defaultValue) {
+
+ Object wValue = get(propName);
+ if (wValue == null) {
+ return defaultValue;
+ }
+ return wValue;
+ }
+
+ /**
+ * ogattaz proposal
+ *
+ * @param propName
+ * the name of the paroperty
+ * @return the boolean value of the property. Returns false if the property
+ * doesn't exist or if the value is not a String or a Boolean
+ * instance
+ */
+ public boolean getBoolean(String aPropertyName) {
+ return getBoolean(aPropertyName, Boolean.FALSE);
+ }
+
+ /**
+ * ogattaz proposal
+ *
+ * @param propName
+ * the name of the parameter stored in the clc file
+ * @param defaultValue
+ * the default value
+ * @return the boolean value of the property. Returns the default value if
+ * the property doesn't exist or if the value is not a String or a
+ * Boolean instance
+ */
+ public boolean getBoolean(String aPropertyName,
+ boolean defaultValue) {
+
+ Object wValue = getObject(aPropertyName, Boolean.valueOf(defaultValue));
+ if (wValue instanceof Boolean) {
+ return ((Boolean) wValue).booleanValue();
+ }
+ if (wValue instanceof String) {
+ return Boolean.parseBoolean((String) wValue);
+ }
+ Logger.error("getBoolean(): unable to retrieve a int value for ["+aPropertyName+"]. Returning default value ["+defaultValue+"]. object found="+wValue);
+
+ return defaultValue;
+ }
+
+ /**
+ * ogattaz proposal
+ *
+ * @param propName
+ * the name of the property
+ * @return the int value of the property. Returns -1 if the property doesn't
+ * exist or if the value is not a String or an Integer instance
+ */
+ public int getInt(String aPropertyName) {
+ return getInt(aPropertyName, -1);
+ }
+
+ /**
+ * ogattaz proposal
+ *
+ * @param propName
+ * the name of the property
+ * @param defaultValue
+ * the default value
+ * @return the int value of the property. Returns the default vakue if the
+ * property doesn't exist or if the value is not a String or an
+ * Integer instance
+ */
+ public int getInt(String aPropertyName, int defaultValue) {
+
+ Object wValue = getObject(aPropertyName, Integer.valueOf(defaultValue));
+ if (wValue instanceof Integer) {
+ return ((Integer) wValue).intValue();
+ }
+ if (wValue instanceof String) {
+ try {
+ return Integer.parseInt((String) wValue);
+ } catch (NumberFormatException ex) { }
+ }
+ Logger.error("getInt(): unable to retrieve a int value for ["+aPropertyName+"]. Returning default value ["+defaultValue+"]. object found="+wValue);
+ return defaultValue;
+ }
+
+ /**
+ * Allow setting of properties as Objects
+ *
+ * @param aPropertyName
+ * the name of the property
+ * @param aPropertyValue
+ */
+ public void setProperty(String aPropertyName, Object aPropertyValue) {
+ put(aPropertyName, aPropertyValue);
+ }
+
+ public void dumpProps(int logLevel) {
+ Logger.msg(logLevel, "Properties:");
+ for (Enumeration<?> e = propertyNames(); e.hasMoreElements();) {
+ String name = (String) e.nextElement();
+ Object value = getObject(name);
+ if (value == null)
+ Logger.msg(" "+name+": null");
+ else
+ Logger.msg(" "+name+" ("+getObject(name).getClass().getSimpleName()+"): '"+getObject(name).toString()+"'");
+ }
+ }
+
+ public Object getInstance(String propName, Object defaultVal) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+ Object prop = getObject(propName, defaultVal);
+ if (prop == null || prop.equals(""))
+ throw new InstantiationException("Property '"+propName+"' was not defined. Cannot instantiate.");
+ if (prop instanceof String)
+ return Class.forName(((String)prop).trim()).newInstance();
+ return prop;
+ }
+
+ public Object getInstance(String propName) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+ return getInstance(propName, null);
+ }
+
+ public ArrayList<?> getInstances(String propName, Object defaultVal) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+ Object val = getObject(propName, defaultVal);
+ if (val == null) return null;
+ if (val instanceof ArrayList)
+ return (ArrayList<?>)val;
+ else if (val instanceof String) {
+ ArrayList<Object> retArr = new ArrayList<Object>();
+ StringTokenizer tok = new StringTokenizer((String)val, ",");
+ while (tok.hasMoreTokens())
+ retArr.add(getInstance(tok.nextToken()));
+ return retArr;
+ }
+ else {
+ ArrayList<Object> retArr = new ArrayList<Object>();
+ retArr.add(val);
+ return retArr;
+ }
+ }
+
+ public ArrayList<?> getInstances(String propName) throws InstantiationException, IllegalAccessException, ClassNotFoundException {
+ return getInstances(propName, null);
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/SoftCache.java b/src/main/java/org/cristalise/kernel/utils/SoftCache.java new file mode 100644 index 0000000..7444dcf --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/SoftCache.java @@ -0,0 +1,139 @@ +/**
+ * 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.utils;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+import java.util.AbstractMap;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+
+/*******************************************************************************
+ * SoftReferences are reaped if no strong references are left and the vm is
+ * running out of memory. Most caches in the kernel use this.
+ *
+ * $Revision: 1.5 $ $Date: 2004/10/29 13:29:09 $
+ ******************************************************************************/
+public class SoftCache<K, V> extends AbstractMap<K, V> {
+
+ private final Map<K, SoftValue<V>> hash = new HashMap<K, SoftValue<V>>();
+ private final int minSize;
+ private final LinkedList<V> hardCache = new LinkedList<V>();
+ private final ReferenceQueue<V> queue = new ReferenceQueue<V>();
+
+ public SoftCache() {
+ this(0);
+ }
+
+ public SoftCache(int minSize) {
+ this.minSize = minSize;
+ }
+
+ @Override
+ public V get(Object key) {
+ V result = null;
+ SoftValue<V> soft_ref = hash.get(key);
+ if (soft_ref != null) {
+ result = soft_ref.get();
+ if (result == null)
+ hash.remove(key);
+ else
+ if (minSize > 0) { // add to hard cache so it's not reaped for a while
+ synchronized(hardCache) {
+ hardCache.addFirst(result);
+ if (hardCache.size() > minSize) // trim last one off
+ hardCache.removeLast();
+ }
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public V put(K key, V value) {
+ processQueue();
+ if (minSize > 0) {
+ synchronized(hardCache) {
+ hardCache.addFirst(value);
+ if (hardCache.size() > minSize)
+ hardCache.removeLast();
+ }
+ }
+ hash.put(key, new SoftValue<V>(key, value, queue));
+ return value;
+ }
+
+ @Override
+ public V remove(Object key) {
+ processQueue();
+ if (hash.containsKey(key)) return hash.remove(key).get();
+ return null;
+ }
+
+ @Override
+ public void clear() {
+ synchronized(hardCache) {
+ hardCache.clear();
+ }
+ while(queue.poll()!=null);
+ hash.clear();
+ }
+
+ @Override
+ public int size() {
+ processQueue();
+ return hash.size();
+ }
+
+ @Override
+ public Set<K> keySet() {
+ processQueue();
+ return hash.keySet();
+ }
+
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
+ // Would have to create another Map to do this - too expensive
+ // Throwing runtime expensive is dangerous, but better than nulls
+ throw new UnsupportedOperationException();
+ }
+
+ private static class SoftValue<V> extends SoftReference<V> {
+ private final Object key;
+ private SoftValue(Object key, V value, ReferenceQueue<V> q) {
+ super(value, q);
+ this.key = key;
+ }
+ }
+
+ /**
+ * Look for values that have been reaped, and remove their keys from the cache
+ */
+ private void processQueue() {
+ SoftValue<V> sv;
+ while ((sv = (SoftValue<V>) queue.poll()) != null) {
+ hash.remove(sv.key);
+ }
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/StateMachineCache.java b/src/main/java/org/cristalise/kernel/utils/StateMachineCache.java new file mode 100644 index 0000000..5aa87b9 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/StateMachineCache.java @@ -0,0 +1,67 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+/**
+ *
+ */
+package org.cristalise.kernel.utils;
+
+import org.cristalise.kernel.common.InvalidDataException;
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.proxy.ItemProxy;
+import org.cristalise.kernel.lifecycle.instance.stateMachine.StateMachine;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.persistency.outcome.Viewpoint;
+import org.cristalise.kernel.process.Gateway;
+
+
+public class StateMachineCache extends DescriptionObjectCache<StateMachine> {
+
+
+ @Override
+ public String getDefRoot() {
+ return "/desc/StateMachine";
+ }
+
+ @Override
+ public StateMachine loadObject(String name, int version, ItemProxy proxy) throws ObjectNotFoundException, InvalidDataException {
+ StateMachine thisStateMachine;
+ Viewpoint smView = (Viewpoint)proxy.getObject(ClusterStorage.VIEWPOINT + "/StateMachine/" + version);
+ String marshalledSM;
+ try {
+ marshalledSM = smView.getOutcome().getData();
+ } catch (PersistencyException ex) {
+ Logger.error(ex);
+ throw new ObjectNotFoundException("Problem loading State Machine "+name+" v"+version+": "+ex.getMessage());
+ }
+ try {
+ thisStateMachine = (StateMachine)Gateway.getMarshaller().unmarshall(marshalledSM);
+ thisStateMachine.validate();
+ } catch (Exception ex) {
+ Logger.error(ex);
+ throw new InvalidDataException("Could not unmarshall State Machine '"+name+"' v"+version+": "+ex.getMessage());
+ }
+ thisStateMachine.setName(name);
+ thisStateMachine.setVersion(version);
+ return thisStateMachine;
+ }
+
+}
\ No newline at end of file diff --git a/src/main/java/org/cristalise/kernel/utils/TransientCache.java b/src/main/java/org/cristalise/kernel/utils/TransientCache.java new file mode 100644 index 0000000..4b13e0e --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/TransientCache.java @@ -0,0 +1,149 @@ +/**
+ * 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.utils;
+import java.lang.ref.Reference;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+/**************************************************************************
+ * TransientCache - Uses transient references to allow unused entries to be
+ * reaped by the java garbage collector.
+ *
+ * $Revision: 1.1 $
+ * $Date: 2004/04/20 09:37:02 $
+ *
+ * Copyright (C) 2003 CERN - European Organization for Nuclear Research
+ * All rights reserved.
+ **************************************************************************/
+public abstract class TransientCache<K, V> extends AbstractMap<K, V> {
+
+ private Map<K, Reference<V>> map = new Hashtable<K, Reference<V>>();
+
+ @Override
+ public synchronized Set<Entry<K, V>> entrySet() {
+ Map<K, V> newMap = new Hashtable<K,V>();
+ Iterator<Entry<K, Reference<V>>> iter = map.entrySet().iterator();
+ while (iter.hasNext()) {
+ Entry<K, Reference<V>> me = iter.next();
+ Reference<V> ref = me.getValue();
+ V o = ref.get();
+ if (o == null) {
+ // Delete cleared reference
+ iter.remove();
+ } else {
+ // Copy out interior object
+ newMap.put(me.getKey(), o);
+ }
+ }
+ // Return set of interior objects
+ return newMap.entrySet();
+ }
+
+ @Override
+ public synchronized V put(K key, V value) {
+ Reference<V> ref = makeReference(value);
+ ref = map.put(key, ref);
+ if (ref != null)
+ return (ref.get());
+ return null;
+ }
+
+ public abstract Reference<V> makeReference(Object value);
+
+ @Override
+ public V remove(Object key) {
+ Iterator<Entry<K, Reference<V>>> i = map.entrySet().iterator();
+ Entry<K, Reference<V>> correctEntry = null;
+ if (key == null) {
+ while (correctEntry == null && i.hasNext()) {
+ Entry<K, Reference<V>> e = i.next();
+ if (e.getKey() == null)
+ correctEntry = e;
+ }
+ } else {
+ while (correctEntry == null && i.hasNext()) {
+ Entry<K, Reference<V>> e = i.next();
+ if (key.equals(e.getKey()))
+ correctEntry = e;
+ }
+ }
+ V oldValue = null;
+ if (correctEntry != null) {
+ Reference<V> correctReference = correctEntry.getValue();
+ oldValue = correctReference.get();
+ i.remove();
+ }
+ return oldValue;
+ }
+ /**
+ *
+ */
+ @Override
+ public void clear() {
+ map.entrySet().clear();
+ }
+
+ private transient Set<K> keySet = null;
+
+ @Override
+ public Set<K> keySet() {
+ if (keySet == null) {
+ keySet = new AbstractSet<K>() {
+ @Override
+ public Iterator<K> iterator() {
+ return new Iterator<K>() {
+ private Iterator<Entry<K, Reference<V>>> i = map.entrySet().iterator();
+
+ @Override
+ public boolean hasNext() {
+ return i.hasNext();
+ }
+
+ @Override
+ public K next() {
+ return i.next().getKey();
+ }
+
+ @Override
+ public void remove() {
+ i.remove();
+ }
+ };
+ }
+
+ @Override
+ public int size() {
+ return TransientCache.this.size();
+ }
+
+ @Override
+ public boolean contains(Object k) {
+ return TransientCache.this.containsKey(k);
+ }
+ };
+ }
+ return keySet;
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/WeakCache.java b/src/main/java/org/cristalise/kernel/utils/WeakCache.java new file mode 100644 index 0000000..3a37031 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/WeakCache.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.utils;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.AbstractMap;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+
+/*******************************************************************************
+ * WeakReferences are reaped if no strong references are left next time the gc has a chance.
+ * The ClusterStorageManager caches can optionally use this one, for high volume imports etc
+ *
+ * $Revision: 1.5 $ $Date: 2004/10/29 13:29:09 $
+ ******************************************************************************/
+public class WeakCache<K, V> extends AbstractMap<K, V> {
+
+ private final Map<K, WeakValue<V>> hash = new HashMap<K, WeakValue<V>>();
+ private final int minSize;
+ private final LinkedList<V> hardCache = new LinkedList<V>();
+ private final ReferenceQueue<V> queue = new ReferenceQueue<V>();
+
+ public WeakCache() {
+ this(0);
+ }
+
+ public WeakCache(int minSize) {
+ this.minSize = minSize;
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.NonStrongRefCache#get(java.lang.Object)
+ */
+ @Override
+ public V get(Object key) {
+ V result = null;
+ WeakValue<V> weak_ref = hash.get(key);
+ if (weak_ref != null) {
+ result = weak_ref.get();
+ if (result == null)
+ hash.remove(key);
+ else
+ if (minSize > 0) { // add to hard cache so it's not reaped for a while
+ hardCache.addFirst(result);
+ if (hardCache.size() > minSize) // trim last one off
+ hardCache.removeLast();
+ }
+ }
+ return result;
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.NonStrongRefCache#put(K, V)
+ */
+ @Override
+ public V put(K key, V value) {
+ processQueue();
+ if (minSize > 0) {
+ hardCache.addFirst(value);
+ if (hardCache.size() > minSize)
+ hardCache.removeLast();
+ }
+ hash.put(key, new WeakValue<V>(key, value, queue));
+ return value;
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.NonStrongRefCache#remove(java.lang.Object)
+ */
+ @Override
+ public V remove(Object key) {
+ processQueue();
+ if (hash.containsKey(key)) return hash.remove(key).get();
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.NonStrongRefCache#clear()
+ */
+ @Override
+ public void clear() {
+ hardCache.clear();
+ while(queue.poll()!=null);
+ hash.clear();
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.NonStrongRefCache#size()
+ */
+ @Override
+ public int size() {
+ processQueue();
+ return hash.size();
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.NonStrongRefCache#keySet()
+ */
+ @Override
+ public Set<K> keySet() {
+ processQueue();
+ return hash.keySet();
+ }
+
+ /* (non-Javadoc)
+ * @see org.cristalise.kernel.utils.NonStrongRefCache#entrySet()
+ */
+ @Override
+ public Set<Map.Entry<K, V>> entrySet() {
+ // Would have to create another Map to do this - too expensive
+ // Throwing runtime expensive is dangerous, but better than nulls
+ throw new UnsupportedOperationException();
+ }
+
+ private static class WeakValue<V> extends WeakReference<V> {
+ private final Object key;
+ private WeakValue(Object key, V value, ReferenceQueue<V> q) {
+ super(value, q);
+ this.key = key;
+ }
+ }
+
+ /**
+ * Look for values that have been reaped, and remove their keys from the cache
+ */
+ private void processQueue() {
+ WeakValue<V> sv;
+ while ((sv = (WeakValue<V>) queue.poll()) != null) {
+ hash.remove(sv.key);
+ }
+ }
+
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/XmlElementParser.java b/src/main/java/org/cristalise/kernel/utils/XmlElementParser.java new file mode 100644 index 0000000..a722410 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/XmlElementParser.java @@ -0,0 +1,125 @@ +/**
+ * 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.utils;
+
+import java.io.StringReader;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+public class XmlElementParser {
+ public static String[] parse(String data, String xpath) {
+ Vector<String> returnData = new Vector<String>();
+ String[] returnArray;
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder;
+ try {
+ builder = factory.newDocumentBuilder();
+ } catch (ParserConfigurationException e) {
+ Logger.error(e);
+ throw new RuntimeException("Could not create XML Document Builder");
+ }
+ StringReader is = new StringReader(data);
+ Document doc;
+ try {
+ doc = builder.parse(new InputSource(is));
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new RuntimeException("Parser malfunction");
+ }
+ StringTokenizer pathTokens = new StringTokenizer(xpath, "/");
+ int taille = pathTokens.countTokens();
+ String[] pathElements = new String[taille];
+ int i = taille;
+ while (pathTokens.hasMoreElements())
+ pathElements[--i] = pathTokens.nextToken();
+
+ if (Logger.doLog(6)) {
+ Logger.msg(6, "Path elements:");
+ for (String pathElement : pathElements)
+ Logger.debug(6, pathElement);
+ }
+
+ Logger.msg(6, "Looking for attribute " + pathElements[0] + " in "
+ + pathElements[1]);
+ NodeList nl = doc.getElementsByTagName(pathElements[1]);
+ for (int j = 0; j < nl.getLength(); j++) {
+ Logger.msg(6, "Found one");
+ Element e = (Element) nl.item(j);
+ boolean match = true;
+ Node child = e;
+ for (int k = 2; k < taille && match; k++) {
+ Logger.msg(6, "Checking parent " + pathElements[k]);
+ child = child.getParentNode();
+ if (!child.getNodeName().equals(pathElements[k])) {
+ Logger.msg(6, "No match for " + child.getNodeName());
+ match = false;
+ } else
+ Logger.msg(6, "Match");
+ }
+ if (match && e.hasAttribute(pathElements[0])) {
+ Logger.msg(
+ 6,
+ "Matching Attribute " + pathElements[0] + "="
+ + e.getAttribute(pathElements[0]));
+ returnData.add(e.getAttribute(pathElements[0]));
+ }
+ }
+
+ Logger.msg(6, "Looking for element " + pathElements[0]);
+ nl = doc.getElementsByTagName(pathElements[0]);
+ for (int j = 0; j < nl.getLength(); j++) {
+ Logger.msg(6, "Found one");
+ Element e = (Element) nl.item(j);
+ boolean match = true;
+ Node child = e;
+ for (int k = 1; k < taille && match; k++) {
+ Logger.msg(6, "Checking parent " + pathElements[k]);
+ child = child.getParentNode();
+ if (!child.getNodeName().equals(pathElements[k])) {
+ Logger.msg(6, "No match for " + child.getNodeName());
+ match = false;
+ } else
+ Logger.msg(6, "Match");
+ }
+ if (match) {
+ String s = e.getFirstChild().getNodeValue();
+ Logger.msg(6, "Found Element " + pathElements[0] + "=" + s);
+ if (s != null)
+ returnData.add(s);
+ }
+ }
+ Logger.msg(3, returnData.size() + " values found for " + xpath);
+ returnArray = new String[returnData.size()];
+ for (int j = 0; j < returnArray.length; j++)
+ returnArray[j] = returnData.get(j);
+ return returnArray;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/server/SimpleTCPIPServer.java b/src/main/java/org/cristalise/kernel/utils/server/SimpleTCPIPServer.java new file mode 100644 index 0000000..16beffe --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/server/SimpleTCPIPServer.java @@ -0,0 +1,130 @@ +/**
+ * 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.utils.server;
+
+import java.io.InterruptedIOException;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import org.cristalise.kernel.utils.Logger;
+
+
+
+public class SimpleTCPIPServer implements Runnable
+{
+ int port = 0;
+ int maxConn = 10;
+ Thread listener = null;
+ Class<?> handlerClass = null;
+ ServerSocket serverSocket = null;
+ boolean keepListening = true;
+ ArrayList<SocketHandler> currentHandlers = new ArrayList<SocketHandler>();
+ static short noServers = 0;
+
+ public SimpleTCPIPServer(int port, Class<?> handlerClass, int maxConnections)
+ {
+ this.port = port;
+ this.handlerClass = handlerClass;
+ this.maxConn = maxConnections;
+ noServers++;
+ }
+
+ public void startListening()
+ {
+ if(listener != null) return;
+ keepListening = true;
+
+ listener = new Thread(this);
+ listener.start();
+ }
+
+ public void stopListening()
+ {
+ Logger.msg("SimpleTCPIPServer: Closing server for " + handlerClass.getName() +" on port "+ port);
+ keepListening = false;
+ for (SocketHandler thisHandler : currentHandlers) {
+ thisHandler.shutdown();
+ }
+ }
+
+ @Override
+ public void run()
+ {
+ Thread.currentThread().setName("TCP/IP Server for "+handlerClass.getName());
+ Socket connectionSocket = null;
+
+ try {
+ serverSocket = new ServerSocket(port);
+ if (port == 0)
+ port = serverSocket.getLocalPort();
+ Logger.msg("SimpleTCPIPServer: Created server for " + handlerClass.getName()+" on port "+port);
+ serverSocket.setSoTimeout(500);
+ SocketHandler freeHandler = null;
+ while(keepListening) {
+ if (freeHandler == null || freeHandler.isBusy()) {
+ ListIterator<SocketHandler> i = currentHandlers.listIterator();
+ try {
+ do {
+ freeHandler = i.next();
+ } while (freeHandler.isBusy());
+ } catch (NoSuchElementException e) {
+ // create new one
+ if (currentHandlers.size() < maxConn) {
+ freeHandler = (SocketHandler)handlerClass.newInstance();
+ currentHandlers.add(freeHandler);
+ }
+ else { // max handlers are created. wait for a while, then look again
+ Logger.warning("No free handlers left for "+handlerClass.getName()+" on port "+ port + "!");
+ Thread.sleep(2000);
+ continue;
+ }
+ }
+ }
+ try {
+ connectionSocket = serverSocket.accept();
+ if (keepListening) {
+ Logger.msg("SimpleTCPIPServer: Connection to "+freeHandler.getName()+" from "+
+ connectionSocket.getInetAddress());
+ freeHandler.setSocket(connectionSocket);
+ new Thread(freeHandler).start();
+ }
+ } catch (InterruptedIOException ex1) { }// timeout just to check if we've been told to die
+
+ }
+ serverSocket.close();
+ Logger.msg("SimpleTCPIPServer: Server closed for " + handlerClass.getName() +" on port "+ port);
+ } catch(Exception ex) {
+ Logger.error(ex);
+ Logger.error("SimpleTCPIPServer.run(): Fatal Error. Listener for '"+handlerClass.getName()+"' will stop.");
+ listener = null; --noServers;
+ return;
+ }
+ listener = null;
+ Logger.msg("SimpleTCPIPServer - Servers still running: "+--noServers);
+ }
+
+ public int getPort() {
+ return port;
+ }
+}
diff --git a/src/main/java/org/cristalise/kernel/utils/server/SocketHandler.java b/src/main/java/org/cristalise/kernel/utils/server/SocketHandler.java new file mode 100644 index 0000000..457fc52 --- /dev/null +++ b/src/main/java/org/cristalise/kernel/utils/server/SocketHandler.java @@ -0,0 +1,35 @@ +/**
+ * 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.utils.server;
+
+import java.net.Socket;
+
+public interface SocketHandler extends Runnable {
+
+ public String getName();
+
+ public boolean isBusy();
+
+ public void setSocket(Socket newSocket);
+
+ public void shutdown();
+}
+
diff --git a/src/main/java/org/cristalise/storage/MemoryOnlyClusterStorage.java b/src/main/java/org/cristalise/storage/MemoryOnlyClusterStorage.java new file mode 100644 index 0000000..737a173 --- /dev/null +++ b/src/main/java/org/cristalise/storage/MemoryOnlyClusterStorage.java @@ -0,0 +1,166 @@ +/**
+ * 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.storage;
+
+import java.util.ArrayList;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.process.auth.Authenticator;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class MemoryOnlyClusterStorage extends ClusterStorage {
+
+ HashMap<ItemPath, Map<String, C2KLocalObject>> memoryCache = new HashMap<ItemPath, Map<String, C2KLocalObject>>();
+ /**
+ *
+ */
+ public MemoryOnlyClusterStorage() {
+ memoryCache = new HashMap<ItemPath, Map<String,C2KLocalObject>>();
+ }
+
+ @Override
+ public void open(Authenticator auth) throws PersistencyException {
+
+ }
+
+ @Override
+ public void close() throws PersistencyException {
+ }
+
+ @Override
+ public short queryClusterSupport(String clusterType) {
+ return ClusterStorage.READWRITE;
+ }
+
+ @Override
+ public String getName() {
+ return "Memory Cache";
+ }
+
+ @Override
+ public String getId() {
+ return "Memory Cache";
+ }
+
+ @Override
+ public C2KLocalObject get(ItemPath thisItem, String path)
+ throws PersistencyException {
+ Map<String, C2KLocalObject> sysKeyMemCache = memoryCache.get(thisItem);
+ if (sysKeyMemCache != null)
+ return sysKeyMemCache.get(path);
+ return null;
+ }
+
+ @Override
+ public void put(ItemPath thisItem, C2KLocalObject obj)
+ throws PersistencyException {
+
+ // create item cache if not present
+ Map<String, C2KLocalObject> sysKeyMemCache;
+ synchronized (memoryCache) {
+ if (memoryCache.containsKey(thisItem))
+ sysKeyMemCache = memoryCache.get(thisItem);
+ else {
+ sysKeyMemCache = new HashMap<String, C2KLocalObject>();
+ memoryCache.put(thisItem, sysKeyMemCache);
+ }
+ }
+
+ // store object in the cache
+ String path = ClusterStorage.getPath(obj);
+ synchronized(sysKeyMemCache) {
+ sysKeyMemCache.put(path, obj);
+ }
+
+ }
+
+ @Override
+ public void delete(ItemPath thisItem, String path)
+ throws PersistencyException {
+ Map<String, C2KLocalObject> sysKeyMemCache = memoryCache.get(thisItem);
+ if (sysKeyMemCache != null) {
+ synchronized (sysKeyMemCache) {
+ if (sysKeyMemCache.containsKey(path)) {
+ sysKeyMemCache.remove(path);
+ if (sysKeyMemCache.isEmpty()) {
+ synchronized (memoryCache) {
+ memoryCache.remove(thisItem);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public String[] getClusterContents(ItemPath thisItem, String path)
+ throws PersistencyException {
+ Map<String, C2KLocalObject> sysKeyMemCache = memoryCache.get(thisItem);
+ ArrayList<String> result = new ArrayList<String>();
+ if (sysKeyMemCache != null) {
+ while (path.endsWith("/"))
+ path = path.substring(0,path.length()-1);
+ path = path+"/";
+ for (String thisPath : sysKeyMemCache.keySet()) {
+ if (thisPath.startsWith(path)) {
+ String end = thisPath.substring(path.length());
+ int slash = end.indexOf('/');
+ String suffix = slash>-1?end.substring(0, slash):end;
+ if (!result.contains(suffix)) result.add(suffix);
+ }
+ }
+ }
+ return result.toArray(new String[result.size()]);
+ }
+
+ public void dumpContents(ItemPath thisItem) {
+ synchronized(memoryCache) {
+ Logger.msg(0, "Cached Objects of Entity "+thisItem);
+ Map<String, C2KLocalObject> sysKeyMemCache = memoryCache.get(thisItem);
+ if (sysKeyMemCache == null) {
+ Logger.msg(0, "No cache found");
+ return;
+ }
+ try {
+ synchronized(sysKeyMemCache) {
+ for (Object name : sysKeyMemCache.keySet()) {
+ String path = (String) name;
+ try {
+ Logger.msg(0, " Path "+path+": "+sysKeyMemCache.get(path).getClass().getName());
+ } catch (NullPointerException e) {
+ Logger.msg(0, " Path "+path+": reaped");
+ }
+ }
+ }
+ } catch (ConcurrentModificationException ex) {
+ Logger.msg(0, "Cache modified - aborting");
+ }
+ }
+ Logger.msg(0, "Total number of cached entities: "+memoryCache.size());
+ }
+}
diff --git a/src/main/java/org/cristalise/storage/ProxyLoader.java b/src/main/java/org/cristalise/storage/ProxyLoader.java new file mode 100644 index 0000000..8922e35 --- /dev/null +++ b/src/main/java/org/cristalise/storage/ProxyLoader.java @@ -0,0 +1,160 @@ +/**
+ * 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.storage;
+import java.util.HashMap;
+import java.util.StringTokenizer;
+
+import org.cristalise.kernel.common.ObjectNotFoundException;
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.AgentHelper;
+import org.cristalise.kernel.entity.C2KLocalObject;
+import org.cristalise.kernel.entity.Item;
+import org.cristalise.kernel.entity.ItemHelper;
+import org.cristalise.kernel.lookup.ItemPath;
+import org.cristalise.kernel.lookup.Lookup;
+import org.cristalise.kernel.persistency.ClusterStorage;
+import org.cristalise.kernel.persistency.outcome.Outcome;
+import org.cristalise.kernel.process.Gateway;
+import org.cristalise.kernel.process.auth.Authenticator;
+import org.cristalise.kernel.utils.Logger;
+
+
+/** Used by proxies to load clusters by queryData from the Entity.
+* Last client storage - only used if not cached elsewhere
+*/
+
+public class ProxyLoader extends ClusterStorage {
+ HashMap<ItemPath, Item> entities = new HashMap<ItemPath, Item>();
+ Lookup lookup;
+
+ @Override
+ public void open(Authenticator auth) throws PersistencyException {
+ lookup = Gateway.getLookup();
+ }
+
+ @Override
+ public void close() throws PersistencyException {
+ }
+ // introspection
+ @Override
+ public short queryClusterSupport(String clusterType) {
+ return READ;
+ }
+
+ @Override
+ public String getName() {
+ return "Proxy Cluster Loader";
+ }
+
+ @Override
+ public String getId() {
+ return "CORBA";
+ }
+
+ // retrieve object by path
+ @Override
+ public C2KLocalObject get(ItemPath thisItem, String path) throws PersistencyException {
+ try {
+ Item thisEntity = getIOR(thisItem);
+ String type = getClusterType(path);
+
+ // fetch the xml from the item
+ String queryData = thisEntity.queryData(path);
+ if (Logger.doLog(6)) Logger.msg(6, "ProxyLoader - "+thisItem+":"+path+" = "+queryData);
+
+ if (queryData != null) {
+ if (type.equals(OUTCOME))
+ return new Outcome(path, queryData);
+ else
+ return (C2KLocalObject)Gateway.getMarshaller().unmarshall(queryData);
+ }
+ } catch (ObjectNotFoundException e) {
+ return null;
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new PersistencyException(e.getMessage());
+ }
+ return null;
+ }
+
+ // store object by path
+ @Override
+ public void put(ItemPath thisItem, C2KLocalObject obj) throws PersistencyException {
+ // not supported
+ throw new PersistencyException("Cannot write to items through the ProxyLoader");
+ }
+ // delete cluster
+ @Override
+ public void delete(ItemPath thisItem, String path) throws PersistencyException {
+ // not supported
+ throw new PersistencyException("Cannot write to items through the ProxyLoader");
+ }
+
+ /* navigation */
+
+ // directory listing
+ @Override
+ public String[] getClusterContents(ItemPath thisItem, String path) throws PersistencyException {
+ try {
+ Item thisEntity = getIOR(thisItem);
+ String contents = thisEntity.queryData(path+"/all");
+ StringTokenizer tok = new StringTokenizer(contents, ",");
+ String[] result = new String[tok.countTokens()];
+ for (int i=0; i<result.length; i++)
+ result[i] = tok.nextToken();
+
+ return result;
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new PersistencyException(e.getMessage());
+ }
+ }
+
+ private Item getIOR(ItemPath thisPath) throws PersistencyException {
+ if (entities.containsKey(thisPath)) {
+ // check the cache
+ Logger.msg(7, "ProxyLoader.getIOR() - "+thisPath+" cached.");
+ return entities.get(thisPath);
+ }
+
+ try {
+ Logger.msg(7, "ProxyLoader.getIOR() - Resolving "+thisPath+".");
+ org.omg.CORBA.Object ior = lookup.resolve(thisPath);
+
+ Item thisItem = null;
+ try {
+ thisItem = ItemHelper.narrow(ior);
+ } catch (org.omg.CORBA.BAD_PARAM ex) {
+ try {
+ thisItem = AgentHelper.narrow(ior);
+ } catch (org.omg.CORBA.BAD_PARAM ex2) {
+ throw new PersistencyException ("Could not narrow "+thisItem+" as a known Entity type");
+ }
+ }
+
+ Logger.msg(7, "ProxyLoader.getIOR() - Found "+thisItem+".");
+ entities.put(thisPath, thisItem);
+ return thisItem;
+ } catch (Exception e) {
+ throw new PersistencyException("Error narrowing "+thisPath+": "+e.getMessage());
+ }
+ }
+}
diff --git a/src/main/java/org/cristalise/storage/XMLClusterStorage.java b/src/main/java/org/cristalise/storage/XMLClusterStorage.java new file mode 100644 index 0000000..3ac864e --- /dev/null +++ b/src/main/java/org/cristalise/storage/XMLClusterStorage.java @@ -0,0 +1,178 @@ +/**
+ * This file is part of the CRISTAL-iSE kernel.
+ * Copyright (c) 2001-2014 The CRISTAL Consortium. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; with out even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * http://www.fsf.org/licensing/licenses/lgpl.html
+ */
+package org.cristalise.storage;
+import java.io.File;
+import java.util.ArrayList;
+
+import org.cristalise.kernel.common.PersistencyException;
+import org.cristalise.kernel.entity.C2KLocalObject;
+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.process.Gateway;
+import org.cristalise.kernel.process.auth.Authenticator;
+import org.cristalise.kernel.utils.FileStringUtility;
+import org.cristalise.kernel.utils.Logger;
+
+
+public class XMLClusterStorage extends ClusterStorage {
+ String rootDir=null;
+
+ public XMLClusterStorage() {
+ }
+
+ @Override
+ public void open(Authenticator auth) throws PersistencyException {
+ String rootProp = Gateway.getProperties().getString("XMLStorage.root");
+ if (rootProp == null)
+ throw new PersistencyException("XMLClusterStorage.open() - Root path not given in config file.");
+
+ rootDir = new File(rootProp).getAbsolutePath();
+
+ if( !FileStringUtility.checkDir( rootDir ) ) {
+ Logger.error("XMLClusterStorage.open() - Path " + rootDir + "' does not exist. Attempting to create.");
+ boolean success = FileStringUtility.createNewDir(rootDir);
+ if (!success) throw new PersistencyException("XMLClusterStorage.open() - Could not create dir "+ rootDir +". Cannot continue.");
+ }
+ }
+
+ @Override
+ public void close() {
+ rootDir = null;
+ }
+
+ // introspection
+ @Override
+ public short queryClusterSupport(String clusterType) {
+ return ClusterStorage.READWRITE;
+ }
+
+ @Override
+ public String getName() {
+ return "XML File Cluster Storage";
+ }
+
+ @Override
+ public String getId() {
+ return "XML";
+ }
+
+ /* object manipulation */
+
+ // retrieve object by path
+ @Override
+ public C2KLocalObject get(ItemPath itemPath, String path) throws PersistencyException {
+ try {
+ String type = ClusterStorage.getClusterType(path);
+ String filePath = getFilePath(itemPath, path)+".xml";
+ String objString = FileStringUtility.file2String(filePath);
+ if (objString.length() == 0) return null;
+ Logger.debug(9, objString);
+ if (type.equals("Outcome"))
+ return new Outcome(path, objString);
+ else {
+ C2KLocalObject obj = (C2KLocalObject)Gateway.getMarshaller().unmarshall(objString);
+ return obj;
+ }
+
+ } catch (Exception e) {
+ Logger.msg(3,"XMLClusterStorage.get() - The path "+path+" from "+itemPath+" does not exist.: "+e.getMessage());
+ }
+ return null;
+ }
+
+ // store object by path
+ @Override
+ public void put(ItemPath itemPath, C2KLocalObject obj) throws PersistencyException {
+ try {
+ String filePath = getFilePath(itemPath, getPath(obj)+".xml");
+ Logger.msg(7, "Writing "+filePath);
+ String data = Gateway.getMarshaller().marshall(obj);
+
+ String dir = filePath.substring(0, filePath.lastIndexOf('/'));
+ if( !FileStringUtility.checkDir( dir ) ) {
+ boolean success = FileStringUtility.createNewDir(dir);
+ if (!success) throw new PersistencyException("XMLClusterStorage.put() - Could not create dir "+ dir +". Cannot continue.");
+ }
+ FileStringUtility.string2File(filePath, data);
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new PersistencyException("XMLClusterStorage.put() - Could not write "+getPath(obj)+" to "+itemPath);
+ }
+ }
+
+ // delete cluster
+ @Override
+ public void delete(ItemPath itemPath, String path) throws PersistencyException {
+ try {
+ String filePath = getFilePath(itemPath, path+".xml");
+ boolean success = FileStringUtility.deleteDir(filePath, true, true);
+ if (success) return;
+ filePath = getFilePath(itemPath, path);
+ success = FileStringUtility.deleteDir(filePath, true, true);
+ if (success) return;
+ } catch(Exception e) { }
+ throw new PersistencyException("XMLClusterStorage.delete() - Failure deleting path "+path+" in "+itemPath);
+ }
+
+ /* navigation */
+
+ // directory listing
+ @Override
+ public String[] getClusterContents(ItemPath itemPath, String path) throws PersistencyException {
+ String[] result = new String[0];
+ try {
+ String filePath = getFilePath(itemPath, path);
+ ArrayList<String> paths = FileStringUtility.listDir( filePath, true, false );
+ if (paths == null) return result; // dir doesn't exist yet
+ ArrayList<String> contents = new ArrayList<String>();
+ String previous = null;
+ for (int i=0; i<paths.size(); i++) {
+ String next = paths.get(i);
+
+ // trim off the xml from the end if it's there
+ if (next.endsWith(".xml")) next = next.substring(0, next.length()-4);
+
+ // avoid duplicates (xml and dir)
+ if (next.equals(previous)) continue;
+ previous = next;
+
+ // only keep the last bit of the path
+ if (next.indexOf('/') > -1) next = next.substring(next.lastIndexOf('/')+1);
+ contents.add(next);
+ }
+
+ result = contents.toArray(result);
+ return result;
+ } catch (Exception e) {
+ Logger.error(e);
+ throw new PersistencyException("XMLClusterStorage.getClusterContents() - Could not get contents of "+path+" from "+itemPath+": "+e.getMessage());
+ }
+ }
+
+ protected String getFilePath(ItemPath itemPath, String path) throws InvalidItemPathException {
+ if (path.length() == 0 || path.charAt(0) != '/') path = "/"+path;
+ String filePath = rootDir+itemPath.toString()+path;
+ Logger.msg(8, "XMLClusterStorage.getFilePath() - "+filePath);
+ return filePath;
+ }
+}
|
