You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ja...@apache.org on 2013/10/10 16:11:14 UTC

svn commit: r1530984 [2/5] - in /ace/trunk: org.apache.ace.agent.itest/ org.apache.ace.agent.itest/src/org/apache/ace/agent/itest/ org.apache.ace.agent.update.itest/ org.apache.ace.agent.update.itest/conf/ org.apache.ace.agent.update.itest/src/org/apac...

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ChangeNotifierManager.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ChangeNotifierManager.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ChangeNotifierManager.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ChangeNotifierManager.java Thu Oct 10 14:11:13 2013
@@ -18,23 +18,41 @@
  */
 package org.apache.ace.client.repository.impl;
 
+import org.apache.ace.client.repository.RepositoryObject;
 import org.osgi.service.event.Event;
 import org.osgi.service.event.EventAdmin;
 
 /**
- * ChangeNotifierManager handles a number of ChangeNotifiers, so there is only
- * one dependency on EventAdmin; this manager directs all calls from the ChangeNotifiers
- * to the 'real' EventAdmin.
+ * ChangeNotifierManager handles a number of ChangeNotifiers, so there is only one dependency on EventAdmin; this
+ * manager directs all calls from the ChangeNotifiers to the 'real' EventAdmin.
  */
 public class ChangeNotifierManager implements EventAdmin {
-
     private volatile EventAdmin m_eventAdmin; /* Will be injected by dependency manager */
 
     /**
      * Creates and configures a ChangeNotifier for use with the given topics.
-     * @param privateTopicRoot The root of all private topics; see TopicRoot in the description of {@link ChangeNotifierImpl}.
-     * @param publicTopicRoot The root of all public topics; see TopicRoot in the description of {@link ChangeNotifierImpl}.
-     * @param entityRoot A class-specific root for the class which will use this ChangeNotifierImpl.
+     * 
+     * @param privateTopicRoot
+     *            The root of all private topics; see TopicRoot in the description of {@link ChangeNotifierImpl}.
+     * @param publicTopicRoot
+     *            The root of all public topics; see TopicRoot in the description of {@link ChangeNotifierImpl}.
+     * @param entityRoot
+     *            A class-specific root for the class which will use this ChangeNotifierImpl.
+     * @return The newly configured ChangeNotifier.
+     */
+    public ChangeNotifier getConfiguredNotifier(String entityRoot, String sessionID) {
+        return new ChangeNotifierImpl(this, RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, entityRoot, sessionID);
+    }
+
+    /**
+     * Creates and configures a ChangeNotifier for use with the given topics.
+     * 
+     * @param privateTopicRoot
+     *            The root of all private topics; see TopicRoot in the description of {@link ChangeNotifierImpl}.
+     * @param publicTopicRoot
+     *            The root of all public topics; see TopicRoot in the description of {@link ChangeNotifierImpl}.
+     * @param entityRoot
+     *            A class-specific root for the class which will use this ChangeNotifierImpl.
      * @return The newly configured ChangeNotifier.
      */
     public ChangeNotifier getConfiguredNotifier(String privateTopicRoot, String publicTopicRoot, String entityRoot, String sessionID) {

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentArtifactImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentArtifactImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentArtifactImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentArtifactImpl.java Thu Oct 10 14:11:13 2013
@@ -160,9 +160,7 @@ public class DeploymentArtifactImpl impl
     @Override
     public int hashCode() {
         int result = getUrl().hashCode();
-        //
         result ^= (int) (m_size ^ (m_size >>> 32));
-        ;
 
         for (String key : m_directives.keySet()) {
             result ^= getDirective(key).hashCode();
@@ -184,5 +182,4 @@ public class DeploymentArtifactImpl impl
 
         return result.toString();
     }
-
 }

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentVersionObjectImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentVersionObjectImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentVersionObjectImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentVersionObjectImpl.java Thu Oct 10 14:11:13 2013
@@ -29,40 +29,77 @@ import com.thoughtworks.xstream.io.Hiera
 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
 
 /**
- * Implementation class for the DeploymentVersionObject. For 'what it does', see DeploymentVersionObject,
- * for 'how it works', see RepositoryObjectImpl.
+ * Implementation class for the DeploymentVersionObject. For 'what it does', see DeploymentVersionObject, for 'how it
+ * works', see RepositoryObjectImpl.
  */
 public class DeploymentVersionObjectImpl extends RepositoryObjectImpl<DeploymentVersionObject> implements DeploymentVersionObject {
+    private static final String[] DEFINING_KEYS = new String[] { KEY_TARGETID, KEY_VERSION };
+
     private final static String XML_NODE = "deploymentversion";
     private final static String ARTIFACTS_XML_NODE = "artifacts";
-    private DeploymentArtifact[] m_deploymentArtifacts;
+
+    private volatile DeploymentArtifact[] m_deploymentArtifacts;
+
+    DeploymentVersionObjectImpl(HierarchicalStreamReader reader, ChangeNotifier notifier) {
+        super(reader, notifier, XML_NODE);
+    }
 
     /**
      * Creates a new <code>DeploymentVersionObjectImpl</code>.
-     * @param attributes A map of attributes; must include <code>KEY_TARGETID</code>, <code>KEY_VERSION</code>.
-     * @param deploymentArtifacts A (possibly empty) array of DeploymentArtifacts.
-     * @param notifier A change notifier to be used by this object.
+     * 
+     * @param attributes
+     *            A map of attributes; must include <code>KEY_TARGETID</code>, <code>KEY_VERSION</code>.
+     * @param deploymentArtifacts
+     *            A (possibly empty) array of DeploymentArtifacts.
+     * @param notifier
+     *            A change notifier to be used by this object.
      */
     DeploymentVersionObjectImpl(Map<String, String> attributes, ChangeNotifier notifier) {
-        super(checkAttributes(attributes, new String[] {KEY_TARGETID, KEY_VERSION}, new boolean[] {false, false}), notifier, XML_NODE);
+        super(checkAttributes(attributes, DEFINING_KEYS, new boolean[] { false, false }), notifier, XML_NODE);
     }
 
     DeploymentVersionObjectImpl(Map<String, String> attributes, Map<String, String> tags, ChangeNotifier notifier) {
-        super(checkAttributes(attributes, new String[] {KEY_TARGETID, KEY_VERSION}, new boolean[] {false, false}), tags, notifier, XML_NODE);
+        super(checkAttributes(attributes, DEFINING_KEYS, new boolean[] { false, false }), tags, notifier, XML_NODE);
     }
 
-    DeploymentVersionObjectImpl(HierarchicalStreamReader reader, ChangeNotifier notifier) {
-        super(reader, notifier, XML_NODE);
+    public DeploymentArtifact[] getDeploymentArtifacts() {
+        DeploymentArtifact[] artifacts;
+        synchronized (this) {
+            artifacts = m_deploymentArtifacts;
+        }
+        if (artifacts == null) {
+            throw new IllegalStateException("This object is not fully initialized yet.");
+        }
+        return artifacts.clone();
     }
 
-    synchronized void setDeploymentArtifacts(DeploymentArtifact[] deploymentArtifacts) {
-        if (m_deploymentArtifacts != null) {
-            throw new IllegalStateException("Deployment artifacts are already set; this can only be done once.");
-        }
+    public String getTargetID() {
+        return getAttribute(KEY_TARGETID);
+    }
+
+    public String getVersion() {
+        return getAttribute(KEY_VERSION);
+    }
+
+    @Override
+    public String toString() {
+        return "DeploymentVersionObject[target=" + getTargetID() + ",version=" + getVersion() + "]";
+    }
+
+    @Override
+    String[] getDefiningKeys() {
+        return DEFINING_KEYS;
+    }
+
+    void setDeploymentArtifacts(DeploymentArtifact[] deploymentArtifacts) {
         if (deploymentArtifacts == null) {
             throw new IllegalArgumentException("The argument should not be null.");
         }
-        else {
+        synchronized (this) {
+            DeploymentArtifact[] old = m_deploymentArtifacts;
+            if (old != null) {
+                throw new IllegalStateException("Deployment artifacts are already set; this can only be done once.");
+            }
             m_deploymentArtifacts = deploymentArtifacts;
         }
     }
@@ -82,40 +119,19 @@ public class DeploymentVersionObjectImpl
     }
 
     @Override
-    protected synchronized void writeCustom(HierarchicalStreamWriter writer) {
-        if (m_deploymentArtifacts == null) {
+    protected void writeCustom(HierarchicalStreamWriter writer) {
+        DeploymentArtifact[] artifacts;
+        synchronized (this) {
+            artifacts = m_deploymentArtifacts;
+        }
+
+        if (artifacts == null) {
             throw new IllegalStateException("This object is not fully initialized, so it cannot be serialized.");
         }
         writer.startNode(ARTIFACTS_XML_NODE);
-        for (DeploymentArtifact da : m_deploymentArtifacts) {
+        for (DeploymentArtifact da : artifacts) {
             ((DeploymentArtifactImpl) da).marshal(writer);
         }
         writer.endNode();
     }
-
-    private static String[] DEFINING_KEYS = new String[] {KEY_TARGETID, KEY_VERSION};
-    @Override
-    String[] getDefiningKeys() {
-        return DEFINING_KEYS;
-    }
-
-    public String getTargetID() {
-        return getAttribute(KEY_TARGETID);
-    }
-
-    public String getVersion() {
-        return getAttribute(KEY_VERSION);
-    }
-
-    public synchronized DeploymentArtifact[] getDeploymentArtifacts() {
-        if (m_deploymentArtifacts == null) {
-            throw new IllegalStateException("This object is not fully initialized yet.");
-        }
-        return m_deploymentArtifacts.clone();
-    }
-    @Override
-    public String toString() {
-    	return "DeploymentVersionObject[target=" + getTargetID() + ",version=" + getVersion() + "]";
-    }
 }
-

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentVersionRepositoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentVersionRepositoryImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentVersionRepositoryImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DeploymentVersionRepositoryImpl.java Thu Oct 10 14:11:13 2013
@@ -21,61 +21,46 @@ package org.apache.ace.client.repository
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
 
 import org.apache.ace.client.repository.RepositoryUtil;
 import org.apache.ace.client.repository.object.DeploymentArtifact;
 import org.apache.ace.client.repository.object.DeploymentVersionObject;
 import org.apache.ace.client.repository.repository.DeploymentVersionRepository;
+import org.apache.ace.client.repository.repository.RepositoryConfiguration;
 import org.osgi.framework.InvalidSyntaxException;
 import org.osgi.framework.Version;
 
 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
 
 /**
- * Implementation class for the TargetRepository. For 'what it does', see TargetRepository,
- * for 'how it works', see ObjectRepositoryImpl.
- * TODO: For now, this class reuses the functionality of ObjectRepositoryImpl. In the future, it
+ * Implementation class for the TargetRepository. For 'what it does', see TargetRepository, for 'how it works', see
+ * ObjectRepositoryImpl. TODO: For now, this class reuses the functionality of ObjectRepositoryImpl. In the future, it
  * might be useful to create a custom implementation for performance reasons.
  */
 public class DeploymentVersionRepositoryImpl extends ObjectRepositoryImpl<DeploymentVersionObjectImpl, DeploymentVersionObject> implements DeploymentVersionRepository {
     private final static String XML_NODE = "deploymentversions";
 
-    public DeploymentVersionRepositoryImpl(ChangeNotifier notifier) {
-        super(notifier, XML_NODE);
-    }
-
     /*
-     * The mechanism below allows us to insert the artifacts that are passed to create
-     * into the newInhabitant, while still using the nice handling of ObjectRepositoryImpl.
+     * The mechanism below allows us to insert the artifacts that are passed to create into the newInhabitant, while
+     * still using the nice handling of ObjectRepositoryImpl.
      */
     private DeploymentArtifact[] m_tempDeploymentArtifacts;
-    private final Object m_creationLock = new Object();
 
-    @Override
-    DeploymentVersionObjectImpl createNewInhabitant(Map<String, String> attributes) {
-        synchronized (m_creationLock) {
-            DeploymentVersionObjectImpl result = new DeploymentVersionObjectImpl(attributes, this);
-            result.setDeploymentArtifacts(m_tempDeploymentArtifacts);
-            m_tempDeploymentArtifacts = null;
-            return result;
-        }
-    }
+    private final Object m_creationLock = new Object();
 
-    @Override
-    DeploymentVersionObjectImpl createNewInhabitant(Map<String, String> attributes, Map<String, String> tags) {
-        synchronized (m_creationLock) {
-            DeploymentVersionObjectImpl result = new DeploymentVersionObjectImpl(attributes, tags, this);
-            result.setDeploymentArtifacts(m_tempDeploymentArtifacts);
-            m_tempDeploymentArtifacts = null;
-            return result;
+    private Comparator<DeploymentVersionObject> versionComparator = new Comparator<DeploymentVersionObject>() {
+        public int compare(DeploymentVersionObject o1, DeploymentVersionObject o2) {
+            return Version.parseVersion(o1.getVersion()).compareTo(Version.parseVersion(o2.getVersion()));
         }
-    }
+    };
 
-    @Override
-    DeploymentVersionObjectImpl createNewInhabitant(HierarchicalStreamReader reader) {
-        return new DeploymentVersionObjectImpl(reader, this);
+    public DeploymentVersionRepositoryImpl(ChangeNotifier notifier, RepositoryConfiguration repositoryConfig) {
+        super(notifier, XML_NODE, repositoryConfig);
     }
 
     public DeploymentVersionObject create(Map<String, String> attributes, Map<String, String> tags, DeploymentArtifact[] artifacts) {
@@ -85,22 +70,24 @@ public class DeploymentVersionRepository
         }
     }
 
-    private Comparator<DeploymentVersionObject> versionComparator = new Comparator<DeploymentVersionObject>() {
-        public int compare(DeploymentVersionObject o1, DeploymentVersionObject o2) {
-            return Version.parseVersion(o1.getVersion()).compareTo(Version.parseVersion(o2.getVersion()));
+    public DeploymentArtifact createDeploymentArtifact(String url, long size, Map<String, String> directives) {
+        DeploymentArtifactImpl result = new DeploymentArtifactImpl(url, size);
+        for (Map.Entry<String, String> entry : directives.entrySet()) {
+            result.addDirective(entry.getKey(), entry.getValue());
         }
-    };
+        return result;
+    }
 
     public List<DeploymentVersionObject> getDeploymentVersions(String targetID) {
         List<DeploymentVersionObject> result = null;
-            try {
-                result = get(createFilter("(" + DeploymentVersionObject.KEY_TARGETID + "=" + RepositoryUtil.escapeFilterValue(targetID) + ")"));
-                Collections.sort(result, versionComparator);
-            }
-            catch (InvalidSyntaxException e) {
-                // Too bad, probably an illegal targetID.
-                result = new ArrayList<DeploymentVersionObject>();
-            }
+        try {
+            result = get(createFilter("(" + DeploymentVersionObject.KEY_TARGETID + "=" + RepositoryUtil.escapeFilterValue(targetID) + ")"));
+            Collections.sort(result, versionComparator);
+        }
+        catch (InvalidSyntaxException e) {
+            // Too bad, probably an illegal targetID.
+            result = new ArrayList<DeploymentVersionObject>();
+        }
         return result;
     }
 
@@ -113,11 +100,69 @@ public class DeploymentVersionRepository
         return result;
     }
 
-    public DeploymentArtifact createDeploymentArtifact(String url, long size, Map<String, String> directives) {
-        DeploymentArtifactImpl result =  new DeploymentArtifactImpl(url, size);
-        for (Map.Entry<String, String> entry : directives.entrySet()) {
-            result.addDirective(entry.getKey(), entry.getValue());
+    @Override
+    boolean add(DeploymentVersionObject entity) {
+        boolean result = super.add(entity);
+
+        int deploymentVersionLimit = getDeploymentVersionLimit();
+        if (deploymentVersionLimit > 0) {
+            purgeOldDeploymentVersions(deploymentVersionLimit);
         }
+
         return result;
     }
+
+    @Override
+    DeploymentVersionObjectImpl createNewInhabitant(HierarchicalStreamReader reader) {
+        return new DeploymentVersionObjectImpl(reader, this);
+    }
+
+    @Override
+    DeploymentVersionObjectImpl createNewInhabitant(Map<String, String> attributes, Map<String, String> tags) {
+        synchronized (m_creationLock) {
+            DeploymentVersionObjectImpl result = new DeploymentVersionObjectImpl(attributes, tags, this);
+            result.setDeploymentArtifacts(m_tempDeploymentArtifacts);
+            m_tempDeploymentArtifacts = null;
+            return result;
+        }
+    }
+
+    /**
+     * @return an index of deployment versions (sorted!) per target, never <code>null</code>.
+     */
+    private Map<String, SortedSet<DeploymentVersionObject>> createDeploymentVersionIndex() {
+        Map<String, SortedSet<DeploymentVersionObject>> index = new HashMap<String, SortedSet<DeploymentVersionObject>>();
+        for (DeploymentVersionObject dvo : get()) {
+            SortedSet<DeploymentVersionObject> versions = index.get(dvo.getTargetID());
+            if (versions == null) {
+                // store all DeploymentVersions in ascending order (oldest version first)...
+                versions = new TreeSet<DeploymentVersionObject>(this.versionComparator);
+                index.put(dvo.getTargetID(), versions);
+            }
+            versions.add(dvo);
+        }
+        return index;
+    }
+
+    /**
+     * @return the maximum number of deployment versions to retain per target, or -1 if no limit is imposed.
+     */
+    private int getDeploymentVersionLimit() {
+        return getRepositoryConfiguration().getDeploymentVersionLimit();
+    }
+
+    /**
+     * Purges old deployment versions for each target.
+     */
+    private void purgeOldDeploymentVersions(int deploymentVersionLimit) {
+        Map<String, SortedSet<DeploymentVersionObject>> index = createDeploymentVersionIndex();
+        for (Map.Entry<String, SortedSet<DeploymentVersionObject>> entry : index.entrySet()) {
+            SortedSet<DeploymentVersionObject> versions = entry.getValue();
+            while (versions.size() > deploymentVersionLimit) {
+                DeploymentVersionObject head = versions.first();
+                remove(head);
+                versions.remove(head);
+            }
+        }
+    }
 }

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Distribution2TargetAssociationRepositoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Distribution2TargetAssociationRepositoryImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Distribution2TargetAssociationRepositoryImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Distribution2TargetAssociationRepositoryImpl.java Thu Oct 10 14:11:13 2013
@@ -24,6 +24,7 @@ import org.apache.ace.client.repository.
 import org.apache.ace.client.repository.object.Distribution2TargetAssociation;
 import org.apache.ace.client.repository.object.DistributionObject;
 import org.apache.ace.client.repository.repository.Distribution2TargetAssociationRepository;
+import org.apache.ace.client.repository.repository.RepositoryConfiguration;
 import org.osgi.framework.InvalidSyntaxException;
 
 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
@@ -38,8 +39,8 @@ public class Distribution2TargetAssociat
     private final DistributionRepositoryImpl m_distributionRepository;
     private final TargetRepositoryImpl m_targetRepository;
 
-    public Distribution2TargetAssociationRepositoryImpl(DistributionRepositoryImpl distributionRepository, TargetRepositoryImpl targetRepository, ChangeNotifier notifier) {
-        super(notifier, XML_NODE);
+    public Distribution2TargetAssociationRepositoryImpl(DistributionRepositoryImpl distributionRepository, TargetRepositoryImpl targetRepository, ChangeNotifier notifier, RepositoryConfiguration repoConfig) {
+        super(notifier, XML_NODE, repoConfig);
         m_distributionRepository = distributionRepository;
         m_targetRepository = targetRepository;
     }

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DistributionRepositoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DistributionRepositoryImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DistributionRepositoryImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DistributionRepositoryImpl.java Thu Oct 10 14:11:13 2013
@@ -22,6 +22,7 @@ import java.util.Map;
 
 import org.apache.ace.client.repository.object.DistributionObject;
 import org.apache.ace.client.repository.repository.DistributionRepository;
+import org.apache.ace.client.repository.repository.RepositoryConfiguration;
 
 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
 
@@ -32,8 +33,8 @@ import com.thoughtworks.xstream.io.Hiera
 public class DistributionRepositoryImpl extends ObjectRepositoryImpl<DistributionObjectImpl, DistributionObject> implements DistributionRepository {
     private final static String XML_NODE = "distributions";
 
-    public DistributionRepositoryImpl(ChangeNotifier notifier) {
-        super(notifier, XML_NODE);
+    public DistributionRepositoryImpl(ChangeNotifier notifier, RepositoryConfiguration repoConfig) {
+        super(notifier, XML_NODE, repoConfig);
     }
 
     @Override
@@ -42,11 +43,6 @@ public class DistributionRepositoryImpl 
     }
 
     @Override
-    DistributionObjectImpl createNewInhabitant(Map<String, String> attributes) {
-        return new DistributionObjectImpl(attributes, this);
-    }
-
-    @Override
     DistributionObjectImpl createNewInhabitant(HierarchicalStreamReader reader) {
         return new DistributionObjectImpl(reader, this);
     }

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Feature2DistributionAssociationRepositoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Feature2DistributionAssociationRepositoryImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Feature2DistributionAssociationRepositoryImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Feature2DistributionAssociationRepositoryImpl.java Thu Oct 10 14:11:13 2013
@@ -24,6 +24,7 @@ import org.apache.ace.client.repository.
 import org.apache.ace.client.repository.object.FeatureObject;
 import org.apache.ace.client.repository.object.DistributionObject;
 import org.apache.ace.client.repository.repository.Feature2DistributionAssociationRepository;
+import org.apache.ace.client.repository.repository.RepositoryConfiguration;
 import org.osgi.framework.InvalidSyntaxException;
 
 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
@@ -38,8 +39,8 @@ public class Feature2DistributionAssocia
     private final FeatureRepositoryImpl m_featureRepository;
     private final DistributionRepositoryImpl m_distributionRepository;
 
-    public Feature2DistributionAssociationRepositoryImpl(FeatureRepositoryImpl featureRepository, DistributionRepositoryImpl distributionRepository, ChangeNotifier notifier) {
-        super(notifier, XML_NODE);
+    public Feature2DistributionAssociationRepositoryImpl(FeatureRepositoryImpl featureRepository, DistributionRepositoryImpl distributionRepository, ChangeNotifier notifier, RepositoryConfiguration repoConfig) {
+        super(notifier, XML_NODE, repoConfig);
         m_featureRepository = featureRepository;
         m_distributionRepository = distributionRepository;
     }

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/FeatureRepositoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/FeatureRepositoryImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/FeatureRepositoryImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/FeatureRepositoryImpl.java Thu Oct 10 14:11:13 2013
@@ -22,6 +22,7 @@ import java.util.Map;
 
 import org.apache.ace.client.repository.object.FeatureObject;
 import org.apache.ace.client.repository.repository.FeatureRepository;
+import org.apache.ace.client.repository.repository.RepositoryConfiguration;
 
 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
 
@@ -32,8 +33,8 @@ import com.thoughtworks.xstream.io.Hiera
 public class FeatureRepositoryImpl extends ObjectRepositoryImpl<FeatureObjectImpl, FeatureObject> implements FeatureRepository {
     private final static String XML_NODE = "features";
 
-    public FeatureRepositoryImpl(ChangeNotifier notifier) {
-        super(notifier, XML_NODE);
+    public FeatureRepositoryImpl(ChangeNotifier notifier, RepositoryConfiguration repoConfig) {
+        super(notifier, XML_NODE, repoConfig);
     }
 
     @Override
@@ -42,11 +43,6 @@ public class FeatureRepositoryImpl exten
     }
 
     @Override
-    FeatureObjectImpl createNewInhabitant(Map<String, String> attributes) {
-        return new FeatureObjectImpl(attributes, this);
-    }
-
-    @Override
     FeatureObjectImpl createNewInhabitant(HierarchicalStreamReader reader) {
         return new FeatureObjectImpl(reader, this);
     }

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ObjectRepositoryImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ObjectRepositoryImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ObjectRepositoryImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ObjectRepositoryImpl.java Thu Oct 10 14:11:13 2013
@@ -24,9 +24,13 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
 
 import org.apache.ace.client.repository.ObjectRepository;
 import org.apache.ace.client.repository.RepositoryObject;
+import org.apache.ace.client.repository.repository.RepositoryConfiguration;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Filter;
 import org.osgi.framework.InvalidSyntaxException;
@@ -37,171 +41,203 @@ import com.thoughtworks.xstream.io.Hiera
 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
 
 /**
- * A basic Object Repository, having most of the functionality that the object repositories share.
- * The creation of new inhabitants, and the deserialization of inhabitants is delegated to
- * derived classes.
- *
- * @param <I> An implementation type of the repository object that this repository will store.
- * @param <T> The non-generic interface that <code>I</code> implements.
+ * A basic Object Repository, having most of the functionality that the object repositories share. The creation of new
+ * inhabitants, and the deserialization of inhabitants is delegated to derived classes.
+ * 
+ * @param <I>
+ *            An implementation type of the repository object that this repository will store.
+ * @param <T>
+ *            The non-generic interface that <code>I</code> implements.
  */
 abstract class ObjectRepositoryImpl<I extends RepositoryObjectImpl<T>, T extends RepositoryObject> implements ObjectRepository<T>, EventHandler, ChangeNotifier {
-    protected BundleContext m_context; /* injected by dependency manager */
+    /* injected by dependency manager */
+    protected BundleContext m_context;
+    // for thread-safety
+    protected final ReadWriteLock m_lock = new ReentrantReadWriteLock();
 
     private final List<T> m_repo = new CopyOnWriteArrayList<T>();
     private final Map<String, T> m_index = new ConcurrentHashMap<String, T>();
-    
     private final ChangeNotifier m_notifier;
-
     private final String m_xmlNode;
+    private final RepositoryConfiguration m_repoConfig;
 
     private volatile boolean m_busy = false;
 
     /**
      * The main constructor for this repository.
-     * @param xmlNode The tag that represents this repository (not its objects) in an XML representation.
+     * 
+     * @param xmlNode
+     *            The tag that represents this repository (not its objects) in an XML representation.
      */
-    public ObjectRepositoryImpl(ChangeNotifier notifier, String xmlNode) {
+    public ObjectRepositoryImpl(ChangeNotifier notifier, String xmlNode, RepositoryConfiguration repoConfig) {
         m_notifier = notifier;
         m_xmlNode = xmlNode;
+        m_repoConfig = repoConfig;
     }
 
     /**
-     * Creates a new inhabitant of this repository with the given attributes. The actual creation of the
-     * object is delagated to a derived class; this function will make sure the correct events get fired
-     * and the object gets stored.
+     * Creates a new inhabitant of this repository with the given attributes. The actual creation of the object is
+     * delagated to a derived class; this function will make sure the correct events get fired and the object gets
+     * stored.
      */
     // About this SuppressWarnings: for some reason, the compiler cannot see that I is a proper subtype of T.
     @SuppressWarnings("unchecked")
-    public T create(Map<String, String> attributes, Map <String, String> tags) throws IllegalArgumentException {
+    public T create(Map<String, String> attributes, Map<String, String> tags) throws IllegalArgumentException {
         if (m_busy) {
             throw new IllegalStateException("The repository is currently busy, so no new objects can be created.");
         }
-        T result =  (T) createNewInhabitant(attributes, tags);
+        T result = (T) createNewInhabitant(attributes, tags);
         if (add(result)) {
             return result;
         }
         throw new IllegalArgumentException("Failed to add new object: entity already exists!");
     }
 
-    /**
-     * Helper method that stores an object in the repository, taking care of the right events.
-     * @param entity the object to be stored.
-     * @return true only when the object (or at least one identical to it) did not yet exist in the repository.
-     */
-    boolean add(T entity) {
-        boolean result = false;
+    public List<T> get() {
+        Lock readLock = m_lock.readLock();
+        readLock.lock();
+        try {
+            return new ArrayList<T>(m_repo);
+        }
+        finally {
+            readLock.unlock();
+        }
+    }
 
-        synchronized (m_repo) {
-            if (!m_repo.contains(entity)) {
-                m_repo.add(entity);
-                m_index.put(entity.getDefinition(), entity);
-                result = true;
+    public List<T> get(Filter filter) {
+        Lock readLock = m_lock.readLock();
+        readLock.lock();
+        try {
+            List<T> result = new ArrayList<T>();
+            for (T entry : m_repo) {
+                if (filter.match(entry.getDictionary())) {
+                    result.add(entry);
+                }
             }
+            return result;
         }
-        if (result) {
-            notifyChanged(entity, RepositoryObject.TOPIC_ADDED_SUFFIX);
+        finally {
+            readLock.unlock();
         }
-        return result;
     }
 
-    @SuppressWarnings("unchecked")
-    public void remove(T entity) {
-        if (m_busy) {
-            throw new IllegalStateException("The repository is currently busy, so no objects can be removed.");
+    public T get(String definition) {
+        Lock readLock = m_lock.readLock();
+        readLock.lock();
+        try {
+            return m_index.get(definition);
         }
-        boolean result = false;
-        synchronized (m_repo) {
-            if (m_repo.remove(entity)) {
-                m_index.remove(entity.getDefinition());
-                ((I) entity).setDeleted();
-                result = true;
+        finally {
+            readLock.unlock();
+        }
+    }
+
+    public String getTopicAll(boolean publicTopic) {
+        return m_notifier.getTopicAll(publicTopic);
+    }
+
+    public String getXmlNode() {
+        return m_xmlNode;
+    }
+
+    @SuppressWarnings("unchecked")
+    public void handleEvent(Event e) {
+        Lock readLock = m_lock.readLock();
+        readLock.lock();
+        try {
+            for (T inhabitant : m_repo) {
+                ((I) inhabitant).handleEvent(e);
             }
         }
-        if (result) {
-            notifyChanged(entity, RepositoryObject.TOPIC_REMOVED_SUFFIX);
+        finally {
+            readLock.unlock();
         }
     }
 
     /**
-     * Removes all objects in this repository, without caring for the consistency and
-     * correct event firing.
+     * Writes this repository and its inhabitants to an XML stream. The serialization of the inhabitants will be
+     * delegated to the inhabitants themselves.
+     * 
+     * @param writer
+     *            The writer to write the XML representation to.
      */
     @SuppressWarnings("unchecked")
-    void removeAll() {
-        synchronized (m_repo) {
-            for (T object : m_repo) {
-                ((I) object).setDeleted();
+    public void marshal(HierarchicalStreamWriter writer) {
+        Lock readLock = m_lock.readLock();
+        readLock.lock();
+        try {
+            writer.startNode(m_xmlNode);
+            for (T inhabitant : m_repo) {
+                ((I) inhabitant).marshal(writer);
             }
-            m_repo.clear();
+            writer.endNode();
+        }
+        finally {
+            readLock.unlock();
         }
     }
 
-    /**
-     * Notifies listeners of a change to a given object. It will also notify
-     * listeners of any changes to the status of this repository.
-     * @param entity The object that has changed.
-     * @param topic The topic to use.
-     */
-    private void notifyChanged(T entity, String topic) {
-        Properties props = new Properties();
-        props.put(RepositoryObject.EVENT_ENTITY, entity);
-        notifyChanged(topic, props, m_busy);
+    public void notifyChanged(String topic, Properties props) {
+        notifyChanged(topic, props, false);
     }
 
     public void notifyChanged(String topic, Properties props, boolean internalOnly) {
         m_notifier.notifyChanged(topic, props, internalOnly);
     }
 
-    public void notifyChanged(String topic, Properties props) {
-        notifyChanged(topic, props, false);
-    }
-
-    public String getTopicAll(boolean publicTopic) {
-        return m_notifier.getTopicAll(publicTopic);
-    }
+    @SuppressWarnings("unchecked")
+    public void remove(T entity) {
+        if (m_busy) {
+            throw new IllegalStateException("The repository is currently busy, so no objects can be removed.");
+        }
 
-    public List<T> get() {
-        return new ArrayList<T>(m_repo);
-    }
+        boolean result = false;
 
-    public List<T> get(Filter filter) {
-        List<T> result = new ArrayList<T>();
-        for (T entry : m_repo) {
-            if (filter.match(entry.getDictionary())) {
-                result.add(entry);
+        Lock writeLock = m_lock.writeLock();
+        writeLock.lock();
+        try {
+            if (m_repo.remove(entity)) {
+                m_index.remove(entity.getDefinition());
+                ((I) entity).setDeleted();
+                result = true;
             }
         }
-        return result;
-    }
+        finally {
+            writeLock.unlock();
+        }
 
-    public T get(String definition) {
-    	return m_index.get(definition);
-    }
-    
-    Filter createFilter(String filter) throws InvalidSyntaxException {
-        return m_context.createFilter(filter);
+        if (result) {
+            notifyEntityChanged(entity, RepositoryObject.TOPIC_REMOVED_SUFFIX);
+        }
     }
 
     /**
-     * Writes this repository and its inhabitants to an XML stream. The serialization of
-     * the inhabitants will be delegated to the inhabitants themselves.
-     * @param writer The writer to write the XML representation to.
+     * Sets this repository to busy: this will be delegated to all inhabitants.
      */
-    @SuppressWarnings("unchecked")
-    public void marshal(HierarchicalStreamWriter writer) {
-        writer.startNode(m_xmlNode);
-        for (T inhabitant : m_repo) {
-            ((I) inhabitant).marshal(writer);
+    public void setBusy(boolean busy) {
+        Lock writeLock = m_lock.writeLock();
+        writeLock.lock();
+        try {
+            for (RepositoryObject o : m_repo) {
+                ((RepositoryObjectImpl) o).setBusy(busy);
+            }
+            m_busy = busy;
+        }
+        finally {
+            writeLock.unlock();
         }
-        writer.endNode();
     }
 
     /**
      * Reads the inhabitants of this repository from an XML stream.
-     * @param reader A reader of the XML representation.
+     * 
+     * @param reader
+     *            A reader of the XML representation.
      */
     @SuppressWarnings("unchecked")
     public void unmarshal(HierarchicalStreamReader reader) {
+        Lock writeLock = m_lock.writeLock();
+        writeLock.lock();
         try {
             while (reader.hasMoreChildren()) {
                 reader.moveDown();
@@ -214,49 +250,102 @@ abstract class ObjectRepositoryImpl<I ex
         catch (Exception ex) {
             throw new IllegalArgumentException(ex);
         }
+        finally {
+            writeLock.unlock();
+        }
     }
 
-    @SuppressWarnings("unchecked")
-    public void handleEvent(Event e) {
-        for (T inhabitant : m_repo) {
-            ((I) inhabitant).handleEvent(e);
+    /**
+     * Helper method that stores an object in the repository, taking care of the right events.
+     * 
+     * @param entity
+     *            the object to be stored.
+     * @return true only when the object (or at least one identical to it) did not yet exist in the repository.
+     */
+    boolean add(T entity) {
+        boolean result = false;
+
+        Lock writeLock = m_lock.writeLock();
+        writeLock.lock();
+        try {
+            if (!m_repo.contains(entity)) {
+                m_repo.add(entity);
+                m_index.put(entity.getDefinition(), entity);
+                result = true;
+            }
+        }
+        finally {
+            writeLock.unlock();
+        }
+
+        if (result) {
+            notifyEntityChanged(entity, RepositoryObject.TOPIC_ADDED_SUFFIX);
         }
+
+        return result;
+    }
+
+    Filter createFilter(String filter) throws InvalidSyntaxException {
+        return m_context.createFilter(filter);
     }
 
     /**
-     * Creates a new inhabitant of the repository based on a map of attributes.
-     * @param attributes A map of attributes
-     * @param tags A map of tags
+     * Creates a new inhabitant of the repository based on an XML representation.
+     * 
+     * @param reader
+     *            A reader for the XML representation.
      * @return The new inhabitant.
      */
-    abstract I createNewInhabitant(Map<String, String> attributes, Map<String, String> tags);
+    abstract I createNewInhabitant(HierarchicalStreamReader reader);
+
     /**
      * Creates a new inhabitant of the repository based on a map of attributes.
-     * @param attributes A map of attributes
+     * 
+     * @param attributes
+     *            A map of attributes
+     * @param tags
+     *            A map of tags
      * @return The new inhabitant.
      */
-    abstract I createNewInhabitant(Map<String, String> attributes);
+    abstract I createNewInhabitant(Map<String, String> attributes, Map<String, String> tags);
+
     /**
-     * Creates a new inhabitant of the repository based on an XML representation.
-     * @param reader A reader for the XML representation.
-     * @return The new inhabitant.
+     * Removes all objects in this repository, without caring for the consistency and correct event firing.
      */
-    abstract I createNewInhabitant(HierarchicalStreamReader reader);
+    @SuppressWarnings("unchecked")
+    void removeAll() {
+        Lock writeLock = m_lock.writeLock();
+        writeLock.lock();
+        try {
+            for (T object : m_repo) {
+                ((I) object).setDeleted();
+            }
+            m_repo.clear();
+        }
+        finally {
+            writeLock.unlock();
+        }
+    }
 
-    public String getXmlNode() {
-        return m_xmlNode;
+    /**
+     * @return the repository configuration, never <code>null</code>.s
+     */
+    protected final RepositoryConfiguration getRepositoryConfiguration() {
+        return m_repoConfig;
     }
 
     /**
-     * Sets this repository to busy: this will be delegated to all inhabitants.
+     * Notifies listeners of a change to a given object. It will also notify listeners of any changes to the status of
+     * this repository.
+     * 
+     * @param entity
+     *            The object that has changed.
+     * @param topic
+     *            The topic to use.
      */
-    @SuppressWarnings("unchecked")
-    public void setBusy(boolean busy) {
-        synchronized(m_repo) {
-            m_busy = busy;
-            for (RepositoryObject o : m_repo) {
-                ((I) o).setBusy(busy);
-            }
-        }
+    private void notifyEntityChanged(T entity, String topic) {
+        Properties props = new Properties();
+        props.put(RepositoryObject.EVENT_ENTITY, entity);
+        notifyChanged(topic, props, m_busy);
     }
 }

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminImpl.java Thu Oct 10 14:11:13 2013
@@ -53,6 +53,7 @@ import org.apache.ace.client.repository.
 import org.apache.ace.client.repository.repository.DistributionRepository;
 import org.apache.ace.client.repository.repository.Feature2DistributionAssociationRepository;
 import org.apache.ace.client.repository.repository.FeatureRepository;
+import org.apache.ace.client.repository.repository.RepositoryConfiguration;
 import org.apache.ace.client.repository.repository.TargetRepository;
 import org.apache.ace.connectionfactory.ConnectionFactory;
 import org.apache.ace.repository.Repository;
@@ -73,11 +74,10 @@ import org.osgi.service.prefs.Preference
 import org.osgi.service.useradmin.User;
 
 /**
- * An implementation of RepositoryAdmin, responsible for managing <code>ObjectRepositoryImpl</code>
- * descendants.<br>
- * The actual repository managing is delegated to <code>RepositorySet</code>s, while the logic
- * for binding these sets together is located in this class. Set actual <code>RepositorySet</code>s
- * to be used are defined in <code>login(...)</code>.<br>
+ * An implementation of RepositoryAdmin, responsible for managing <code>ObjectRepositoryImpl</code> descendants.<br>
+ * The actual repository managing is delegated to <code>RepositorySet</code>s, while the logic for binding these sets
+ * together is located in this class. Set actual <code>RepositorySet</code>s to be used are defined in
+ * <code>login(...)</code>.<br>
  */
 public class RepositoryAdminImpl implements RepositoryAdmin {
     private final static String PREFS_LOCAL_FILE_ROOT = "ClientRepositoryAdmin";
@@ -88,23 +88,22 @@ public class RepositoryAdminImpl impleme
     /**
      * Maps from interface classes of the ObjectRepositories to their implementations.
      */
-    @SuppressWarnings("unchecked")
     private Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> m_repositories;
 
     private final String m_sessionID;
     private final Properties m_sessionProps;
+    private final RepositoryConfiguration m_repositoryConfig;
     private final ChangeNotifier m_changeNotifier;
     private final Object m_lock = new Object();
 
     // Injected by dependency manager
-    private volatile DependencyManager m_manager;
-    private volatile BundleContext m_context; 
+    private volatile DependencyManager m_dm;
+    private volatile BundleContext m_context;
     private volatile PreferencesService m_preferences;
     private volatile LogService m_log;
 
     private User m_user;
     private RepositorySet[] m_repositorySets;
-    
     private List<PreCommitMember> m_preCommitMembers;
 
     private List<Component[]> m_services;
@@ -118,9 +117,9 @@ public class RepositoryAdminImpl impleme
     private DeploymentVersionRepositoryImpl m_deploymentVersionRepositoryImpl;
     private ChangeNotifierManager m_changeNotifierManager;
 
-
-    public RepositoryAdminImpl(String sessionID) {
+    public RepositoryAdminImpl(String sessionID, RepositoryConfiguration repoConfig) {
         m_sessionID = sessionID;
+        m_repositoryConfig = repoConfig;
         m_preCommitMembers = new ArrayList<PreCommitMember>();
         m_sessionProps = new Properties();
         m_sessionProps.put(SessionFactory.SERVICE_SID, sessionID);
@@ -133,16 +132,14 @@ public class RepositoryAdminImpl impleme
     }
 
     /**
-     * Returns a list of instances that make up this composition. Instances are used to
-     * inject dependencies into.
-     *
+     * Returns a list of instances that make up this composition. Instances are used to inject dependencies into.
+     * 
      * @return list of instances
      */
     public Object[] getInstances() {
         return new Object[] { this, m_changeNotifierManager };
     }
 
-    @SuppressWarnings("unchecked")
     public void start() {
         synchronized (m_lock) {
             initialize(publishRepositories());
@@ -163,53 +160,64 @@ public class RepositoryAdminImpl impleme
         }
     }
 
-    @SuppressWarnings("unchecked")
     void initialize(Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> repositories) {
         m_repositories = repositories;
     }
 
+    private ChangeNotifier createChangeNotifier(String topic) {
+        return m_changeNotifierManager.getConfiguredNotifier(topic, m_sessionID);
+    }
+
     @SuppressWarnings("unchecked")
     private Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> publishRepositories() {
-        // create the repository objects, if this is the first time this method is called.
+        // create the repository objects, if this is the first time this method is called. In case a repository
+        // implementation needs some form of (runtime) configuration, adapt the RepositoryConfiguration object and pass
+        // this object to the repository...
         if (m_artifactRepositoryImpl == null) {
-            m_artifactRepositoryImpl = new ArtifactRepositoryImpl(m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, ArtifactObject.TOPIC_ENTITY_ROOT, m_sessionID));
-            m_featureRepositoryImpl = new FeatureRepositoryImpl(m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, FeatureObject.TOPIC_ENTITY_ROOT, m_sessionID));
-            m_artifact2FeatureAssociationRepositoryImpl = new Artifact2FeatureAssociationRepositoryImpl(m_artifactRepositoryImpl, m_featureRepositoryImpl, m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, Artifact2FeatureAssociation.TOPIC_ENTITY_ROOT, m_sessionID));
-            m_distributionRepositoryImpl = new DistributionRepositoryImpl(m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, DistributionObject.TOPIC_ENTITY_ROOT, m_sessionID));
-            m_feature2DistributionAssociationRepositoryImpl = new Feature2DistributionAssociationRepositoryImpl(m_featureRepositoryImpl, m_distributionRepositoryImpl, m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, Feature2DistributionAssociation.TOPIC_ENTITY_ROOT, m_sessionID));
-            m_targetRepositoryImpl = new TargetRepositoryImpl(m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, TargetObject.TOPIC_ENTITY_ROOT, m_sessionID));
-            m_distribution2TargetAssociationRepositoryImpl = new Distribution2TargetAssociationRepositoryImpl(m_distributionRepositoryImpl, m_targetRepositoryImpl, m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, Distribution2TargetAssociation.TOPIC_ENTITY_ROOT, m_sessionID));
-            m_deploymentVersionRepositoryImpl = new DeploymentVersionRepositoryImpl(m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, DeploymentVersionObject.TOPIC_ENTITY_ROOT, m_sessionID));
+            m_artifactRepositoryImpl = new ArtifactRepositoryImpl(createChangeNotifier(ArtifactObject.TOPIC_ENTITY_ROOT), m_repositoryConfig);
+            m_featureRepositoryImpl = new FeatureRepositoryImpl(createChangeNotifier(FeatureObject.TOPIC_ENTITY_ROOT), m_repositoryConfig);
+            m_distributionRepositoryImpl = new DistributionRepositoryImpl(createChangeNotifier(DistributionObject.TOPIC_ENTITY_ROOT), m_repositoryConfig);
+            m_targetRepositoryImpl = new TargetRepositoryImpl(createChangeNotifier(TargetObject.TOPIC_ENTITY_ROOT), m_repositoryConfig);
+            //
+            m_deploymentVersionRepositoryImpl = new DeploymentVersionRepositoryImpl(createChangeNotifier(DeploymentVersionObject.TOPIC_ENTITY_ROOT), m_repositoryConfig);
+            //
+            m_artifact2FeatureAssociationRepositoryImpl = new Artifact2FeatureAssociationRepositoryImpl(m_artifactRepositoryImpl, m_featureRepositoryImpl, createChangeNotifier(Artifact2FeatureAssociation.TOPIC_ENTITY_ROOT), m_repositoryConfig);
+            m_feature2DistributionAssociationRepositoryImpl = new Feature2DistributionAssociationRepositoryImpl(m_featureRepositoryImpl, m_distributionRepositoryImpl, createChangeNotifier(Feature2DistributionAssociation.TOPIC_ENTITY_ROOT), m_repositoryConfig);
+            m_distribution2TargetAssociationRepositoryImpl = new Distribution2TargetAssociationRepositoryImpl(m_distributionRepositoryImpl, m_targetRepositoryImpl, createChangeNotifier(Distribution2TargetAssociation.TOPIC_ENTITY_ROOT), m_repositoryConfig);
         }
-        
+
         // first, register the artifact repository manually; it needs some special care.
-        Component artifactRepoService = m_manager.createComponent()
+        Component artifactRepoService = m_dm.createComponent()
             .setInterface(ArtifactRepository.class.getName(), m_sessionProps)
             .setImplementation(m_artifactRepositoryImpl)
-            .add(m_manager.createServiceDependency().setService(ConnectionFactory.class).setRequired(true))
-            .add(m_manager.createServiceDependency().setService(LogService.class).setRequired(false))
-            .add(m_manager.createServiceDependency().setService(ArtifactHelper.class).setRequired(false).setAutoConfig(false).setCallbacks(this, "addArtifactHelper", "removeArtifactHelper"));
-        
+            .add(m_dm.createServiceDependency().setService(ConnectionFactory.class).setRequired(true))
+            .add(m_dm.createServiceDependency().setService(LogService.class).setRequired(false))
+            .add(m_dm.createServiceDependency().setService(ArtifactHelper.class).setRequired(false).setAutoConfig(false).setCallbacks(this, "addArtifactHelper", "removeArtifactHelper"));
+
         Dictionary topic = new Hashtable();
         topic.put(EventConstants.EVENT_FILTER, "(" + SessionFactory.SERVICE_SID + "=" + m_sessionID + ")");
         topic.put(EventConstants.EVENT_TOPIC, new String[] {});
-        
-        Component artifactHandlerService = m_manager.createComponent()
+
+        Component artifactHandlerService = m_dm.createComponent()
             .setInterface(EventHandler.class.getName(), topic)
             .setImplementation(m_artifactRepositoryImpl);
 
-        m_manager.add(artifactRepoService);
-        m_manager.add(artifactHandlerService);
+        m_dm.add(artifactRepoService);
+        m_dm.add(artifactHandlerService);
 
         m_services = new ArrayList<Component[]>();
-        m_services.add(new Component[] {artifactRepoService, artifactHandlerService});
+        m_services.add(new Component[] { artifactRepoService, artifactHandlerService });
 
-        // register all repositories are services. Keep the service objects around, we need them to pull the services later.
-        m_services.add(registerRepository(Artifact2FeatureAssociationRepository.class, m_artifact2FeatureAssociationRepositoryImpl, new String[] {createPrivateObjectTopic(ArtifactObject.TOPIC_ENTITY_ROOT), createPrivateObjectTopic(FeatureObject.TOPIC_ENTITY_ROOT)}));
+        // register all repositories are services. Keep the service objects around, we need them to pull the services
+        // later.
+        m_services.add(registerRepository(Artifact2FeatureAssociationRepository.class, m_artifact2FeatureAssociationRepositoryImpl, new String[] { createPrivateObjectTopic(ArtifactObject.TOPIC_ENTITY_ROOT),
+            createPrivateObjectTopic(FeatureObject.TOPIC_ENTITY_ROOT) }));
         m_services.add(registerRepository(FeatureRepository.class, m_featureRepositoryImpl, new String[] {}));
-        m_services.add(registerRepository(Feature2DistributionAssociationRepository.class, m_feature2DistributionAssociationRepositoryImpl, new String[] {createPrivateObjectTopic(FeatureObject.TOPIC_ENTITY_ROOT), createPrivateObjectTopic(DistributionObject.TOPIC_ENTITY_ROOT)}));
+        m_services.add(registerRepository(Feature2DistributionAssociationRepository.class, m_feature2DistributionAssociationRepositoryImpl, new String[] { createPrivateObjectTopic(FeatureObject.TOPIC_ENTITY_ROOT),
+            createPrivateObjectTopic(DistributionObject.TOPIC_ENTITY_ROOT) }));
         m_services.add(registerRepository(DistributionRepository.class, m_distributionRepositoryImpl, new String[] {}));
-        m_services.add(registerRepository(Distribution2TargetAssociationRepository.class, m_distribution2TargetAssociationRepositoryImpl, new String[] {createPrivateObjectTopic(DistributionObject.TOPIC_ENTITY_ROOT), createPrivateObjectTopic(TargetObject.TOPIC_ENTITY_ROOT)}));
+        m_services.add(registerRepository(Distribution2TargetAssociationRepository.class, m_distribution2TargetAssociationRepositoryImpl, new String[] { createPrivateObjectTopic(DistributionObject.TOPIC_ENTITY_ROOT),
+            createPrivateObjectTopic(TargetObject.TOPIC_ENTITY_ROOT) }));
         m_services.add(registerRepository(TargetRepository.class, m_targetRepositoryImpl, new String[] {}));
         m_services.add(registerRepository(DeploymentVersionRepository.class, m_deploymentVersionRepositoryImpl, new String[] {}));
 
@@ -234,27 +242,27 @@ public class RepositoryAdminImpl impleme
     private void pullRepositories() {
         for (Component[] services : m_services) {
             for (Component service : services) {
-                m_manager.remove(service);
+                m_dm.remove(service);
             }
         }
     }
 
     @SuppressWarnings("unchecked")
     private <T extends RepositoryObject> Component[] registerRepository(Class<? extends ObjectRepository<T>> iface, ObjectRepositoryImpl<?, T> implementation, String[] topics) {
-        Component repositoryService = m_manager.createComponent()
+        Component repositoryService = m_dm.createComponent()
             .setInterface(iface.getName(), m_sessionProps)
             .setImplementation(implementation)
-            .add(m_manager.createServiceDependency().setService(LogService.class).setRequired(false));
+            .add(m_dm.createServiceDependency().setService(LogService.class).setRequired(false));
         Dictionary topic = new Hashtable();
         topic.put(EventConstants.EVENT_TOPIC, topics);
         topic.put(EventConstants.EVENT_FILTER, "(" + SessionFactory.SERVICE_SID + "=" + m_sessionID + ")");
-        Component handlerService = m_manager.createComponent()
+        Component handlerService = m_dm.createComponent()
             .setInterface(EventHandler.class.getName(), topic)
             .setImplementation(implementation);
 
-        m_manager.add(repositoryService);
-        m_manager.add(handlerService);
-        return new Component[] {repositoryService, handlerService};
+        m_dm.add(repositoryService);
+        m_dm.add(handlerService);
+        return new Component[] { repositoryService, handlerService };
     }
 
     /**
@@ -321,7 +329,7 @@ public class RepositoryAdminImpl impleme
             ensureLogin();
             boolean result = true;
             for (RepositorySet set : m_repositorySets) {
-                    result &= (set.isCurrent() || !set.writeAccess());
+                result &= (set.isCurrent() || !set.writeAccess());
             }
             return result;
         }
@@ -359,20 +367,18 @@ public class RepositoryAdminImpl impleme
         RepositoryAdminLoginContextImpl impl = ((RepositoryAdminLoginContextImpl) context);
         RepositorySet[] repositorySets = getRepositorySets(impl);
 
-        synchronized(m_lock) {
-            // TODO I don't like this line, it should not be here...
-            ((ArtifactRepository) m_repositories.get(ArtifactRepository.class)).setObrBase(impl.getObrBase());
+        synchronized (m_lock) {
             login(impl.getUser(), repositorySets);
         }
     }
 
     /**
-     * Helper method for login; also allows injection of custom RepositorySet objects for
-     * testing purposes.
+     * Helper method for login; also allows injection of custom RepositorySet objects for testing purposes.
+     * 
      * @throws IOException
      */
     private void login(User user, RepositorySet[] sets) throws IOException {
-        synchronized(m_lock) {
+        synchronized (m_lock) {
             if (m_user != null) {
                 throw new IllegalStateException("Another user is logged in.");
             }
@@ -407,32 +413,29 @@ public class RepositoryAdminImpl impleme
             for (RepositorySet set : m_repositorySets) {
                 set.clearRepositories();
                 set.unregisterHandler();
-//                set.deleteLocal();
+                // set.deleteLocal();
             }
 
-            
             unloadRepositorySet(m_user);
-            
-            
-            
+
             m_user = null;
-//            m_repositorySets = new RepositorySet[0];
+            // m_repositorySets = new RepositorySet[0];
         }
         m_changeNotifier.notifyChanged(TOPIC_LOGOUT_SUFFIX, null);
-        
+
         if (exception != null) {
             throw exception;
         }
     }
-    
+
     public void deleteLocal() {
-    	synchronized (m_lock) {
-    		if (m_user != null && m_repositorySets != null) {
-    			for (RepositorySet set : m_repositorySets) {
-    				set.deleteLocal();
-    			}
-    		}
-    	}
+        synchronized (m_lock) {
+            if (m_user != null && m_repositorySets != null) {
+                for (RepositorySet set : m_repositorySets) {
+                    set.deleteLocal();
+                }
+            }
+        }
     }
 
     private boolean loggedIn() {
@@ -441,6 +444,7 @@ public class RepositoryAdminImpl impleme
 
     /**
      * Helper method to make sure a user is logged in.
+     * 
      * @throws IllegalStateException
      */
     private void ensureLogin() throws IllegalStateException {
@@ -452,10 +456,9 @@ public class RepositoryAdminImpl impleme
     /**
      * Helper method, creates RepositorySets based on the Login context.
      */
-    @SuppressWarnings("unchecked")
     private RepositorySet[] getRepositorySets(RepositoryAdminLoginContextImpl context) throws IOException {
         List<RepositorySetDescriptor> descriptors = context.getDescriptors();
-        
+
         // First, some sanity checks on the list of descriptors.
         for (RepositorySetDescriptor rsd : descriptors) {
             for (Class c : rsd.m_objectRepositories) {
@@ -469,12 +472,11 @@ public class RepositoryAdminImpl impleme
         RepositorySet[] result = new RepositorySet[descriptors.size()];
 
         /*
-         * Create the lists of repositories and topics, and create and register
-         * the sets with these.
+         * Create the lists of repositories and topics, and create and register the sets with these.
          */
         for (int i = 0; i < result.length; i++) {
             RepositorySetDescriptor rsd = descriptors.get(i);
-            
+
             ObjectRepositoryImpl[] impls = new ObjectRepositoryImpl[rsd.m_objectRepositories.length];
             String[] topics = new String[rsd.m_objectRepositories.length];
             for (int j = 0; j < impls.length; j++) {
@@ -502,6 +504,7 @@ public class RepositoryAdminImpl impleme
 
     /**
      * Helper method for login.
+     * 
      * @throws IOException
      */
     private File getFileFromPreferences(Preferences repositoryPrefs, String type) throws IOException {
@@ -537,6 +540,7 @@ public class RepositoryAdminImpl impleme
 
     /**
      * Helper method for login.
+     * 
      * @throws IOException
      */
     private BackupRepository getBackupFromPreferences(Preferences repositoryPrefs) throws IOException {
@@ -547,6 +551,7 @@ public class RepositoryAdminImpl impleme
 
     /**
      * Helper method for login.
+     * 
      * @throws IOException
      */
     private CachedRepository getCachedRepositoryFromPreferences(Repository repository, Preferences repositoryPrefs) throws IOException {
@@ -556,20 +561,23 @@ public class RepositoryAdminImpl impleme
 
     /**
      * Helper method for login, which loads a set of repositories.
-     * @param user A <code>User</code> object
-     * @param rsd A RepositorySetDescriptor, defining the set to be created.
-     * @param repos An array of <code>ObjectRepositoryImpl</code> which this set should manage. Each
+     * 
+     * @param user
+     *            A <code>User</code> object
+     * @param rsd
+     *            A RepositorySetDescriptor, defining the set to be created.
+     * @param repos
+     *            An array of <code>ObjectRepositoryImpl</code> which this set should manage. Each
      * @return The newly created repository set.
      * @throws IOException
      */
-    @SuppressWarnings("unchecked")
     public RepositorySet loadRepositorySet(User user, RepositorySetDescriptor rsd, ObjectRepositoryImpl[] repos) throws IOException {
         Repository repo = new RemoteRepository(rsd.m_location, rsd.m_customer, rsd.m_name);
 
         // Expose the repository itself as component so its dependencies get managed...
-        m_manager.add(m_manager.createComponent()
+        m_dm.add(m_dm.createComponent()
             .setImplementation(repo)
-            .add(m_manager.createServiceDependency()
+            .add(m_dm.createServiceDependency()
                 .setService(ConnectionFactory.class)
                 .setRequired(true)));
 
@@ -579,7 +587,7 @@ public class RepositoryAdminImpl impleme
 
         return new RepositorySet(m_changeNotifier, m_log, user, repoPrefs, repos, getCachedRepositoryFromPreferences(repo, repoPrefs), rsd.m_name, rsd.m_writeAccess);
     }
-    
+
     private void unloadRepositorySet(User user) {
         Preferences prefs = m_preferences.getUserPreferences(user.getName());
         prefs.remove(m_sessionID);

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImpl.java Thu Oct 10 14:11:13 2013
@@ -35,12 +35,12 @@ import org.apache.ace.client.repository.
 import org.apache.ace.client.repository.repository.TargetRepository;
 import org.osgi.service.useradmin.User;
 
+@SuppressWarnings({ "unchecked" })
 public class RepositoryAdminLoginContextImpl implements RepositoryAdminLoginContext {
-    
+
     private final String m_sessionid;
     private final User m_user;
     private final List<RepositorySetDescriptor> m_descriptors = new ArrayList<RepositorySetDescriptor>();
-    private URL m_obrBase;
 
     RepositoryAdminLoginContextImpl(User user, String sessionid) {
         m_user = user;
@@ -54,14 +54,15 @@ public class RepositoryAdminLoginContext
         if (!(repositoryContext instanceof AbstractRepositoryContext)) {
             throw new IllegalArgumentException("Invalid repository context!");
         }
-        
+
         addDescriptor(((AbstractRepositoryContext<?>) repositoryContext).createDescriptor());
-        
+
         return this;
     }
 
     /**
-     * @param descriptor the descriptor to add, cannot be <code>null</code>.
+     * @param descriptor
+     *            the descriptor to add, cannot be <code>null</code>.
      */
     public void addDescriptor(RepositorySetDescriptor descriptor) {
         checkConsistency(descriptor);
@@ -103,19 +104,10 @@ public class RepositoryAdminLoginContext
         return result;
     }
 
-    public RepositoryAdminLoginContext setObrBase(URL base) {
-        m_obrBase = base;
-        return this;
-    }
-
-    URL getObrBase() {
-        return m_obrBase;
-    }
-
     User getUser() {
         return m_user;
     }
-    
+
     String getSessionId() {
         return m_sessionid;
     }
@@ -123,7 +115,8 @@ public class RepositoryAdminLoginContext
     /**
      * Checks the consistency of the internal descriptors with the one given.
      * 
-     * @param descriptor the to-be-added repository set descriptor, cannot be <code>null</code>.
+     * @param descriptor
+     *            the to-be-added repository set descriptor, cannot be <code>null</code>.
      */
     private void checkConsistency(RepositorySetDescriptor descriptor) {
         List<Class<? extends ObjectRepository>> seenClasses = new ArrayList<Class<? extends ObjectRepository>>();
@@ -134,11 +127,11 @@ public class RepositoryAdminLoginContext
             seenClasses.addAll(Arrays.asList(rsd.m_objectRepositories));
             seenNames.add(rsd.m_name);
         }
-        
+
         if (seenNames.contains(descriptor.m_name)) {
             throw new IllegalArgumentException("Duplicate repository name!");
         }
-        
+
         for (Class<? extends ObjectRepository> clazz : descriptor.m_objectRepositories) {
             if (seenClasses.contains(clazz)) {
                 throw new IllegalArgumentException("Duplicate object repository!");
@@ -147,18 +140,16 @@ public class RepositoryAdminLoginContext
     }
 
     /**
-     * Helper class to store all relevant information about a repository in a convenient location before
-     * we start using it.
+     * Helper class to store all relevant information about a repository in a convenient location before we start using
+     * it.
      */
     public static final class RepositorySetDescriptor {
         public final URL m_location;
         public final String m_customer;
         public final String m_name;
         public final boolean m_writeAccess;
-        @SuppressWarnings("unchecked")
         public final Class<? extends ObjectRepository>[] m_objectRepositories;
 
-        @SuppressWarnings("unchecked")
         public RepositorySetDescriptor(URL location, String customer, String name, boolean writeAccess, Class<? extends ObjectRepository>... objectRepositories) {
             m_location = location;
             m_customer = customer;
@@ -173,21 +164,21 @@ public class RepositoryAdminLoginContext
         }
     }
 
-    static abstract class AbstractRepositoryContext<T extends BaseRepositoryContext<?>> implements BaseRepositoryContext<T> 
+    static abstract class AbstractRepositoryContext<T extends BaseRepositoryContext<?>> implements BaseRepositoryContext<T>
     {
         private URL m_location;
         private String m_name;
         private String m_customer;
         private boolean m_writeable;
         private final Class<? extends ObjectRepository<?>>[] m_repositories;
-        
+
         public AbstractRepositoryContext(Class<? extends ObjectRepository<?>>... repositories) {
             if (repositories == null || repositories.length == 0) {
                 throw new IllegalArgumentException("Need at least one object repository!");
             }
             m_repositories = repositories;
         }
-        
+
         public T setCustomer(String customer) {
             if (customer == null) {
                 throw new IllegalArgumentException("Customer cannot be null!");
@@ -216,23 +207,23 @@ public class RepositoryAdminLoginContext
             m_writeable = true;
             return getThis();
         }
-        
+
         /**
          * @return a new repository set descriptor, never <code>null</code>.
          */
         final RepositorySetDescriptor createDescriptor() {
             return new RepositorySetDescriptor(m_location, m_customer, m_name, m_writeable, m_repositories);
         }
-        
+
         abstract T getThis();
     }
 
     static final class ShopRepositoryContextImpl extends AbstractRepositoryContext<ShopRepositoryContext> implements ShopRepositoryContext {
-        
+
         public ShopRepositoryContextImpl() {
             super(ArtifactRepository.class, FeatureRepository.class, Artifact2FeatureAssociationRepository.class, DistributionRepository.class, Feature2DistributionAssociationRepository.class);
         }
-        
+
         @Override
         ShopRepositoryContext getThis() {
             return this;
@@ -240,11 +231,11 @@ public class RepositoryAdminLoginContext
     }
 
     static final class TargetRepositoryContextImpl extends AbstractRepositoryContext<TargetRepositoryContext> implements TargetRepositoryContext {
-        
+
         public TargetRepositoryContextImpl() {
             super(TargetRepository.class, Distribution2TargetAssociationRepository.class);
         }
-        
+
         @Override
         TargetRepositoryContext getThis() {
             return this;
@@ -252,11 +243,11 @@ public class RepositoryAdminLoginContext
     }
 
     static final class DeploymentRepositoryContextImpl extends AbstractRepositoryContext<DeploymentRepositoryContext> implements DeploymentRepositoryContext {
-        
+
         public DeploymentRepositoryContextImpl() {
             super(DeploymentVersionRepository.class);
         }
-        
+
         @Override
         DeploymentRepositoryContext getThis() {
             return this;

Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryConfigurationImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryConfigurationImpl.java?rev=1530984&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryConfigurationImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryConfigurationImpl.java Thu Oct 10 14:11:13 2013
@@ -0,0 +1,245 @@
+/*
+ * 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.ace.client.repository.impl;
+
+import static org.apache.ace.client.repository.repository.RepositoryConstants.KEY_DEPLOYMENT_VERSION_LIMITS;
+import static org.apache.ace.client.repository.repository.RepositoryConstants.KEY_OBR_LOCATION;
+import static org.apache.ace.client.repository.repository.RepositoryConstants.KEY_SHOW_UNREGISTERED_TARGETS;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Map;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import org.apache.ace.client.repository.repository.RepositoryConfiguration;
+
+/**
+ * Helper class to make a type-safe configuration object for holding the configuration of repositories.
+ * <p>
+ * This class is thread-safe.
+ * </p>
+ */
+final class RepositoryConfigurationImpl implements RepositoryConfiguration {
+    private static final boolean DEFAULT_SHOW_UNREGISTERED_TARGETS = true;
+    private static final int DEFAULT_DEPLOYMENT_VERSION_LIMIT = -1;
+    private static final URL DEFAULT_OBR_LOCATION;
+
+    static {
+        try {
+            DEFAULT_OBR_LOCATION = new URL("http://localhost:8080/obr/");
+        }
+        catch (MalformedURLException exception) {
+            throw new RuntimeException("Invalid default URL!", exception);
+        }
+    }
+
+    private final ReadWriteLock m_lock = new ReentrantReadWriteLock();
+
+    private boolean m_showUnregisteredTargets;
+    private int m_deploymentVersionLimit;
+    private URL m_obrLocation;
+
+    /**
+     * Creates a new {@link RepositoryConfigurationImpl} instance.
+     */
+    public RepositoryConfigurationImpl() {
+        m_showUnregisteredTargets = DEFAULT_SHOW_UNREGISTERED_TARGETS;
+        m_deploymentVersionLimit = DEFAULT_DEPLOYMENT_VERSION_LIMIT;
+        m_obrLocation = DEFAULT_OBR_LOCATION;
+    }
+
+    /**
+     * Creates a new {@link RepositoryConfigurationImpl} instance.
+     */
+    public RepositoryConfigurationImpl(RepositoryConfiguration defaultConfig) {
+        m_showUnregisteredTargets = defaultConfig.isShowUnregisteredTargets();
+        m_deploymentVersionLimit = defaultConfig.getDeploymentVersionLimit();
+        m_obrLocation = defaultConfig.getOBRLocation();
+    }
+
+    /**
+     * Creates a new {@link RepositoryConfigurationImpl} instance.
+     */
+    public RepositoryConfigurationImpl(RepositoryConfiguration defaultConfig, Map<String, Object> map) {
+        m_showUnregisteredTargets = parseBoolean(map.get(KEY_SHOW_UNREGISTERED_TARGETS), defaultConfig.isShowUnregisteredTargets());
+        m_deploymentVersionLimit = parseInteger(map.get(KEY_DEPLOYMENT_VERSION_LIMITS), defaultConfig.getDeploymentVersionLimit());
+        m_obrLocation = parseURL(map.get(KEY_OBR_LOCATION), defaultConfig.getOBRLocation());
+    }
+
+    @Override
+    public int getDeploymentVersionLimit() {
+        Lock lock = m_lock.readLock();
+        lock.lock();
+        try {
+            return m_deploymentVersionLimit;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    public URL getOBRLocation() {
+        Lock lock = m_lock.readLock();
+        lock.lock();
+        try {
+            return m_obrLocation;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    @Override
+    public boolean isShowUnregisteredTargets() {
+        Lock lock = m_lock.readLock();
+        lock.lock();
+        try {
+            return m_showUnregisteredTargets;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Sets the number of deployment versions to retain per target.
+     * 
+     * @param deploymentVersionLimit
+     *            the limit to set, > 0 or -1 if no limit is to be imposed.
+     */
+    public void setDeploymentVersionLimit(int deploymentVersionLimit) {
+        if (deploymentVersionLimit == 0) {
+            throw new IllegalArgumentException("Deployment version limit cannot be zero!");
+        }
+
+        Lock lock = m_lock.writeLock();
+        lock.lock();
+        try {
+            m_deploymentVersionLimit = deploymentVersionLimit;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * @param base
+     *            the base OBR location to set, should not be <code>null</code>.
+     */
+    public void setObrLocation(URL base) {
+        if (base == null) {
+            throw new IllegalArgumentException("Base URL cannot be null!");
+        }
+
+        Lock lock = m_lock.writeLock();
+        lock.lock();
+        try {
+            m_obrLocation = base;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * @param showUnregisteredTargets
+     *            the showUnregisteredTargets to set, can be <code>null</code>.
+     */
+    public void setShowUnregisteredTargets(boolean showUnregisteredTargets) {
+        Lock lock = m_lock.writeLock();
+        lock.lock();
+        try {
+            m_showUnregisteredTargets = showUnregisteredTargets;
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    /**
+     * Updates the configuration atomically.
+     * 
+     * @param dict
+     *            the dictionary with the new configuration options, can be <code>null</code> in case the default values
+     *            should be used.
+     */
+    public void update(Dictionary<String, Object> dict) {
+        Lock lock = m_lock.writeLock();
+        lock.lock();
+        try {
+            if (dict == null) {
+                m_showUnregisteredTargets = DEFAULT_SHOW_UNREGISTERED_TARGETS;
+                m_deploymentVersionLimit = DEFAULT_DEPLOYMENT_VERSION_LIMIT;
+                m_obrLocation = DEFAULT_OBR_LOCATION;
+            }
+            else {
+                m_showUnregisteredTargets = parseBoolean(dict.get(KEY_SHOW_UNREGISTERED_TARGETS), m_showUnregisteredTargets);
+                m_deploymentVersionLimit = parseInteger(dict.get(KEY_DEPLOYMENT_VERSION_LIMITS), m_deploymentVersionLimit);
+                m_obrLocation = parseURL(dict.get(KEY_OBR_LOCATION), m_obrLocation);
+            }
+        }
+        finally {
+            lock.unlock();
+        }
+    }
+
+    private static boolean parseBoolean(Object value, boolean defaultValue) {
+        if (value instanceof Boolean) {
+            return ((Boolean) value).booleanValue();
+        }
+        else if (value instanceof String) {
+            return Boolean.parseBoolean((String) value);
+        }
+        return defaultValue;
+    }
+
+    private static int parseInteger(Object value, int defaultValue) {
+        if (value instanceof Integer) {
+            return ((Integer) value).intValue();
+        }
+        else if (value instanceof String) {
+            try {
+                return Integer.valueOf((String) value);
+            }
+            catch (NumberFormatException exception) {
+                // Ignore, use default value...
+            }
+        }
+        return defaultValue;
+    }
+
+    private static URL parseURL(Object value, URL defaultValue) {
+        if (value instanceof URL) {
+            return (URL) value;
+        }
+        else if (value instanceof String) {
+            try {
+                return new URL((String) value);
+            }
+            catch (MalformedURLException exception) {
+                // Ignore, use default value...
+            }
+        }
+        return defaultValue;
+    }
+}

Propchange: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryConfigurationImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryObjectImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryObjectImpl.java?rev=1530984&r1=1530983&r2=1530984&view=diff
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryObjectImpl.java (original)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryObjectImpl.java Thu Oct 10 14:11:13 2013
@@ -31,7 +31,6 @@ import com.thoughtworks.xstream.io.Hiera
 public class RepositoryObjectImpl<T extends RepositoryObject> extends Dictionary<String, Object> implements RepositoryObject, EventHandler {
     private final Map<String, String> m_attributes = new HashMap<String, String>();
     private final Map<String, String> m_tags = new HashMap<String, String>();
-    @SuppressWarnings("unchecked")
     private final Map<Class, List<Association>> m_associations = new HashMap<Class, List<Association>>();
     private final ChangeNotifier m_notifier;
     private final String m_xmlNode;
@@ -265,7 +264,6 @@ public class RepositoryObjectImpl<T exte
         }
     }
 
-    @SuppressWarnings("unchecked")
     public void add(Association association, Class clazz) {
         synchronized (m_associations) {
             List<Association> associations = m_associations.get(clazz);
@@ -277,7 +275,6 @@ public class RepositoryObjectImpl<T exte
         }
     }
 
-    @SuppressWarnings("unchecked")
     public void remove(Association association, Class clazz) {
         synchronized (m_associations) {
             List<Association> associations = m_associations.get(clazz);
@@ -287,7 +284,6 @@ public class RepositoryObjectImpl<T exte
         }
     }
 
-    @SuppressWarnings("unchecked")
     public <A extends Associatable> List<A> getAssociations(Class<A> clazz) {
         synchronized (m_associations) {
             List<A> result = new ArrayList<A>();
@@ -306,7 +302,6 @@ public class RepositoryObjectImpl<T exte
         }
     }
 
-    @SuppressWarnings("unchecked")
     public boolean isAssociated(Object obj, Class clazz) {
         synchronized (m_associations) {
             if (obj == null) {
@@ -344,7 +339,6 @@ public class RepositoryObjectImpl<T exte
     }
 
     @Override
-    @SuppressWarnings("unchecked")
     public boolean equals(Object o) {
         synchronized(m_attributes) {
             if ((o == null) || !(getClass().isInstance(o))) {