You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ma...@apache.org on 2013/04/02 16:53:35 UTC

svn commit: r1463576 [4/8] - in /ace/trunk: org.apache.ace.client.repository.api/ org.apache.ace.client.repository.helper.base/ org.apache.ace.client.repository.helper.bundle/ org.apache.ace.client.repository.helper.configuration/ org.apache.ace.client...

Added: 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=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Distribution2TargetAssociationRepositoryImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Distribution2TargetAssociationRepositoryImpl.java Tue Apr  2 14:53:33 2013
@@ -0,0 +1,87 @@
+/*
+ * 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 java.util.Map;
+
+import org.apache.ace.client.repository.object.TargetObject;
+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.osgi.framework.InvalidSyntaxException;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+/**
+ * Implementation class for the Distribution2TargetAssociationRepository. For 'what it does', see Distribution2TargetAssociationRepository,
+ * for 'how it works', see AssociationRepositoryImpl.
+ */
+
+public class Distribution2TargetAssociationRepositoryImpl extends AssociationRepositoryImpl<DistributionObject, TargetObject, Distribution2TargetAssociationImpl, Distribution2TargetAssociation> implements Distribution2TargetAssociationRepository {
+    private final static String XML_NODE = "distributions2targets";
+
+    private final DistributionRepositoryImpl m_distributionRepository;
+    private final TargetRepositoryImpl m_targetRepository;
+
+    public Distribution2TargetAssociationRepositoryImpl(DistributionRepositoryImpl distributionRepository, TargetRepositoryImpl targetRepository, ChangeNotifier notifier) {
+        super(notifier, XML_NODE);
+        m_distributionRepository = distributionRepository;
+        m_targetRepository = targetRepository;
+    }
+
+    @Override
+    Distribution2TargetAssociationImpl createNewInhabitant(Map<String, String> attributes) {
+        try {
+            return new Distribution2TargetAssociationImpl(attributes, this, m_distributionRepository, m_targetRepository);
+        }
+        catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException("Unable to create association: ", e);
+        }
+    }
+
+    @Override
+    Distribution2TargetAssociationImpl createNewInhabitant(Map<String, String> attributes, Map<String, String> tags) {
+        try {
+            return new Distribution2TargetAssociationImpl(attributes, tags, this, m_distributionRepository, m_targetRepository);
+        }
+        catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException("Unable to create association: ", e);
+        }
+    }
+
+    @Override
+    Distribution2TargetAssociationImpl createNewInhabitant(HierarchicalStreamReader reader) {
+        try {
+            return new Distribution2TargetAssociationImpl(reader, this, m_distributionRepository, m_targetRepository);
+        }
+        catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException("Unable to create association: ", e);
+        }
+    }
+
+    public Distribution2TargetAssociation createDistribution2TargetFilter(DistributionObject distribution, String targetFilter) {
+        try {
+            m_targetRepository.createFilter(targetFilter);
+        }
+        catch (InvalidSyntaxException ise) {
+            throw new IllegalArgumentException("Target filter '" + targetFilter + "' cannot be parsed into a valid Filter.", ise);
+        }
+
+        return create(distribution.getAssociationFilter(null), targetFilter);
+    }
+}

Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DistributionObjectImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DistributionObjectImpl.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DistributionObjectImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DistributionObjectImpl.java Tue Apr  2 14:53:33 2013
@@ -0,0 +1,88 @@
+/*
+ * 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 java.util.List;
+import java.util.Map;
+
+import org.apache.ace.client.repository.object.TargetObject;
+import org.apache.ace.client.repository.object.Feature2DistributionAssociation;
+import org.apache.ace.client.repository.object.FeatureObject;
+import org.apache.ace.client.repository.object.Distribution2TargetAssociation;
+import org.apache.ace.client.repository.object.DistributionObject;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/**
+ * Implementation class for the DistributionObject. For 'what it does', see DistributionObject,
+ * for 'how it works', see RepositoryObjectImpl.
+ */
+public class DistributionObjectImpl extends RepositoryObjectImpl<DistributionObject> implements DistributionObject {
+    private final static String XML_NODE = "distribution";
+
+    DistributionObjectImpl(Map<String, String> attributes, Map<String, String> tags, ChangeNotifier notifier) {
+        super(checkAttributes(attributes, KEY_NAME), tags, notifier, XML_NODE);
+    }
+
+    DistributionObjectImpl(Map<String, String> attributes, ChangeNotifier notifier) {
+        super(checkAttributes(attributes, KEY_NAME), notifier, XML_NODE);
+    }
+
+    DistributionObjectImpl(HierarchicalStreamReader reader, ChangeNotifier notifier) {
+        super(reader, notifier, XML_NODE);
+    }
+
+    public List<TargetObject> getTargets() {
+        return getAssociations(TargetObject.class);
+    }
+
+    public List<FeatureObject> getFeatures() {
+        return getAssociations(FeatureObject.class);
+    }
+
+    public String getDescription() {
+        return getAttribute(KEY_DESCRIPTION);
+    }
+
+    public String getName() {
+        return getAttribute(KEY_NAME);
+    }
+
+    public void setDescription(String description) {
+        addAttribute(KEY_DESCRIPTION, description);
+    }
+
+    public void setName(String name) {
+        addAttribute(KEY_NAME, name);
+    }
+
+    public List<Feature2DistributionAssociation> getAssociationsWith(FeatureObject feature) {
+        return getAssociationsWith(feature, FeatureObject.class, Feature2DistributionAssociation.class);
+    }
+
+    public List<Distribution2TargetAssociation> getAssociationsWith(TargetObject target) {
+        return getAssociationsWith(target, TargetObject.class, Distribution2TargetAssociation.class);
+    }
+
+    private static String[] DEFINING_KEYS = new String[] {KEY_NAME};
+    @Override
+    String[] getDefiningKeys() {
+        return DEFINING_KEYS;
+    }
+}

