Modified: 
ode/trunk/dao-hibernate/src/main/java/org/apache/ode/daohib/bpel/CorrelatorDaoImpl.java
URL: 
http://svn.apache.org/viewvc/ode/trunk/dao-hibernate/src/main/java/org/apache/ode/daohib/bpel/CorrelatorDaoImpl.java?rev=663741&r1=663740&r2=663741&view=diff
==============================================================================
--- 
ode/trunk/dao-hibernate/src/main/java/org/apache/ode/daohib/bpel/CorrelatorDaoImpl.java
 (original)
+++ 
ode/trunk/dao-hibernate/src/main/java/org/apache/ode/daohib/bpel/CorrelatorDaoImpl.java
 Thu Jun  5 14:14:08 2008
@@ -25,7 +25,6 @@
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.ode.bpel.common.CorrelationKey;
-import org.apache.ode.bpel.common.ProcessState;
 import org.apache.ode.bpel.dao.CorrelatorDAO;
 import org.apache.ode.bpel.dao.MessageExchangeDAO;
 import org.apache.ode.bpel.dao.MessageRouteDAO;
@@ -36,7 +35,7 @@
 import org.apache.ode.daohib.bpel.hobj.HCorrelatorSelector;
 import org.apache.ode.daohib.bpel.hobj.HMessageExchange;
 import org.apache.ode.daohib.bpel.hobj.HProcessInstance;
-import org.apache.ode.utils.ArrayUtils;
+import org.apache.ode.utils.CollectionUtils;
 import org.hibernate.Hibernate;
 import org.hibernate.LockMode;
 import org.hibernate.Query;
