summaryrefslogtreecommitdiff
path: root/src/main/java/org/cristalise/kernel/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/org/cristalise/kernel/utils')
-rw-r--r--src/main/java/org/cristalise/kernel/utils/ActDefCache.java68
-rw-r--r--src/main/java/org/cristalise/kernel/utils/CastorArrayList.java74
-rw-r--r--src/main/java/org/cristalise/kernel/utils/CastorHashMap.java101
-rw-r--r--src/main/java/org/cristalise/kernel/utils/CastorXMLUtility.java188
-rw-r--r--src/main/java/org/cristalise/kernel/utils/DateUtility.java138
-rw-r--r--src/main/java/org/cristalise/kernel/utils/DescriptionObject.java31
-rw-r--r--src/main/java/org/cristalise/kernel/utils/DescriptionObjectCache.java105
-rw-r--r--src/main/java/org/cristalise/kernel/utils/FileStringUtility.java450
-rw-r--r--src/main/java/org/cristalise/kernel/utils/GTimeStampComparator.java46
-rw-r--r--src/main/java/org/cristalise/kernel/utils/KeyValuePair.java107
-rw-r--r--src/main/java/org/cristalise/kernel/utils/Language.java86
-rw-r--r--src/main/java/org/cristalise/kernel/utils/LocalObjectLoader.java111
-rw-r--r--src/main/java/org/cristalise/kernel/utils/Logger.java207
-rw-r--r--src/main/java/org/cristalise/kernel/utils/ObjectProperties.java215
-rw-r--r--src/main/java/org/cristalise/kernel/utils/SoftCache.java139
-rw-r--r--src/main/java/org/cristalise/kernel/utils/StateMachineCache.java67
-rw-r--r--src/main/java/org/cristalise/kernel/utils/TransientCache.java149
-rw-r--r--src/main/java/org/cristalise/kernel/utils/WeakCache.java154
-rw-r--r--src/main/java/org/cristalise/kernel/utils/XmlElementParser.java125
-rw-r--r--src/main/java/org/cristalise/kernel/utils/server/SimpleTCPIPServer.java130
-rw-r--r--src/main/java/org/cristalise/kernel/utils/server/SocketHandler.java35
21 files changed, 2726 insertions, 0 deletions
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();
+}
+