Added: 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=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DistributionRepositoryImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/DistributionRepositoryImpl.java Tue Apr  2 14:53:33 2013
@@ -0,0 +1,53 @@
+/*
+ * 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 java.util.Map;
+
+import org.apache.ace.client.repository.object.DistributionObject;
+import org.apache.ace.client.repository.repository.DistributionRepository;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/**
+ * Implementation class for the DistributionRepository. For 'what it does', see DistributionRepository,
+ * for 'how it works', see ObjectRepositoryImpl.
+ */
+public class DistributionRepositoryImpl extends ObjectRepositoryImpl<DistributionObjectImpl, DistributionObject> implements DistributionRepository {
+    private final static String XML_NODE = "distributions";
+
+    public DistributionRepositoryImpl(ChangeNotifier notifier) {
+        super(notifier, XML_NODE);
+    }
+
+    @Override
+    DistributionObjectImpl createNewInhabitant(Map<String, String> attributes, Map<String, String> tags) {
+        return new DistributionObjectImpl(attributes, tags, this);
+    }
+
+    @Override
+    DistributionObjectImpl createNewInhabitant(Map<String, String> attributes) {
+        return new DistributionObjectImpl(attributes, this);
+    }
+
+    @Override
+    DistributionObjectImpl createNewInhabitant(HierarchicalStreamReader reader) {
+        return new DistributionObjectImpl(reader, this);
+    }
+}

Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Feature2DistributionAssociationImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Feature2DistributionAssociationImpl.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Feature2DistributionAssociationImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Feature2DistributionAssociationImpl.java Tue Apr  2 14:53:33 2013
@@ -0,0 +1,46 @@
+/*
+ * 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 java.util.Map;
+
+import org.apache.ace.client.repository.object.Feature2DistributionAssociation;
+import org.apache.ace.client.repository.object.FeatureObject;
+import org.apache.ace.client.repository.object.DistributionObject;
+import org.osgi.framework.InvalidSyntaxException;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/**
+ * Implementation class for the Feature2DistributionAssociation. For 'what it does', see Feature2DistributionAssociation,
+ * for 'how it works', see AssociationImpl.
+ */
+public class Feature2DistributionAssociationImpl extends AssociationImpl<FeatureObject, DistributionObject, Feature2DistributionAssociation> implements Feature2DistributionAssociation {
+    private final static String XML_NODE = "feature2distribution";
+
+    public Feature2DistributionAssociationImpl(Map<String, String> attributes, ChangeNotifier notifier, FeatureRepositoryImpl featureRepository, DistributionRepositoryImpl distributionRepository) throws InvalidSyntaxException {
+        super(attributes, notifier, FeatureObject.class, DistributionObject.class, featureRepository, distributionRepository, XML_NODE);
+    }
+    public Feature2DistributionAssociationImpl(Map<String, String> attributes, Map<String, String> tags, ChangeNotifier notifier, FeatureRepositoryImpl featureRepository, DistributionRepositoryImpl distributionRepository) throws InvalidSyntaxException {
+        super(attributes, tags, notifier, FeatureObject.class, DistributionObject.class, featureRepository, distributionRepository, XML_NODE);
+    }
+    public Feature2DistributionAssociationImpl(HierarchicalStreamReader reader, ChangeNotifier notifier, FeatureRepositoryImpl featureRepository, DistributionRepositoryImpl distributionRepository) throws InvalidSyntaxException {
+        super(reader, notifier, FeatureObject.class, DistributionObject.class, null, null, featureRepository, distributionRepository, XML_NODE);
+    }
+}