@@ -147,7 +146,7 @@
     public void enqueueMessage(MessageExchangeDAO mex, CorrelationKey[] 
correlationKeys) {
         String[] keys = canonifyKeys(correlationKeys);
         String hdr = "enqueueMessage(mex=" + ((MessageExchangeDaoImpl) 
mex)._hobj.getId() + " keys="
-                + ArrayUtils.makeCollection(ArrayList.class, keys) + "): ";
+                + CollectionUtils.makeCollection(ArrayList.class, keys) + "): 
";
 
         if (__log.isDebugEnabled())
             __log.debug(hdr);

Modified: ode/trunk/jacob/src/main/java/org/apache/ode/jacob/JacobRunnable.java
URL: 
http://svn.apache.org/viewvc/ode/trunk/jacob/src/main/java/org/apache/ode/jacob/JacobRunnable.java?rev=663741&r1=663740&r2=663741&view=diff
==============================================================================
--- ode/trunk/jacob/src/main/java/org/apache/ode/jacob/JacobRunnable.java 
(original)
+++ ode/trunk/jacob/src/main/java/org/apache/ode/jacob/JacobRunnable.java Thu 
Jun  5 14:14:08 2008
@@ -23,7 +23,7 @@
 import java.util.Collections;
 import java.util.Set;
 
-import org.apache.ode.utils.ArrayUtils;
+import org.apache.ode.utils.CollectionUtils;
 
 /**
  * Base class for process abstractions. An abstraction is a parameterized
@@ -71,7 +71,7 @@
     
     static {
         try {
-            Method m = JacobRunnable.class.getMethod("run", 
ArrayUtils.EMPTY_CLASS_ARRAY);
+            Method m = JacobRunnable.class.getMethod("run", 
CollectionUtils.EMPTY_CLASS_ARRAY);
             IMPLEMENTED_METHODS = Collections.singleton(m);
         } catch (NoSuchMethodException e) {
             throw new AssertionError(e);

Modified: 
ode/trunk/jacob/src/main/java/org/apache/ode/jacob/vpu/ChannelFactory.java
URL: 
http://svn.apache.org/viewvc/ode/trunk/jacob/src/main/java/org/apache/ode/jacob/vpu/ChannelFactory.java?rev=663741&r1=663740&r2=663741&view=diff
==============================================================================
--- ode/trunk/jacob/src/main/java/org/apache/ode/jacob/vpu/ChannelFactory.java 
(original)
+++ ode/trunk/jacob/src/main/java/org/apache/ode/jacob/vpu/ChannelFactory.java 
Thu Jun  5 14:14:08 2008
@@ -24,7 +24,7 @@
 
 import org.apache.ode.jacob.Channel;
 import org.apache.ode.jacob.soup.CommChannel;
-import org.apache.ode.utils.ArrayUtils;
+import org.apache.ode.utils.CollectionUtils;
 
 public class ChannelFactory {
     private static final Method METHOD_OBJECT_EQUALS;
@@ -39,7 +39,7 @@
         }
 
         try {
-            METHOD_CHANNEL_EXPORT = Channel.class.getMethod("export", 
ArrayUtils.EMPTY_CLASS_ARRAY);
+            METHOD_CHANNEL_EXPORT = Channel.class.getMethod("export", 
CollectionUtils.EMPTY_CLASS_ARRAY);
         } catch (Exception e) {
             throw new AssertionError("No export() method on Object!");
         }

Modified: 
ode/trunk/jacob/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java
URL: 
http://svn.apache.org/viewvc/ode/trunk/jacob/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java?rev=663741&r1=663740&r2=663741&view=diff
==============================================================================
--- 
ode/trunk/jacob/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java 
(original)
+++ 
ode/trunk/jacob/src/main/java/org/apache/ode/jacob/vpu/ExecutionQueueImpl.java 
Thu Jun  5 14:14:08 2008
@@ -33,7 +33,7 @@
 import org.apache.ode.jacob.soup.ExecutionQueue;
 import org.apache.ode.jacob.soup.ExecutionQueueObject;
 import org.apache.ode.jacob.soup.ReplacementMap;
-import org.apache.ode.utils.ArrayUtils;
+import org.apache.ode.utils.CollectionUtils;
 import org.apache.ode.utils.ObjectPrinter;
 
 import java.io.Externalizable;
@@ -142,7 +142,7 @@
 
     public Continuation dequeueReaction() {
         if (__log.isTraceEnabled()) {
-            __log.trace(ObjectPrinter.stringifyMethodEnter("dequeueReaction", 
ArrayUtils.EMPTY_OBJECT_ARRAY));
+            __log.trace(ObjectPrinter.stringifyMethodEnter("dequeueReaction", 
CollectionUtils.EMPTY_OBJECT_ARRAY));
         }
 
         Continuation continuation = null;
@@ -209,7 +209,7 @@
 
     public int cycle() {
         if (__log.isTraceEnabled()) {
-            __log.trace(ObjectPrinter.stringifyMethodEnter("cycle", 
ArrayUtils.EMPTY_OBJECT_ARRAY));
+            __log.trace(ObjectPrinter.stringifyMethodEnter("cycle", 
CollectionUtils.EMPTY_OBJECT_ARRAY));
         }
 
         return ++_currentCycle;
@@ -243,7 +243,7 @@
 
     public void flush() {
         if (__log.isTraceEnabled()) {
-            __log.trace(ObjectPrinter.stringifyMethodEnter("flush", 
ArrayUtils.EMPTY_OBJECT_ARRAY));
+            __log.trace(ObjectPrinter.stringifyMethodEnter("flush", 
CollectionUtils.EMPTY_OBJECT_ARRAY));
         }
     }
 
@@ -622,7 +622,7 @@
         public MessageFrame(CommGroupFrame commFrame, ChannelFrame 
channelFrame, String method, Object[] args) {
             super(commFrame, channelFrame);
             this.method = method;
-            this.args = args == null ? ArrayUtils.EMPTY_CLASS_ARRAY : args;
+            this.args = args == null ? CollectionUtils.EMPTY_CLASS_ARRAY : 
args;
         }
 
         public void readExternal(ObjectInput in) throws IOException, 
ClassNotFoundException {

Modified: ode/trunk/jacob/src/main/java/org/apache/ode/jacob/vpu/JacobVPU.java
URL: 
http://svn.apache.org/viewvc/ode/trunk/jacob/src/main/java/org/apache/ode/jacob/vpu/JacobVPU.java?rev=663741&r1=663740&r2=663741&view=diff
==============================================================================
--- ode/trunk/jacob/src/main/java/org/apache/ode/jacob/vpu/JacobVPU.java 
(original)
+++ ode/trunk/jacob/src/main/java/org/apache/ode/jacob/vpu/JacobVPU.java Thu 
Jun  5 14:14:08 2008
@@ -22,7 +22,7 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.ode.jacob.*;
 import org.apache.ode.jacob.soup.*;
-import org.apache.ode.utils.ArrayUtils;
+import org.apache.ode.utils.CollectionUtils;
 import org.apache.ode.utils.ObjectPrinter;
 import org.apache.ode.utils.msg.MessageBundle;
 
@@ -57,7 +57,7 @@
      */
     static {
         try {
-            REDUCE_METHOD = JacobRunnable.class.getMethod("run", 
ArrayUtils.EMPTY_CLASS_ARRAY);
+            REDUCE_METHOD = JacobRunnable.class.getMethod("run", 
CollectionUtils.EMPTY_CLASS_ARRAY);
         } catch (Exception e) {
             throw new Error("Cannot resolve 'run' method", e);
         }
@@ -118,7 +118,7 @@
      */
     public boolean execute() {
         if (__log.isTraceEnabled()) {
-            __log.trace(ObjectPrinter.stringifyMethodEnter("execute", 
ArrayUtils.EMPTY_OBJECT_ARRAY));
+            __log.trace(ObjectPrinter.stringifyMethodEnter("execute", 
CollectionUtils.EMPTY_OBJECT_ARRAY));
         }
         if (_executionQueue == null) {
             throw new IllegalStateException("No state object for VPU!");
@@ -151,7 +151,7 @@
 
     public void flush() {
         if (__log.isTraceEnabled()) {
-            __log.trace(ObjectPrinter.stringifyMethodEnter("flush", 
ArrayUtils.EMPTY_OBJECT_ARRAY));
+            __log.trace(ObjectPrinter.stringifyMethodEnter("flush", 
CollectionUtils.EMPTY_OBJECT_ARRAY));
         }
         _executionQueue.flush();
     }
@@ -214,7 +214,7 @@
         if (__log.isDebugEnabled()) {
             __log.debug("injecting " + concretion);
         }
-        addReaction(concretion, REDUCE_METHOD, ArrayUtils.EMPTY_OBJECT_ARRAY,
+        addReaction(concretion, REDUCE_METHOD, 
CollectionUtils.EMPTY_OBJECT_ARRAY,
                 (__log.isInfoEnabled() ? concretion.toString() : null));
     }
 
@@ -313,7 +313,7 @@
                 desc = template.toString();
             }
             _statistics.numReductionsStruct++;
-            addReaction(template, REDUCE_METHOD, 
ArrayUtils.EMPTY_OBJECT_ARRAY, desc);
+            addReaction(template, REDUCE_METHOD, 
CollectionUtils.EMPTY_OBJECT_ARRAY, desc);
         }
 
         public Channel message(Channel channel, Method method, Object[] args) {

Added: ode/trunk/utils/src/main/java/org/apache/ode/utils/CollectionUtils.java
URL: 
http://svn.apache.org/viewvc/ode/trunk/utils/src/main/java/org/apache/ode/utils/CollectionUtils.java?rev=663741&view=auto
==============================================================================
--- ode/trunk/utils/src/main/java/org/apache/ode/utils/CollectionUtils.java 
(added)
+++ ode/trunk/utils/src/main/java/org/apache/ode/utils/CollectionUtils.java Thu 
Jun  5 14:14:08 2008
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ode.utils;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Utility class for dealing with arrays.
+ */
+public class CollectionUtils {
+
+    public static final Object[] EMPTY_OBJECT_ARRAY = new Object[]{};
+    public static final Class[] EMPTY_CLASS_ARRAY = new Class[]{};
+
+    /**
+     * Make a [EMAIL PROTECTED] Collection} out of an array.
+     *
+     * @param type     the type of [EMAIL PROTECTED] Collection} to make.
+     * @param elements objects to put into the collection.
+     * @return a [EMAIL PROTECTED] Collection} of the type given in the 
<code>type</type> argument containing <code>elements</code>
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> Collection<T> makeCollection(Class<? extends Collection> 
type, T[] elements) {
+        if (elements == null) {
+            return null;
+        }
+        try {
+            Collection<T> c = type.newInstance();
+
+            for (int i = 0; i < elements.length; ++i) {
+                c.add(elements[i]);
+            }
+
+            return c;
+        } catch (Exception ex) {
+            throw new IllegalArgumentException("Invalid arguments.", ex);
+        }
+    }
+
+    /**
+     * Compares the two specified maps for equality.  Returns
+     * <tt>true</tt> if the two maps represent the same mappings.  More 
formally, two maps <tt>m1</tt> and
+     * <tt>m2</tt> represent the same mappings if
+     * <tt>m1.keySet().equals(m2.keySet())</tt> and for every key <tt>k</tt>
+     * in <tt>m1.keySet()</tt>, <tt> (m1.get(k)==null ? m2.get(k)==null :
+     * m1.get(k).equals(m2.get(k))) </tt>.
+     * <p/>
+     * This implementation first checks if the <tt>m1</tt> and <tt>m2</tt> are 
the same object;
+     * if so it returns <tt>true</tt>.  Then, it checks if the two maps have 
the same sizw; if
+     * not, it returns <tt>false</tt>.  If so, it iterates over <tt>m1</tt>'s
+     * <tt>entrySet</tt> collection, and checks that map <tt>m1</tt>
+     * contains each mapping that map <tt>m2</tt> contains.  If map <tt>m1</tt>
+     * fails to contain such a mapping, <tt>false</tt> is returned.  If the
+     * iteration completes, <tt>true</tt> is returned.
+     *
+     * @return <tt>true</tt> if the specified object is equal to this map.
+     */
+    public static boolean equals(Map m1, Map m2) {
+        if (m2 == m1) return true;
+        if (m1 == null) return false;
+        if (m2 == null) return false;
+        if (m2.size() != m1.size()) return false;
+
+        try {
+            for (Iterator it = m1.entrySet().iterator(); it.hasNext();) {
+                Map.Entry e = (Map.Entry) it.next();
+                Object key = e.getKey();
+                Object value = e.getValue();
+                if (value == null) {
+                    if (!(m2.get(key) == null && m2.containsKey(key)))
+                        return false;
+                } else {
+                    if (!value.equals(m2.get(key)))
+                        return false;
+                }
+            }
+        } catch (ClassCastException unused) {
+            return false;
+        } catch (NullPointerException unused) {
+            return false;
+        }
+        return true;
+    }
+
+}

Added: 
ode/trunk/utils/src/main/java/org/apache/ode/utils/HierarchiedProperties.java
URL: 
http://svn.apache.org/viewvc/ode/trunk/utils/src/main/java/org/apache/ode/utils/HierarchiedProperties.java?rev=663741&view=auto
==============================================================================
--- 
ode/trunk/utils/src/main/java/org/apache/ode/utils/HierarchiedProperties.java 
(added)
+++ 
ode/trunk/utils/src/main/java/org/apache/ode/utils/HierarchiedProperties.java 
Thu Jun  5 14:14:08 2008
@@ -0,0 +1,433 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ode.utils;
+
+import org.apache.commons.collections.map.MultiKeyMap;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Collections;
+
+/**
+ * This class load a regular property file in [EMAIL PROTECTED] 
java.util.Properties} instance. The main feature is that property can
+ * be hierarchied/chained in three levels. Then when querying for a property, 
if it's not found in the deepest level,
+ * the parent will be queryed and so on.
+ * <p/>
+ * A prefix must be defined to discriminate the property name and the level-1, 
level-2 names. The default prefix is [EMAIL PROTECTED] #ODE_PREFFIX}.
+ * <p/>
+ * Properties must respect the following pattern: 
[level1[.level2].prefix.]property
+ * <p/>
+ * A concrete use case could be the definition of properties for wsdl services 
and ports.
+ * <br/>Level 0 would be: values common to all services and ports.
+ * <br/>Level 1: values common to a given service.
+ * <br/>Level 2: values common to a given port.
+ * <p/>
+ * For instance, if the property file looks like this:
+ * <pre>
+ * timeout=40000
+ * film-service.port-of-cannes.ode.timeout=50000
+ * <p/>
+ * max-redirects=30
+ * brel-service.ode.max-redirects=40
+ * brel-service.port-of-amsterdam.ode.max-redirects=60
+ * </pre>
+ * The following values may be expected:
+ * <pre>
+ * getProperty("max-redirects")                                       => 30
+ * getProperty("brel-service", "max-redirects")                       => 40
+ * getProperty("brel-service", "port-of-amsterdam", "max-redirects")  => 60
+ * <p/>
+ * getProperty("film-service", "timeout")                       => 40000
+ * getProperty("film-service", "port-of-cannes", "timeout")     => 50000
+ * getProperty("brel-service", "port-of-amsterdam", "timeout")  => 40000
+ * </pre>
+ * <p/>
+ * Values may contain some environment variables. For instance, message=You're 
using ${java.version}.
+ * <p/>
+ * This class is not thread-safe.
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Alexis Midon</a>
+ */
+public class HierarchiedProperties {
+
+    private static final Log log = 
LogFactory.getLog(HierarchiedProperties.class);
+
+    // Prefix used by all properties
+    public static final String ODE_PREFFIX = "ode.";
+
+    // the raw properties as of loaded from the filesystem
+    private Properties props = new Properties();
+    private File file;
+    private String prefix;
+    /*
+        This map contains ChainedMap instances hierarchied according to the 
service and/or port they are associated with.
+        All ChainedMap instances has a common parent.
+        The ChainedMap instances are chained to each others so that if a 
property is not found for [service, port],
+        the ChainedMap associated to [service] will be queried, and if still 
not found, then the common parent.
+
+        The ChainedMap instance common to all services and ports is associated 
to the [null, null] key.
+        ChainedMap instance common to all ports of a given service is 
associated to [service, null].
+        ChainedMap instance of a given service, port couple is associated to 
[service, port].
+
+        The ChainedMap instances contain string values as loaded from the 
filesystem.
+     */
+    private MultiKeyMap hierarchiedMap = new MultiKeyMap();
+
+    // map used to cache immutable versions of the maps
+    private transient MultiKeyMap cacheOfImmutableMaps = new MultiKeyMap();
+
+    /**
+     * @param file   the property file to be loaded. The file may not exist.
+     *               But if the file exists it has to be a file (not a 
directory), otherwhise an IOException is thrown.
+     * @param prefix the property prefix
+     * @throws IOException
+     */
+    public HierarchiedProperties(File file, String prefix) throws IOException {
+        this.file = file;
+        this.prefix = prefix;
+        loadFile();
+    }
+
+    public HierarchiedProperties(File file) throws IOException {
+        this(file, ODE_PREFFIX);
+    }
+
+    /**
+     * Clear all existing content, read the file and parse each property. 
Simply logs a message and returns if the file does not exist.
+     *
+     * @throws IOException if the file is a Directory
+     */
+    public void loadFile() throws IOException {
+        if (!file.exists()) {
+            if (log.isDebugEnabled()) log.debug("File does not exist [" + file 
+ "] Properties will be empty.");
+            return;
+        }
+        // #1. clear all existing content
+        clear();
+
+        // #2. read the file
+        FileInputStream fis = new FileInputStream(file);
+        try {
+            if (log.isDebugEnabled()) log.debug("Loading property file: " + 
file);
+            props.load(fis);
+        } finally {
+            fis.close();
+        }
+
+        // #3. put the root map
+        hierarchiedMap.put(null, null, new ChainedMap());
+
+        // #4. process each property
+        for (Object key : props.keySet()) {
+            String value = (String) props.get(key);
+
+            // replace any env variables by its value
+            value = SystemUtils.replaceSystemProperties(value);
+            props.put(key, value);
+
+            // parse the property name
+            String[] info = parseProperty((String) key);
+            String service = info[0];
+            String port = info[1];
+            String targetedProperty = info[2];
+
+            // get the map associated to this port
+            ChainedMap p = (ChainedMap) hierarchiedMap.get(service, port);
+            if (p == null) {
+                // create it if necessary
+                // get the associated service map
+                ChainedMap s = (ChainedMap) hierarchiedMap.get(service, null);
+                if (s == null) {
+                    // create the service map if necessary, the parent is the 
root map.
+                    s = new ChainedMap(getRootMap());
+                    // put it in the multi-map
+                    hierarchiedMap.put(service, null, s);
+                }
+
+                // create the map itself and link it to theservice map
+                p = new ChainedMap(s);
+                // put it in the multi-map
+                hierarchiedMap.put(service, port, p);
+            }
+
+            // save the key/value in its chained map
+            p.put(targetedProperty, value);
+        }
+    }
+
+    /**
+     * Clear all content. If [EMAIL PROTECTED] #loadFile()} is not invoked 
later, all returned values will be null.
+     */
+    public void clear() {
+        props.clear();
+        hierarchiedMap.clear();
+        cacheOfImmutableMaps.clear();
+    }
+
+    protected ChainedMap getRootMap() {
+        Object o = hierarchiedMap.get(null, null);
+        if (o == null) {
+            o = new ChainedMap();
+            hierarchiedMap.put(null, null, o);
+        }
+        return (ChainedMap) o;
+    }
+
+    /**
+     * @param service
+     * @return a map containing all the properties for the given service.
+     * @see #getProperties(String, String)
+     */
+    public Map getProperties(String service) {
+        return getProperties(service, null);
+    }
+
+    /**
+     * Return a map containing all the properties for the given port. The map 
is an immutable snapshot of the properties.
+     * Meaning that futur changes to the properties will NOT be reflected in 
the returned map.
+     *
+     * @param service
+     * @param port
+     * @return a map containing all the properties for the given port
+     */
+    public Map getProperties(String service, String port) {
+        // no need to go further if no properties
+        if (hierarchiedMap.isEmpty()) return Collections.EMPTY_MAP;
+
+        // else check the cache of ChainedMap already converted into immutable 
maps
+        Map cachedMap = (Map) this.cacheOfImmutableMaps.get(service, port);
+        if (cachedMap != null) {
+            return cachedMap;
+        }
+
+        // else get the corresponding ChainedMap and convert it into a Map
+        ChainedMap cm = (ChainedMap) hierarchiedMap.get(service, port);
+        // if this port is not explicitly mentioned in the multimap, get the 
default values.
+        if (cm == null) {
+            cm = (ChainedMap) hierarchiedMap.get(service, null);
+            if (cm == null) {
+                // return the cached version of the root map
+                return getProperties(null, null);
+            }
+        }
+        Map snapshotMap = new HashMap(cm.size() * 15 / 10);
+        for (Object key : cm.keySet()) {
+            snapshotMap.put(key, cm.get(key));
+        }
+        snapshotMap = Collections.unmodifiableMap(snapshotMap);
+        // put it in cache to avoid creating one map at each invocation
+        this.cacheOfImmutableMaps.put(service, port, snapshotMap);
+        return snapshotMap;
+    }
+
+    public String getProperty(String property) {
+        return (String) getRootMap().get(property);
+    }
+
+    public String getProperty(String service, String property) {
+        return getProperty(service, null, property);
+    }
+
+    public String getProperty(String service, String port, String property) {
+        ChainedMap cm = (ChainedMap) hierarchiedMap.get(service, port);
+        // if this port is not explicitly mentioned in the multimap, get the 
default values.
+        if (cm == null) cm = getRootMap();
+        return (String) cm.get(property);
+    }
+
+    public String getPrefix() {
+        return prefix;
+    }
+
+    public void setPrefix(String prefix) {
+        this.prefix = prefix;
+    }
+
+    private String[] parseProperty(String property) {
+        // service, port, targeted property
+        String[] res = new String[3];
+
+        int index = property.indexOf(prefix);
+        if (index <= 0) {
+            // assume there is no service/port prefixed, no need to go further
+            res[2] = property;
+        } else {
+            res[2] = property.substring(index + prefix.length()); // targeted 
property
+            String prefix = property.substring(0, index);
+            String[] t = prefix.split("\\.");
+            if (t.length > 2) {
+                throw new IllegalArgumentException("'.' cannot be mentioned 
more than twice in the before the property prefix");
+            }
+            if (t.length >= 1) {
+                res[0] = t[0]; // service name
+            }
+            if (t.length > 1) {
+                res[1] = t[1]; // port name
+            }
+        }
+        return res;
+    }
+
+    /**
+     * Link two Maps instances in a parent-child relation. Meaning that if a 
key is looked up but not found on the child,
+     * then the key will be looked up on the parent map.
+     * <br/>The raison d'etre of this class is to the [EMAIL PROTECTED] 
#keySet()} method. This methods returns a set of <strong>all</strong> the keys 
contained in the child and the parent.
+     * That's the main reason to not used the [EMAIL PROTECTED] 
java.util.Properties} class (which offers access to child keys only).
+     * <p/>The child has an immutable view of the parent map. Methods [EMAIL 
PROTECTED] #clear()} and [EMAIL PROTECTED] #remove(Object)}
+     * throw [EMAIL PROTECTED] UnsupportedOperationException}. Methods [EMAIL 
PROTECTED] #put(Object, Object)} and  [EMAIL PROTECTED] #putAll(java.util.Map)} 
impacts only the child map.
+     * <br/>Methods  [EMAIL PROTECTED] #clearLocally(Object)}
+     * <p/>
+     * This class does NOT implement the [EMAIL PROTECTED] java.util.Map} 
interface because methods [EMAIL PROTECTED] java.util.Map#entrySet()} },
+     * [EMAIL PROTECTED] java.util.Map#values()} and [EMAIL PROTECTED] 
java.util.Map#keySet()} would NOT be backed by the Map itself.
+     * <br/> Contributions welcome to implement that part.
+     *
+     * @author <a href="mailto:[EMAIL PROTECTED]">Alexis Midon</a>
+     */
+    private static class ChainedMap {
+
+        private ChainedMap parent;
+        private Map child;
+
+        public ChainedMap() {
+            parent = null;
+            child = new HashMap();
+        }
+
+        public ChainedMap(ChainedMap parent) {
+            this.parent = parent;
+            this.child = new HashMap();
+        }
+
+        public ChainedMap getParent() {
+            return parent;
+        }
+
+        public void setParent(ChainedMap parent) {
+            this.parent = parent;
+        }
+
+        /**
+         * Perfom a look up on the child map only.
+         */
+        public Object getLocally(Object key) {
+            return child.get(key);
+        }
+
+        /**
+         * Clear the child map only, the parent map is not altered.
+         */
+        public void clearLocally() {
+            child.clear();
+        }
+
+        /**
+         * Perform a look up for the given key on the child map, and if not 
found then perform the look up on the parent map.
+         *
+         * @param key
+         * @return
+         */
+        public Object get(Object key) {
+            Object lv = getLocally(key);
+            if (lv != null) return lv;
+            else if (parent != null) return parent.get(key);
+            return null;
+        }
+
+        /**
+         * Put this pair in the child map.
+         */
+        public Object put(Object key, Object value) {
+            if (key == null) throw new NullPointerException("Null keys 
forbidden!");
+            return child.put(key, value);
+        }
+
+
+        /**
+         * Put these pairs in the child map.
+         */
+        public void putAll(Map t) {
+            for (Object e : t.entrySet()) {
+                put(((Map.Entry) e).getKey(), ((Map.Entry) e).getValue());
+            }
+        }
+
+        /**
+         * @throws UnsupportedOperationException
+         * @see #clearLocally()
+         */
+        public void clear() {
+            throw new UnsupportedOperationException();
+        }
+
+        /**
+         * @throws UnsupportedOperationException
+         */
+        public Object remove(Object key) {
+            throw new UnsupportedOperationException();
+        }
+
+        /**
+         * @return true if the child map is empty AND the parent map is null 
or empty as well.
+         *         <pre>child.isEmpty() && (parent == null || 
parent.isEmpty());</pre>
+         */
+        public boolean isEmpty() {
+            return child.isEmpty() && (parent == null || parent.isEmpty());
+        }
+
+        /**
+         * @return true if the child map contains this key OR the parent map 
is not null and contains this key.
+         *         <pre>child.containsKey(key) || (parent != null && 
parent.containsKey(key));</pre>
+         */
+        public boolean containsKey(Object key) {
+            if (key == null) throw new NullPointerException("Null keys 
forbidden!");
+            return child.containsKey(key) || (parent != null && 
parent.containsKey(key));
+        }
+
+        /**
+         * @return true if the child map contains this value OR the parent is 
not null
+         *         <pre>child.containsValue(value) || (parent != null && 
parent.containsValue(value));</pre>
+         */
+        public boolean containsValue(Object value) {
+            return child.containsValue(value) || (parent != null && 
parent.containsValue(value));
+        }
+
+        public int size() {
+            return keySet().size();
+        }
+
+        /**
+         * @return a new set instance merging all keys contained in the child 
and parent maps. <strong>The returned set is not backed by the maps.</strong>
+         *         Any references to the returned sets are hold at the 
holder's own risks. This breaks the general [EMAIL PROTECTED] 
java.util.Map#entrySet()} contract.
+         */
+        public Set keySet() {
+            HashSet s = new HashSet(child.keySet());
+            if (parent != null) s.addAll(parent.keySet());
+            return s;
+        }
+    }
+}

Modified: ode/trunk/utils/src/main/java/org/apache/ode/utils/ObjectPrinter.java
URL: 
http://svn.apache.org/viewvc/ode/trunk/utils/src/main/java/org/apache/ode/utils/ObjectPrinter.java?rev=663741&r1=663740&r2=663741&view=diff
==============================================================================
--- ode/trunk/utils/src/main/java/org/apache/ode/utils/ObjectPrinter.java 
(original)
+++ ode/trunk/utils/src/main/java/org/apache/ode/utils/ObjectPrinter.java Thu 
Jun  5 14:14:08 2008
@@ -69,7 +69,7 @@
 //             NOTE: this causes blowups since array may be array of primitive 
type
 //                               which cannot be cast to 'Object[]'
 //      else if (objects[i].getClass().isArray()){
-//        buf.append(ArrayUtils.makeCollection(ArrayList.class, (Object[]) 
objects[i]));
+//        buf.append(CollectionUtils.makeCollection(ArrayList.class, 
(Object[]) objects[i]));
       else
         buf.append(objects[i]);
 

Added: ode/trunk/utils/src/main/java/org/apache/ode/utils/WatchDog.java
URL: 
http://svn.apache.org/viewvc/ode/trunk/utils/src/main/java/org/apache/ode/utils/WatchDog.java?rev=663741&view=auto
==============================================================================
--- ode/trunk/utils/src/main/java/org/apache/ode/utils/WatchDog.java (added)
+++ ode/trunk/utils/src/main/java/org/apache/ode/utils/WatchDog.java Thu Jun  5 
14:14:08 2008
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ode.utils;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * This class is based on [EMAIL PROTECTED] 
org.apache.log4j.helpers.FileWatchdog}.<p/>
+ * Modifications have been made to support additional abstract ressource and 
more events (creation, deletion and updates), and to allow "manual"
+ * invocations of [EMAIL PROTECTED] #check()} (i.e wihtout having to use a 
thread) while preserving time checking.<p/>
+ * Now two use cases coexist:
+ * <ol>
+ * <li>Pass an instance of [EMAIL PROTECTED] WatchDog} to a new thread ([EMAIL 
PROTECTED] WatchDog} is a [EMAIL PROTECTED] Runnable}).
+ * So that [EMAIL PROTECTED] WatchDog# check ()} will be called automatically 
every [EMAIL PROTECTED] delay} milliseconds.</li>
+ * <li>Invoke [EMAIL PROTECTED] WatchDog# check ()} only when you feel like 
it. If the expiration date previously set is lower than NOW then event
+ * callback methods will be invoked accordingly.</li>
+ * </ol>
+ *
+ * @author <a href="mailto:[EMAIL PROTECTED]">Alexis Midon</a>
+ */
+public class WatchDog<T> implements Runnable {
+    static final public long DEFAULT_DELAY = 30000;
+    final Log log = LogFactory.getLog(getClass());
+
+    private long expire;
+    private T lastModif;
+    private long delay;
+    private boolean existedBefore, warnedAlready, interrupted;
+    protected final Mutable<T> mutable;
+
+    /**
+     * @param mutable the object to watch closely
+     * @param delay   between two checks
+     */
+    public WatchDog(Mutable<T> mutable, long delay) {
+        this(mutable);
+        this.delay = delay;
+    }
+
+    /**
+     * @see #WatchDog(org.apache.ode.utils.WatchDog.Mutable, long)
+     */
+    public WatchDog(Mutable<T> mutable) {
+        this.mutable = mutable;
+        this.delay = DEFAULT_DELAY;
+    }
+
+    protected boolean isInitialized() {
+        return true;
+    }
+
+    /**
+     * Called by [EMAIL PROTECTED] #check()} if the object is not [EMAIL 
PROTECTED] #isInitialized initialized} and the [EMAIL PROTECTED] 
WatchDog.Mutable#exists()}  resource does not exist}.
+     * <br/> This method might called to reset the object.
+     *
+     * @throws Exception
+     */
+    protected void init() {
+    }
+
+    /**
+     * Called only if the resource previously existed and now does not exist.
+     * <br/>The default implementation invokes [EMAIL PROTECTED] #init()} .
+     *
+     * @throws Exception
+     */
+    protected void doOnDelete() {
+        init();
+    }
+
+    /**
+     * Called only if the resource previously existed but the [EMAIL 
PROTECTED] WatchDog.Mutable#lastModified()} timestamp has changed (greater than 
the previous value).
+     * <br/>The default implementation invokes [EMAIL PROTECTED] #init()} .
+     *
+     * @throws Exception
+     */
+    protected void doOnUpdate() {
+        init();
+    }
+
+    public long getDelay() {
+        return delay;
+    }
+
+    public void setDelay(long delay) {
+        this.delay = delay;
+    }
+
+    public void run() {
+        try {
+            while (!interrupted) {
+                try {
+                    Thread.sleep(delay);
+                } catch (InterruptedException e) {
+                    // no interruption expected
+                }
+                check();
+            }
+        } catch (Exception e) {
+            log.warn("Exception occured. Thread will stop", e);
+        }
+    }
+
+    public final void check() {
+        long now = System.currentTimeMillis();
+        if (expire <= now) {
+            expire = now + delay;
+
+            if (mutable.exists()) {
+                existedBefore = true;
+                if (lastModif==null || mutable.hasChangedSince(lastModif)) {
+                    lastModif = mutable.lastModified();
+                    if (log.isDebugEnabled())
+                        log.debug(mutable + " has been modified");
+                    doOnUpdate();
+                    warnedAlready = false;
+                }
+            } else if (!isInitialized()) {
+                // no resource and first time
+                init();
+            } else {
+                if (existedBefore) {
+                    existedBefore = false;
+                    lastModif = null;
+                    doOnDelete();
+                }
+                if (!warnedAlready) {
+                    warnedAlready = true;
+                    if (log.isDebugEnabled()) log.debug(mutable + "] does not 
exist.");
+                }
+            }
+        }
+    }
+
+    /**
+     * have you said that duck typing would be nice?
+     */
+    public interface Mutable<T> {
+        boolean exists();
+
+        boolean hasChangedSince(T since);
+
+        T lastModified();
+    }
+
+}

Modified: 
ode/trunk/utils/src/main/java/org/apache/ode/utils/fs/FileWatchDog.java
URL: 
http://svn.apache.org/viewvc/ode/trunk/utils/src/main/java/org/apache/ode/utils/fs/FileWatchDog.java?rev=663741&r1=663740&r2=663741&view=diff
==============================================================================
--- ode/trunk/utils/src/main/java/org/apache/ode/utils/fs/FileWatchDog.java 
(original)
+++ ode/trunk/utils/src/main/java/org/apache/ode/utils/fs/FileWatchDog.java Thu 
Jun  5 14:14:08 2008
@@ -19,121 +19,40 @@
 
 package org.apache.ode.utils.fs;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.apache.ode.utils.WatchDog;
 
 import java.io.File;
 
-/**
- * This class is based on [EMAIL PROTECTED] 
org.apache.log4j.helpers.FileWatchdog}.<p/>
- * Modifications have been made to support additional file events (creation, 
deletion and updates), and to allow "manual"
- * invocations of [EMAIL PROTECTED] #checkAndConfigure()} (i.e wihtout having 
to use a thread) while preserving time checking.<p/>
- * Now two use cases coexist:
- * <ol>
- * <li>Pass an instance of [EMAIL PROTECTED] FileWatchDog} to a new thread 
([EMAIL PROTECTED] FileWatchDog} is a [EMAIL PROTECTED] Runnable}).
- *  So that [EMAIL PROTECTED] FileWatchDog#checkAndConfigure()} will be called 
automatically every [EMAIL PROTECTED] delay} milliseconds.</li>
- * <li>Invoke [EMAIL PROTECTED] FileWatchDog#checkAndConfigure()} only when 
you feel like it. If the expiration date previously set is lower than NOW then 
event
- * callback methods will be invoked accordingly.</li>
- * </ol>
- *
- * @author Ceki G&uuml;lc&uuml;
- * @author <a href="mailto:[EMAIL PROTECTED]">Alexis Midon</a>
- */
-public class FileWatchDog implements Runnable {
-    static final public long DEFAULT_DELAY = 60000;
-    private final Log log;
-
-    long expire;
-    long lastModif;
-    long delay = DEFAULT_DELAY;
-    boolean fileExistedBefore, warnedAlready, interrupted;
-    protected final File file;
+public class FileWatchDog extends WatchDog<Long> {
 
-    protected FileWatchDog(File file, long delay) {
-        this(file);
-        this.delay = delay;
-    }
+    protected final File file;
 
-    protected FileWatchDog(File file) {
+    public FileWatchDog(File file, long delay) {
+        super(new FileDecorator(file),delay);
         this.file = file;
-        log = LogFactory.getLog(FileWatchDog.class);
-    }
-
-    protected boolean isInitialized() throws Exception {
-        return true;
-    }
-
-    protected void init() throws Exception {
     }
 
-    protected void doOnDelete() throws Exception {
-        init();
+    public FileWatchDog(File file) {
+        this(file, WatchDog.DEFAULT_DELAY);
     }
 
-    protected void doOnUpdate() throws Exception {
-        init();
-    }
-
-    public long getDelay() {
-        return delay;
-    }
+    static class FileDecorator implements WatchDog.Mutable<Long>{
+        File file;
 
-    public void setDelay(long delay) {
-        this.delay = delay;
-    }
+        FileDecorator(File file) {
+            this.file = file;
+        }
 
-    public void run() {
-        try {
-            while (!interrupted) {
-                try {
-                    Thread.currentThread().sleep(delay);
-                } catch (InterruptedException e) {
-                    // no interruption expected
-                }
-                checkAndConfigure();
-            }
-        } catch (Exception e) {
-            log.warn("Exception occured. Thread will stop", e);
+        public boolean exists() {
+            return file.exists();
         }
-    }
 
+        public boolean hasChangedSince(Long since) {
+            return lastModified().longValue()>since.longValue();
+        }
 
-    public final void checkAndConfigure() throws Exception {
-        long now = System.currentTimeMillis();
-        if (expire <= now) {
-            expire = now + delay;
-            boolean fileExists;
-            try {
-                fileExists = file.exists();
-            } catch (SecurityException e) {
-                log.warn("Was not allowed to read check file existance, 
file:[" + file.getPath() + "].");
-                interrupted = true; // there is no point in continuing 
-                return;
-            }
-
-            if (fileExists) {
-                fileExistedBefore = true;
-                long l = file.lastModified();
-                if (l > lastModif) {
-                    lastModif = l;
-                    if (log.isDebugEnabled())
-                        log.debug("File [" + file + "] has been modified");
-                    doOnUpdate();
-                    warnedAlready = false;
-                }
-            } else if (!isInitialized()) {
-                // first time and no file
-                init();
-            } else {
-                if (fileExistedBefore) {
-                    fileExistedBefore = false;
-                    doOnDelete();
-                }
-                if (!warnedAlready) {
-                    warnedAlready = true;
-                    if (log.isDebugEnabled()) log.debug("[" + file + "] does 
not exist.");
-                }
-            }
+        public Long lastModified() {
+            return Long.valueOf(file.lastModified());
         }
     }
 

Added: 
ode/trunk/utils/src/test/java/org/apache/ode/utils/HierarchiedPropertiesTest.java
URL: 
http://svn.apache.org/viewvc/ode/trunk/utils/src/test/java/org/apache/ode/utils/HierarchiedPropertiesTest.java?rev=663741&view=auto
==============================================================================
--- 
ode/trunk/utils/src/test/java/org/apache/ode/utils/HierarchiedPropertiesTest.java
 (added)
+++ 
ode/trunk/utils/src/test/java/org/apache/ode/utils/HierarchiedPropertiesTest.java
 Thu Jun  5 14:14:08 2008
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ode.utils;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Map;
+import java.util.List;
+import java.util.Arrays;
+
+/**
+ * @author <a href="mailto:[EMAIL PROTECTED]">Alexis Midon</a>
+ */
+public class HierarchiedPropertiesTest extends TestCase {
+    protected HierarchiedProperties hp;
+
+    protected void setUp() throws Exception {
+        File file = new 
File(getClass().getResource("/hierarchied.properties").toURI());
+        hp = new HierarchiedProperties(file);
+    }
+
+    public void testGetProperty() {
+        String msg = "Returned value does not match expected value for this 
property!";
+        assertEquals(msg, hp.getProperty("max-redirects"), "30");
+        assertEquals(msg, hp.getProperty("brel-service", "max-redirects"), 
"40");
+        assertEquals(msg, hp.getProperty("brel-service", "port-of-amsterdam", 
"max-redirects"), "60");
+        assertEquals(msg, hp.getProperty("film-service", "timeout"), "40000");
+        assertEquals(msg, hp.getProperty("film-service", "port-of-cannes", 
"timeout"), "50000");
+        assertEquals(msg, hp.getProperty("brel-service", "port-of-amsterdam", 
"timeout"), "40000");
+        assertEquals(msg, 
hp.getProperty("ode.a.property.beginning.with.the.prefix.but.no.service"), "so 
green or red?");
+    }
+
+    public void testGetProperties(){
+        final List keys = Arrays.asList("timeout", "max-redirects", 
"ode.a.property.beginning.with.the.prefix.but.no.service");
+        Map map = hp.getProperties("film-service");
+        assertEquals("Number of properties is wrong",keys.size(), map.size());
+        assertEquals("40000", map.get("timeout"));
+        assertEquals("30", map.get("max-redirects"));
+        assertEquals("so green or red?", 
map.get("ode.a.property.beginning.with.the.prefix.but.no.service"));
+    }
+
+
+    public void testCachedGetProperties(){
+        assertSame("Snapshot maps should be cached!", 
hp.getProperties("film-service"), hp.getProperties("film-service"));
+        assertSame("Snapshot maps should be cached!", 
hp.getProperties("film-service", "port-of-cannes"), 
hp.getProperties("film-service", "port-of-cannes"));
+        assertSame("Snapshot maps should be cached!", 
hp.getProperties("unknown-service"), hp.getProperties("unknown-service"));
+    }
+
+    public void testWithNoFile() throws IOException {
+        File file = new File("/a-file-that-does-not-exist");
+        Map m = new HierarchiedProperties(file).getProperties("a-service", 
"a-port");
+        assertEquals("Should be empty", 0, m.size());
+    }
+
+}

Modified: 
ode/trunk/utils/src/test/java/org/apache/ode/utils/wsdl/WsdlUtilsTest.java
URL: 
http://svn.apache.org/viewvc/ode/trunk/utils/src/test/java/org/apache/ode/utils/wsdl/WsdlUtilsTest.java?rev=663741&r1=663740&r2=663741&view=diff
==============================================================================
--- ode/trunk/utils/src/test/java/org/apache/ode/utils/wsdl/WsdlUtilsTest.java 
(original)
+++ ode/trunk/utils/src/test/java/org/apache/ode/utils/wsdl/WsdlUtilsTest.java 
Thu Jun  5 14:14:08 2008
@@ -42,7 +42,7 @@
 public class WsdlUtilsTest extends TestCase {
     private Definition definition;
     private Service dummyService;
-    
+
     protected void setUp() throws Exception {
         super.setUp();
 
@@ -178,8 +178,8 @@
             Map.Entry e = (Map.Entry) it.next();
             Port port = (Port) e.getValue();
 
-            if("DummyService_port_with_empty_binding".equals(port.getName())
-                    || 
"DummyService_port_with_no_binding".equals(port.getName())){
+            if ("DummyService_port_with_empty_binding".equals(port.getName())
+                    || 
"DummyService_port_with_no_binding".equals(port.getName())) {
                 continue;
             }
 

Added: ode/trunk/utils/src/test/resources/hierarchied.properties
URL: 
http://svn.apache.org/viewvc/ode/trunk/utils/src/test/resources/hierarchied.properties?rev=663741&view=auto
==============================================================================
--- ode/trunk/utils/src/test/resources/hierarchied.properties (added)
+++ ode/trunk/utils/src/test/resources/hierarchied.properties Thu Jun  5 
14:14:08 2008
@@ -0,0 +1,10 @@
+
+
+timeout=40000
+max-redirects=30
+
+film-service.port-of-cannes.ode.timeout=50000
+brel-service.ode.max-redirects=40
+brel-service.port-of-amsterdam.ode.max-redirects=60
+ode.a.property.beginning.with.the.prefix.but.no.service=so green or red?
+


Reply via email to