Added: 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=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Feature2DistributionAssociationRepositoryImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Feature2DistributionAssociationRepositoryImpl.java Tue Apr  2 14:53:33 2013
@@ -0,0 +1,76 @@
+/*
+ * 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 java.util.Map;
+
+import org.apache.ace.client.repository.object.Feature2DistributionAssociation;
+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.osgi.framework.InvalidSyntaxException;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/**
+ * Implementation class for the Feature2DistributionAssociationRepository. For 'what it does', see Feature2DistributionAssociationRepository,
+ * for 'how it works', see AssociationRepositoryImpl.
+ */
+public class Feature2DistributionAssociationRepositoryImpl extends AssociationRepositoryImpl<FeatureObject, DistributionObject, Feature2DistributionAssociationImpl, Feature2DistributionAssociation> implements Feature2DistributionAssociationRepository {
+    private final static String XML_NODE = "features2distributions";
+
+    private final FeatureRepositoryImpl m_featureRepository;
+    private final DistributionRepositoryImpl m_distributionRepository;
+
+    public Feature2DistributionAssociationRepositoryImpl(FeatureRepositoryImpl featureRepository, DistributionRepositoryImpl distributionRepository, ChangeNotifier notifier) {
+        super(notifier, XML_NODE);
+        m_featureRepository = featureRepository;
+        m_distributionRepository = distributionRepository;
+    }
+
+    @Override
+    Feature2DistributionAssociationImpl createNewInhabitant(Map<String, String> attributes) {
+        try {
+            return new Feature2DistributionAssociationImpl(attributes, this, m_featureRepository, m_distributionRepository);
+        }
+        catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException("Unable to create association: ", e);
+        }
+    }
+
+    @Override
+    Feature2DistributionAssociationImpl createNewInhabitant(Map<String, String> attributes, Map<String, String> tags) {
+        try {
+            return new Feature2DistributionAssociationImpl(attributes, tags, this, m_featureRepository, m_distributionRepository);
+        }
+        catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException("Unable to create association: ", e);
+        }
+    }
+
+    @Override
+    Feature2DistributionAssociationImpl createNewInhabitant(HierarchicalStreamReader reader) {
+        try {
+            return new Feature2DistributionAssociationImpl(reader, this, m_featureRepository, m_distributionRepository);
+        }
+        catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException("Unable to create association: ", e);
+        }
+    }
+}

Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/FeatureObjectImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/FeatureObjectImpl.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/FeatureObjectImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/FeatureObjectImpl.java Tue Apr  2 14:53:33 2013
@@ -0,0 +1,88 @@
+/*
+ * 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 java.util.List;
+import java.util.Map;
+
+import org.apache.ace.client.repository.object.Artifact2FeatureAssociation;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.ace.client.repository.object.Feature2DistributionAssociation;
+import org.apache.ace.client.repository.object.FeatureObject;
+import org.apache.ace.client.repository.object.DistributionObject;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/**
+ * Implementation class for the FeatureObject. For 'what it does', see FeatureObject,
+ * for 'how it works', see RepositoryObjectImpl.
+ */
+public class FeatureObjectImpl extends RepositoryObjectImpl<FeatureObject> implements FeatureObject {
+    private final static String XML_NODE = "feature";
+
+    FeatureObjectImpl(Map<String, String> attributes, Map<String, String> tags, ChangeNotifier notifier) {
+        super(checkAttributes(attributes, KEY_NAME), tags, notifier, XML_NODE);
+    }
+
+    FeatureObjectImpl(Map<String, String> attributes, ChangeNotifier notifier) {
+        super(checkAttributes(attributes, KEY_NAME), notifier, XML_NODE);
+    }
+
+    FeatureObjectImpl(HierarchicalStreamReader reader, ChangeNotifier notifier) {
+        super(reader, notifier, XML_NODE);
+    }
+
+    public List<ArtifactObject> getArtifacts() {
+        return getAssociations(ArtifactObject.class);
+    }
+
+    public List<DistributionObject> getDistributions() {
+        return getAssociations(DistributionObject.class);
+    }
+
+    public String getDescription() {
+        return getAttribute(KEY_DESCRIPTION);
+    }
+
+    public String getName() {
+        return getAttribute(KEY_NAME);
+    }
+
+    public void setDescription(String description) {
+        addAttribute(KEY_DESCRIPTION, description);
+    }
+
+    public void setName(String name) {
+        addAttribute(KEY_NAME, name);
+    }
+
+    public List<Artifact2FeatureAssociation> getAssociationsWith(ArtifactObject artifact) {
+        return getAssociationsWith(artifact, ArtifactObject.class, Artifact2FeatureAssociation.class);
+    }
+
+    public List<Feature2DistributionAssociation> getAssociationsWith(DistributionObject distribution) {
+        return getAssociationsWith(distribution, DistributionObject.class, Feature2DistributionAssociation.class);
+    }
+
+    private static String[] DEFINING_KEYS = new String[] {KEY_NAME};
+    @Override
+    String[] getDefiningKeys() {
+        return DEFINING_KEYS;
+    }
+}

Added: 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=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/FeatureRepositoryImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/FeatureRepositoryImpl.java Tue Apr  2 14:53:33 2013
@@ -0,0 +1,53 @@
+/*
+ * 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 java.util.Map;
+
+import org.apache.ace.client.repository.object.FeatureObject;
+import org.apache.ace.client.repository.repository.FeatureRepository;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/**
+ * Implementation class for the FeatureRepository. For 'what it does', see FeatureRepository,
+ * for 'how it works', see ObjectRepositoryImpl.
+ */
+public class FeatureRepositoryImpl extends ObjectRepositoryImpl<FeatureObjectImpl, FeatureObject> implements FeatureRepository {
+    private final static String XML_NODE = "features";
+
+    public FeatureRepositoryImpl(ChangeNotifier notifier) {
+        super(notifier, XML_NODE);
+    }
+
+    @Override
+    FeatureObjectImpl createNewInhabitant(Map<String, String> attributes, Map<String, String> tags) {
+        return new FeatureObjectImpl(attributes, tags, this);
+    }
+
+    @Override
+    FeatureObjectImpl createNewInhabitant(Map<String, String> attributes) {
+        return new FeatureObjectImpl(attributes, this);
+    }
+
+    @Override
+    FeatureObjectImpl createNewInhabitant(HierarchicalStreamReader reader) {
+        return new FeatureObjectImpl(reader, this);
+    }
+}

Added: 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=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ObjectRepositoryImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/ObjectRepositoryImpl.java Tue Apr  2 14:53:33 2013
@@ -0,0 +1,262 @@
+/*
+ * 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 java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.apache.ace.client.repository.ObjectRepository;
+import org.apache.ace.client.repository.RepositoryObject;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+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.
+ */
+abstract class ObjectRepositoryImpl<I extends RepositoryObjectImpl<T>, T extends RepositoryObject> implements ObjectRepository<T>, EventHandler, ChangeNotifier {
+    protected BundleContext m_context; /* injected by dependency manager */
+
+    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 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.
+     */
+    public ObjectRepositoryImpl(ChangeNotifier notifier, String xmlNode) {
+        m_notifier = notifier;
+        m_xmlNode = xmlNode;
+    }
+
+    /**
+     * 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 {
+        if (m_busy) {
+            throw new IllegalStateException("The repository is currently busy, so no new objects can be created.");
+        }
+        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;
+
+        synchronized (m_repo) {
+            if (!m_repo.contains(entity)) {
+                m_repo.add(entity);
+                m_index.put(entity.getDefinition(), entity);
+                result = true;
+            }
+        }
+        if (result) {
+            notifyChanged(entity, RepositoryObject.TOPIC_ADDED_SUFFIX);
+        }
+        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.");
+        }
+        boolean result = false;
+        synchronized (m_repo) {
+            if (m_repo.remove(entity)) {
+                m_index.remove(entity.getDefinition());
+                ((I) entity).setDeleted();
+                result = true;
+            }
+        }
+        if (result) {
+            notifyChanged(entity, RepositoryObject.TOPIC_REMOVED_SUFFIX);
+        }
+    }
+
+    /**
+     * Removes all objects in this repository, without caring for the consistency and
+     * correct event firing.
+     */
+    @SuppressWarnings("unchecked")
+    void removeAll() {
+        synchronized(m_repo) {
+            for (T object : m_repo) {
+                ((I) object).setDeleted();
+            }
+            m_repo.clear();
+        }
+    }
+
+    /**
+     * 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, 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);
+    }
+
+    public List<T> get() {
+        return new ArrayList<T>(m_repo);
+    }
+
+    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);
+            }
+        }
+        return result;
+    }
+
+    public T get(String definition) {
+    	return m_index.get(definition);
+    }
+    
+    Filter createFilter(String filter) throws InvalidSyntaxException {
+        return m_context.createFilter(filter);
+    }
+
+    /**
+     * 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")
+    public void marshal(HierarchicalStreamWriter writer) {
+        writer.startNode(m_xmlNode);
+        for (T inhabitant : m_repo) {
+            ((I) inhabitant).marshal(writer);
+        }
+        writer.endNode();
+    }
+
+    /**
+     * Reads the inhabitants of this repository from an XML stream.
+     * @param reader A reader of the XML representation.
+     */
+    @SuppressWarnings("unchecked")
+    public void unmarshal(HierarchicalStreamReader reader) {
+        try {
+            while (reader.hasMoreChildren()) {
+                reader.moveDown();
+                I newInhabitant = createNewInhabitant(reader);
+                newInhabitant.setBusy(m_busy);
+                add((T) newInhabitant);
+                reader.moveUp();
+            }
+        }
+        catch (Exception ex) {
+            throw new IllegalArgumentException(ex);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    public void handleEvent(Event e) {
+        for (T inhabitant : m_repo) {
+            ((I) inhabitant).handleEvent(e);
+        }
+    }
+
+    /**
+     * 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
+     * @return The new inhabitant.
+     */
+    abstract I createNewInhabitant(Map<String, String> attributes, Map<String, String> tags);
+    /**
+     * Creates a new inhabitant of the repository based on a map of attributes.
+     * @param attributes A map of attributes
+     * @return The new inhabitant.
+     */
+    abstract I createNewInhabitant(Map<String, String> attributes);
+    /**
+     * 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(HierarchicalStreamReader reader);
+
+    public String getXmlNode() {
+        return m_xmlNode;
+    }
+
+    /**
+     * Sets this repository to busy: this will be delegated to all inhabitants.
+     */
+    @SuppressWarnings("unchecked")
+    public void setBusy(boolean busy) {
+        synchronized(m_repo) {
+            m_busy = busy;
+            for (RepositoryObject o : m_repo) {
+                ((I) o).setBusy(busy);
+            }
+        }
+    }
+}

Added: 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=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminImpl.java Tue Apr  2 14:53:33 2013
@@ -0,0 +1,589 @@
+/*
+ * 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 java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.ace.client.repository.ObjectRepository;
+import org.apache.ace.client.repository.RepositoryAdmin;
+import org.apache.ace.client.repository.RepositoryAdminLoginContext;
+import org.apache.ace.client.repository.RepositoryObject;
+import org.apache.ace.client.repository.RepositoryObject.WorkingState;
+import org.apache.ace.client.repository.SessionFactory;
+import org.apache.ace.client.repository.helper.ArtifactHelper;
+import org.apache.ace.client.repository.impl.RepositoryAdminLoginContextImpl.RepositorySetDescriptor;
+import org.apache.ace.client.repository.object.Artifact2FeatureAssociation;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.ace.client.repository.object.DeploymentVersionObject;
+import org.apache.ace.client.repository.object.Distribution2TargetAssociation;
+import org.apache.ace.client.repository.object.DistributionObject;
+import org.apache.ace.client.repository.object.Feature2DistributionAssociation;
+import org.apache.ace.client.repository.object.FeatureObject;
+import org.apache.ace.client.repository.object.TargetObject;
+import org.apache.ace.client.repository.repository.Artifact2FeatureAssociationRepository;
+import org.apache.ace.client.repository.repository.ArtifactRepository;
+import org.apache.ace.client.repository.repository.DeploymentVersionRepository;
+import org.apache.ace.client.repository.repository.Distribution2TargetAssociationRepository;
+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.TargetRepository;
+import org.apache.ace.connectionfactory.ConnectionFactory;
+import org.apache.ace.repository.Repository;
+import org.apache.ace.repository.ext.BackupRepository;
+import org.apache.ace.repository.ext.CachedRepository;
+import org.apache.ace.repository.ext.impl.CachedRepositoryImpl;
+import org.apache.ace.repository.ext.impl.FilebasedBackupRepository;
+import org.apache.ace.repository.ext.impl.RemoteRepository;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+import org.osgi.service.log.LogService;
+import org.osgi.service.prefs.Preferences;
+import org.osgi.service.prefs.PreferencesService;
+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>
+ */
+public class RepositoryAdminImpl implements RepositoryAdmin {
+    private final static String PREFS_LOCAL_FILE_ROOT = "ClientRepositoryAdmin";
+    private final static String PREFS_LOCAL_FILE_LOCATION = "FileLocation";
+    private final static String PREFS_LOCAL_FILE_CURRENT = "current";
+    private final static String PREFS_LOCAL_FILE_BACKUP = "backup";
+
+    /**
+     * 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 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 PreferencesService m_preferences;
+    private volatile LogService m_log;
+
+    private User m_user;
+    private RepositorySet[] m_repositorySets;
+
+    private List<Component[]> m_services;
+    private ArtifactRepositoryImpl m_artifactRepositoryImpl;
+    private FeatureRepositoryImpl m_featureRepositoryImpl;
+    private Artifact2FeatureAssociationRepositoryImpl m_artifact2FeatureAssociationRepositoryImpl;
+    private DistributionRepositoryImpl m_distributionRepositoryImpl;
+    private Feature2DistributionAssociationRepositoryImpl m_feature2DistributionAssociationRepositoryImpl;
+    private TargetRepositoryImpl m_targetRepositoryImpl;
+    private Distribution2TargetAssociationRepositoryImpl m_distribution2TargetAssociationRepositoryImpl;
+    private DeploymentVersionRepositoryImpl m_deploymentVersionRepositoryImpl;
+    private ChangeNotifierManager m_changeNotifierManager;
+
+
+    public RepositoryAdminImpl(String sessionID) {
+        m_sessionID = sessionID;
+        m_sessionProps = new Properties();
+        m_sessionProps.put(SessionFactory.SERVICE_SID, sessionID);
+        m_changeNotifierManager = new ChangeNotifierManager();
+        m_changeNotifier = m_changeNotifierManager.getConfiguredNotifier(RepositoryAdmin.PRIVATE_TOPIC_ROOT, RepositoryAdmin.PUBLIC_TOPIC_ROOT, RepositoryAdmin.TOPIC_ENTITY_ROOT, m_sessionID);
+    }
+
+    public Properties getSessionProps() {
+        return m_sessionProps;
+    }
+
+    /**
+     * 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());
+        }
+    }
+
+    public void stop() {
+        pullRepositories();
+        synchronized (m_lock) {
+            if (loggedIn()) {
+                try {
+                    logout(true);
+                }
+                catch (IOException ioe) {
+                    m_log.log(LogService.LOG_ERROR, "Failed to log out of the repositories.", ioe);
+                }
+            }
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    void initialize(Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> repositories) {
+        m_repositories = repositories;
+    }
+
+    @SuppressWarnings("unchecked")
+    private Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> publishRepositories() {
+        // create the repository objects, if this is the first time this method is called.
+        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));
+        }
+        
+        // first, register the artifact repository manually; it needs some special care.
+        Component artifactRepoService = m_manager.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"));
+        
+        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()
+            .setInterface(EventHandler.class.getName(), topic)
+            .setImplementation(m_artifactRepositoryImpl);
+
+        m_manager.add(artifactRepoService);
+        m_manager.add(artifactHandlerService);
+
+        m_services = new ArrayList<Component[]>();
+        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)}));
+        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(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(TargetRepository.class, m_targetRepositoryImpl, new String[] {}));
+        m_services.add(registerRepository(DeploymentVersionRepository.class, m_deploymentVersionRepositoryImpl, new String[] {}));
+
+        // prepare the results.
+        Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> result = new HashMap<Class<? extends ObjectRepository>, ObjectRepositoryImpl>();
+
+        result.put(ArtifactRepository.class, m_artifactRepositoryImpl);
+        result.put(Artifact2FeatureAssociationRepository.class, m_artifact2FeatureAssociationRepositoryImpl);
+        result.put(FeatureRepository.class, m_featureRepositoryImpl);
+        result.put(Feature2DistributionAssociationRepository.class, m_feature2DistributionAssociationRepositoryImpl);
+        result.put(DistributionRepository.class, m_distributionRepositoryImpl);
+        result.put(Distribution2TargetAssociationRepository.class, m_distribution2TargetAssociationRepositoryImpl);
+        result.put(TargetRepository.class, m_targetRepositoryImpl);
+        result.put(DeploymentVersionRepository.class, m_deploymentVersionRepositoryImpl);
+
+        return result;
+    }
+
+    /**
+     * Pulls all repository services; is used to make sure the repositories go away before the RepositoryAdmin does.
+     */
+    private void pullRepositories() {
+        for (Component[] services : m_services) {
+            for (Component service : services) {
+                m_manager.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()
+            .setInterface(iface.getName(), m_sessionProps)
+            .setImplementation(implementation)
+            .add(m_manager.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()
+            .setInterface(EventHandler.class.getName(), topic)
+            .setImplementation(implementation);
+
+        m_manager.add(repositoryService);
+        m_manager.add(handlerService);
+        return new Component[] {repositoryService, handlerService};
+    }
+
+    /**
+     * Helper method for use in publishRepositories
+     */
+    private static String createPrivateObjectTopic(String entityRoot) {
+        return RepositoryObject.PRIVATE_TOPIC_ROOT + entityRoot + RepositoryObject.TOPIC_ALL_SUFFIX;
+    }
+
+    public void checkout() throws IOException {
+        synchronized (m_lock) {
+            ensureLogin();
+            for (RepositorySet set : m_repositorySets) {
+                set.checkout();
+            }
+            m_changeNotifier.notifyChanged(TOPIC_REFRESH_SUFFIX, null);
+        }
+    }
+
+    public void commit() throws IOException {
+        synchronized (m_lock) {
+            ensureLogin();
+            for (RepositorySet set : m_repositorySets) {
+                set.commit();
+            }
+            m_changeNotifier.notifyChanged(TOPIC_REFRESH_SUFFIX, null);
+        }
+    }
+
+    public void flush() throws IOException {
+        synchronized (m_lock) {
+            ensureLogin();
+            for (RepositorySet set : m_repositorySets) {
+                set.writeLocal();
+                set.savePreferences();
+            }
+            m_changeNotifier.notifyChanged(TOPIC_FLUSHED_SUFFIX, null);
+        }
+    }
+
+    public void revert() throws IOException {
+        synchronized (m_lock) {
+            ensureLogin();
+            for (RepositorySet set : m_repositorySets) {
+                set.revert();
+            }
+            m_changeNotifier.notifyChanged(TOPIC_REFRESH_SUFFIX, null);
+        }
+    }
+
+    public boolean isCurrent() throws IOException {
+        synchronized (m_lock) {
+            ensureLogin();
+            boolean result = true;
+            for (RepositorySet set : m_repositorySets) {
+                    result &= (set.isCurrent() || !set.writeAccess());
+            }
+            return result;
+        }
+    }
+
+    public boolean isModified() {
+        synchronized (m_lock) {
+            ensureLogin();
+            for (RepositorySet set : m_repositorySets) {
+                if (set.isModified()) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+
+    public RepositoryAdminLoginContext createLoginContext(User user) {
+        if (user == null) {
+            throw new IllegalArgumentException("User may not be null.");
+        }
+        return new RepositoryAdminLoginContextImpl(user, m_sessionID);
+    }
+
+    public void login(RepositoryAdminLoginContext context) throws IOException {
+        if (!(context instanceof RepositoryAdminLoginContextImpl)) {
+            throw new IllegalArgumentException("Only the RepositoryAdminLoginContext returned by createLoginContext can be used.");
+        }
+
+        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());
+            login(impl.getUser(), repositorySets);
+        }
+    }
+
+    /**
+     * 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) {
+            if (m_user != null) {
+                throw new IllegalStateException("Another user is logged in.");
+            }
+
+            m_user = user;
+            m_repositorySets = sets;
+            for (RepositorySet set : m_repositorySets) {
+                set.readLocal();
+                set.loadPreferences();
+            }
+        }
+
+        m_changeNotifier.notifyChanged(TOPIC_LOGIN_SUFFIX, null);
+    }
+
+    public void logout(boolean force) throws IOException {
+        IOException exception = null;
+        synchronized (m_lock) {
+            ensureLogin();
+
+            try {
+                flush();
+            }
+            catch (IOException e) {
+                if (!force) {
+                    throw e;
+                }
+                else {
+                    exception = e;
+                }
+            }
+
+            for (RepositorySet set : m_repositorySets) {
+                set.clearRepositories();
+                set.unregisterHandler();
+//                set.deleteLocal();
+            }
+
+            m_user = null;
+//            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();
+    			}
+    		}
+    	}
+    }
+
+    private boolean loggedIn() {
+        return m_user != null;
+    }
+
+    /**
+     * Helper method to make sure a user is logged in.
+     * @throws IllegalStateException
+     */
+    private void ensureLogin() throws IllegalStateException {
+        if (!loggedIn()) {
+            throw new IllegalStateException("This operation requires a user to be logged in.");
+        }
+    }
+
+    /**
+     * 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) {
+                // Do we have an impl for each repository class?
+                if (!m_repositories.containsKey(c)) {
+                    throw new IllegalArgumentException(rsd.toString() + " references repository class " + c.getName() + " for which no implementation is available.");
+                }
+            }
+        }
+
+        RepositorySet[] result = new RepositorySet[descriptors.size()];
+
+        /*
+         * 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++) {
+                impls[j] = m_repositories.get(rsd.m_objectRepositories[j]);
+                topics[j] = impls[j].getTopicAll(true);
+            }
+
+            result[i] = loadRepositorySet(context.getUser(), rsd, impls);
+            result[i].registerHandler(m_context, m_sessionID, topics);
+        }
+
+        return result;
+    }
+
+    /**
+     * Helper method for login.
+     */
+    private Preferences getRepositoryPrefs(Preferences userPrefs, URL location, String customer, String name) {
+        // Note: we can only use the getAuthority part of the URL for indexing, because the full URL will contain
+        // in the protocol part.
+        Preferences repoPref = userPrefs.node(location.getAuthority() + location.getPath());
+        Preferences customerPref = repoPref.node(customer);
+        return customerPref.node(name);
+    }
+
+    /**
+     * Helper method for login.
+     * @throws IOException
+     */
+    private File getFileFromPreferences(Preferences repositoryPrefs, String type) throws IOException {
+        String sessionLocation = PREFS_LOCAL_FILE_LOCATION + m_sessionID;
+        String directory = repositoryPrefs.get(sessionLocation, "");
+
+        if (directory == "") {
+            File directoryFile = null;
+            try {
+                File bundleDataDir = m_context.getDataFile(PREFS_LOCAL_FILE_ROOT);
+                if (!bundleDataDir.isDirectory()) {
+                    if (!bundleDataDir.mkdir()) {
+                        throw new IOException("Error creating the local repository root directory.");
+                    }
+                }
+                directoryFile = File.createTempFile("repo", "", bundleDataDir);
+                if (!directoryFile.delete()) {
+                    throw new IOException("Cannot delete temporary file: " + directoryFile.getName());
+                }
+            }
+            catch (IOException e) {
+                // We cannot create or delete the temp file? Then something is seriously wrong, so rethrow.
+                throw e;
+            }
+            repositoryPrefs.put(sessionLocation, directoryFile.getName());
+            return new File(directoryFile + "-" + type);
+        }
+        else {
+            // Get the given file from that location.
+            return m_context.getDataFile(PREFS_LOCAL_FILE_ROOT + "/" + directory + "-" + type);
+        }
+    }
+
+    /**
+     * Helper method for login.
+     * @throws IOException
+     */
+    private BackupRepository getBackupFromPreferences(Preferences repositoryPrefs) throws IOException {
+        File current = getFileFromPreferences(repositoryPrefs, PREFS_LOCAL_FILE_CURRENT);
+        File backup = getFileFromPreferences(repositoryPrefs, PREFS_LOCAL_FILE_BACKUP);
+        return new FilebasedBackupRepository(current, backup);
+    }
+
+    /**
+     * Helper method for login.
+     * @throws IOException
+     */
+    private CachedRepository getCachedRepositoryFromPreferences(Repository repository, Preferences repositoryPrefs) throws IOException {
+        long mostRecentVersion = repositoryPrefs.getLong("version", CachedRepositoryImpl.UNCOMMITTED_VERSION);
+        return new CachedRepositoryImpl(repository, getBackupFromPreferences(repositoryPrefs), mostRecentVersion);
+    }
+
+    /**
+     * 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
+     * @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()
+            .setImplementation(repo)
+            .add(m_manager.createServiceDependency()
+                .setService(ConnectionFactory.class)
+                .setRequired(true)));
+
+        Preferences prefs = m_preferences.getUserPreferences(user.getName());
+        Preferences repoPrefs = getRepositoryPrefs(prefs, rsd.m_location, rsd.m_customer, rsd.m_name);
+
+        return new RepositorySet(m_changeNotifier, m_log, user, repoPrefs, repos, getCachedRepositoryFromPreferences(repo, repoPrefs), rsd.m_name, rsd.m_writeAccess);
+    }
+
+    public int getNumberWithWorkingState(Class<? extends RepositoryObject> clazz, WorkingState state) {
+        int result = 0;
+        synchronized (m_lock) {
+            for (RepositorySet set : m_repositorySets) {
+                result += set.getNumberWithWorkingState(clazz, state);
+            }
+        }
+        return result;
+    }
+
+    public WorkingState getWorkingState(RepositoryObject object) {
+        WorkingState result = null;
+        synchronized (m_lock) {
+            for (RepositorySet set : m_repositorySets) {
+                result = set.getWorkingState(object);
+                if (result != null) {
+                    break;
+                }
+            }
+        }
+        return (result == null) ? WorkingState.Unchanged : result;
+    }
+
+    public void addArtifactHelper(ServiceReference ref, ArtifactHelper helper) {
+        String mimetype = (String) ref.getProperty(ArtifactHelper.KEY_MIMETYPE);
+        m_artifactRepositoryImpl.addHelper(mimetype, helper);
+    }
+
+    public synchronized void removeArtifactHelper(ServiceReference ref, ArtifactHelper helper) {
+        String mimetype = (String) ref.getProperty(ArtifactHelper.KEY_MIMETYPE);
+        m_artifactRepositoryImpl.removeHelper(mimetype, helper);
+    }
+}

Added: 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=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/RepositoryAdminLoginContextImpl.java Tue Apr  2 14:53:33 2013
@@ -0,0 +1,265 @@
+/*
+ * 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 java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.ace.client.repository.ObjectRepository;
+import org.apache.ace.client.repository.RepositoryAdminLoginContext;
+import org.apache.ace.client.repository.repository.Artifact2FeatureAssociationRepository;
+import org.apache.ace.client.repository.repository.ArtifactRepository;
+import org.apache.ace.client.repository.repository.DeploymentVersionRepository;
+import org.apache.ace.client.repository.repository.Distribution2TargetAssociationRepository;
+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.TargetRepository;
+import org.osgi.service.useradmin.User;
+
+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;
+        m_sessionid = sessionid;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public RepositoryAdminLoginContext add(BaseRepositoryContext<?> repositoryContext) {
+        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>.
+     */
+    public void addDescriptor(RepositorySetDescriptor descriptor) {
+        checkConsistency(descriptor);
+
+        synchronized (m_descriptors) {
+            m_descriptors.add(descriptor);
+        }
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public ShopRepositoryContext createShopRepositoryContext() {
+        return new ShopRepositoryContextImpl();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public TargetRepositoryContext createTargetRepositoryContext() {
+        return new TargetRepositoryContextImpl();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DeploymentRepositoryContext createDeploymentRepositoryContext() {
+        return new DeploymentRepositoryContextImpl();
+    }
+
+    /**
+     * @return a list with all repository set descriptors, never <code>null</code>.
+     */
+    public List<RepositorySetDescriptor> getDescriptors() {
+        List<RepositorySetDescriptor> result;
+        synchronized (m_descriptors) {
+            result = new ArrayList<RepositorySetDescriptor>(m_descriptors);
+        }
+        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;
+    }
+
+    /**
+     * 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>.
+     */
+    private void checkConsistency(RepositorySetDescriptor descriptor) {
+        List<Class<? extends ObjectRepository>> seenClasses = new ArrayList<Class<? extends ObjectRepository>>();
+        List<String> seenNames = new ArrayList<String>();
+
+        // Presumption: initially we start out without any duplication...
+        for (RepositorySetDescriptor rsd : getDescriptors()) {
+            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!");
+            }
+        }
+    }
+
+    /**
+     * 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;
+            m_name = name;
+            m_writeAccess = writeAccess;
+            m_objectRepositories = objectRepositories;
+        }
+
+        @Override
+        public String toString() {
+            return "Repository location " + m_location.toString() + ", customer " + m_customer + ", name " + m_name;
+        }
+    }
+
+    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!");
+            }
+            m_customer = customer;
+            return getThis();
+        }
+
+        public T setLocation(URL location) {
+            if (location == null) {
+                throw new IllegalArgumentException("Location cannot be null!");
+            }
+            m_location = location;
+            return getThis();
+        }
+
+        public T setName(String name) {
+            if (name == null) {
+                throw new IllegalArgumentException("Name cannot be null!");
+            }
+            m_name = name;
+            return getThis();
+        }
+
+        public T setWriteable() {
+            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;
+        }
+    }
+
+    static final class TargetRepositoryContextImpl extends AbstractRepositoryContext<TargetRepositoryContext> implements TargetRepositoryContext {
+        
+        public TargetRepositoryContextImpl() {
+            super(TargetRepository.class, Distribution2TargetAssociationRepository.class);
+        }
+        
+        @Override
+        TargetRepositoryContext getThis() {
+            return this;
+        }
+    }
+
+    static final class DeploymentRepositoryContextImpl extends AbstractRepositoryContext<DeploymentRepositoryContext> implements DeploymentRepositoryContext {
+        
+        public DeploymentRepositoryContextImpl() {
+            super(DeploymentVersionRepository.class);
+        }
+        
+        @Override
+        DeploymentRepositoryContext getThis() {
+            return this;
+        }
+    }
+}