Return-Path: Delivered-To: apmail-incubator-ace-commits-archive@minotaur.apache.org Received: (qmail 40179 invoked from network); 27 Jun 2009 16:15:08 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 27 Jun 2009 16:15:08 -0000 Received: (qmail 95516 invoked by uid 500); 27 Jun 2009 16:15:18 -0000 Delivered-To: apmail-incubator-ace-commits-archive@incubator.apache.org Received: (qmail 95504 invoked by uid 500); 27 Jun 2009 16:15:18 -0000 Mailing-List: contact ace-commits-help@incubator.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ace-dev@incubator.apache.org Delivered-To: mailing list ace-commits@incubator.apache.org Delivered-To: moderator for ace-commits@incubator.apache.org Received: (qmail 83916 invoked by uid 99); 27 Jun 2009 15:54:47 -0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r788992 [10/25] - in /incubator/ace/trunk: gateway/ gateway/src/ gateway/src/net/ gateway/src/net/luminis/ gateway/src/net/luminis/liq/ gateway/src/net/luminis/liq/bootstrap/ gateway/src/net/luminis/liq/bootstrap/multigateway/ gateway/src/n... Date: Sat, 27 Jun 2009 15:53:26 -0000 To: ace-commits@incubator.apache.org From: marrs@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090627155343.9E84823889B9@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/AssociationRepositoryImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/AssociationRepositoryImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/AssociationRepositoryImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/AssociationRepositoryImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,95 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import net.luminis.liq.client.repository.Association; +import net.luminis.liq.client.repository.AssociationRepository; +import net.luminis.liq.client.repository.RepositoryObject; + +/** + * A basic association repository. It cannot be directly instantiated, since some functionality + * is delagated to deriving classes, being + * + *
  • The creation of new inhabitants
  • + *
  • The generation of filter strings based on objects
  • + *
    + * + * @param The left side of the associations which will be stored in this repository. + * @param The right side of the associations which will be stored in this repository. + * @param An implementation of the association from L to R. + * @param The non-generic Association interface that I implements. + */ +public abstract class AssociationRepositoryImpl, T extends Association> extends ObjectRepositoryImpl implements AssociationRepository { + private Object m_lock = new Object(); + + public AssociationRepositoryImpl(ChangeNotifier notifier, String xmlNode) { + super(notifier, xmlNode); + } + + @SuppressWarnings("unchecked") + public T create(String left, int leftCardinality, String right, int rightCardinality) { + synchronized (m_lock) { + T association = null; + try { + Map attributes = new HashMap(); + attributes.put(Association.LEFT_ENDPOINT, left); + attributes.put(Association.RIGHT_ENDPOINT, right); + attributes.put(Association.LEFT_CARDINALITY, "" + leftCardinality); + attributes.put(Association.RIGHT_CARDINALITY, "" + rightCardinality); + association = (T) createNewInhabitant(attributes); + add(association); + } + catch (Exception e) { + // We have not been able to instantiate our constructor. Not much to do about that. + e.printStackTrace(); + } + return association; + } + } + + public T create(String left, String right) { + return create(left, Integer.MAX_VALUE, right, Integer.MAX_VALUE); + } + + public T create(L left, Map leftProps, R right, Map rightProps) { + return create(left.getAssociationFilter(leftProps), left.getCardinality(leftProps), + right.getAssociationFilter(rightProps), right.getCardinality(rightProps)); + } + + public T create(L left, R right) { + return create(left, null, right, null); + } + + public T create(List left, List right) { + if ((left == null) || left.isEmpty()) { + throw new IllegalArgumentException("The left side of the association cannot be empty."); + } + if ((right == null) || right.isEmpty()) { + throw new IllegalArgumentException("The right side of the association cannot be empty."); + } + + StringBuilder leftFilter = new StringBuilder("(|"); + for (L l : left) { + leftFilter.append(l.getAssociationFilter(null)); + } + leftFilter.append(")"); + + StringBuilder rightFilter = new StringBuilder("(|"); + for (R r : right) { + rightFilter.append(r.getAssociationFilter(null)); + } + rightFilter.append(")"); + + return create(leftFilter.toString(), Integer.MAX_VALUE, rightFilter.toString(), Integer.MAX_VALUE); + } + + @Override + public void remove(T entity) { + synchronized (m_lock) { + super.remove(entity); + entity.remove(); + } + } +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ChangeNotifier.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ChangeNotifier.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ChangeNotifier.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ChangeNotifier.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,37 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.Properties; + +/** + * This interface defines a mechanism for notifying both internally interested parties, and + * external listeners, of changes to the a given 'inhabitant' of the model. + */ +public interface ChangeNotifier { + /** + * Notifies both internal and external listeners of a change to some object. + * @param topic A topic, as defined in the interface definitions of the various objects. + * Note that this is not a full topic, but merely the 'last part', such as "ADDED"; + * this allows the ChangeNotifier to generate internal or external topics. + * @param props Properties to pack with the event. May be null. + */ + public void notifyChanged(String topic, Properties props); + + /** + * Notifies both internal and external listeners of a change to some object. + * @param topic A topic, as defined in the interface definitions of the various objects. + * Note that this is not a full topic, but merely the 'last part', such as "ADDED"; + * this allows the ChangeNotifier to generate internal or external topics. + * @param props Properties to pack with the event. May be null. + * @param internalOnly Indicates this event is only for internal use, and the external + * events should not be sent. + */ + public void notifyChanged(String topic, Properties props, boolean internalOnly); + + /** + * Gets a topic name which allows subscription to all topics that this ChangeNotifier can send. + * @param publicTopic Indicates whether we are interested in the public (true) or the + * private topic (false). + * @return A topic name. + */ + String getTopicAll(boolean publicTopic); +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ChangeNotifierImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ChangeNotifierImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ChangeNotifierImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ChangeNotifierImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,62 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.Properties; + +import org.osgi.service.event.Event; +import org.osgi.service.event.EventAdmin; + +/** + * ChangeNotifierImpl provides a basic implementation of a ChangeNotifier, intended to be used + * by classes related to the RepositoryAdmin.
    + *
    + * Topics are built up in the following fashion: + *
      + *
    • ...TopicRoot All topics start with a TopicRoot, which is the same for all related classes, and ends with a "/". + * There can be internal and external topics, hence two TopicRoot parameters in the constructor.
    • + *
    • entityRoot This is followed by a class-specific root, usually consisting of the classname with an added "/".
    • + *
    • Finally, for each call to notifyChanged, a topic can be specified, which is something like + * "CHANGED" or "ADDED".
    • + *
    + */ +public class ChangeNotifierImpl implements ChangeNotifier { + + private final EventAdmin m_eventAdmin; + private final String m_privateTopicRoot; + private final String m_publicTopicRoot; + private final String m_entityRoot; + + /** + * Creates a new ChangeNotifierImpl. + * @param eventAdmin An EventAdmin to send events to. + * @param privateTopicRoot The root of all private topics; see TopicRoot in the description of this class. + * @param publicTopicRoot The root of all public topics; see TopicRoot in the description of this class. + * @param entityRoot A class-specific root for the class which will use this ChangeNotifierImpl. + */ + ChangeNotifierImpl(EventAdmin eventAdmin, String privateTopicRoot, String publicTopicRoot, String entityRoot) { + m_eventAdmin = eventAdmin; + m_privateTopicRoot = privateTopicRoot; + m_publicTopicRoot = publicTopicRoot; + m_entityRoot = entityRoot; + } + + public void notifyChanged(String topic, Properties props, boolean internalOnly) { + m_eventAdmin.sendEvent(new Event(m_privateTopicRoot + m_entityRoot + topic, props)); + if (!internalOnly) { + m_eventAdmin.postEvent(new Event(m_publicTopicRoot + m_entityRoot + topic, props)); + } + } + + public void notifyChanged(String topic, Properties props) { + notifyChanged(topic, props, false); + } + + public String getTopicAll(boolean publicTopic) { + if (publicTopic) { + return m_publicTopicRoot + m_entityRoot + "*"; + } + else { + return m_privateTopicRoot + m_entityRoot + "*"; + } + } + +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ChangeNotifierManager.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ChangeNotifierManager.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ChangeNotifierManager.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ChangeNotifierManager.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,34 @@ +package net.luminis.liq.client.repository.impl; + +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. + */ +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. + * @return The newly configured ChangeNotifier. + */ + public ChangeNotifier getConfiguredNotifier(String privateTopicRoot, String publicTopicRoot, String entityRoot) { + return new ChangeNotifierImpl(this, privateTopicRoot, publicTopicRoot, entityRoot); + } + + public void postEvent(Event event) { + m_eventAdmin.postEvent(event); + } + + public void sendEvent(Event event) { + m_eventAdmin.sendEvent(event); + } + +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/DeploymentArtifactImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/DeploymentArtifactImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/DeploymentArtifactImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/DeploymentArtifactImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,142 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.HashMap; +import java.util.Map; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; + +import net.luminis.liq.client.repository.object.DeploymentArtifact; + +/** + * This class is a basic implementation of DeploymentArtifact, with additional facilities + * for serializing this artifacts with its directives. + */ +public class DeploymentArtifactImpl implements DeploymentArtifact { + private final static String XML_NODE = "deploymentArtifact"; + private final static String XML_NODE_URL = "url"; + private final static String XML_NODE_DIRECTIVES = "directives"; + private final String m_url; + private final Map m_directives = new HashMap(); + + /** + * Creates a new DeploymentArtifactImpl. + * @param url The url to the new artifact, as a string; should not be null; + */ + public DeploymentArtifactImpl(String url) { + if (url == null) { + throw new IllegalArgumentException("The url should not be null."); + } + m_url = url; + } + + /** + * Creates a new DeploymentArtifactImpl by deserializing it from an XML stream. + * @param reader A stream reader for the XML representation of this object. + */ + public DeploymentArtifactImpl(HierarchicalStreamReader reader) { + reader.moveDown(); + m_url = reader.getValue(); + reader.moveUp(); + + reader.moveDown(); + while (reader.hasMoreChildren()) { + reader.moveDown(); + m_directives.put(reader.getNodeName(), reader.getValue()); + reader.moveUp(); + } + reader.moveUp(); + + } + + /** + * Writes this object to an XML stream. + */ + public void marshal(HierarchicalStreamWriter writer) { + writer.startNode(XML_NODE); + + writer.startNode(XML_NODE_URL); + writer.setValue(m_url); + writer.endNode(); // url node + + writer.startNode(XML_NODE_DIRECTIVES); + for (Map.Entry entry : m_directives.entrySet()) { + writer.startNode(entry.getKey()); + assert (entry.getValue() != null); + writer.setValue(entry.getValue()); + writer.endNode(); // this directive entry + } + writer.endNode(); // directives node + + writer.endNode(); // deploymentartifact node + } + + /** + * Adds a directive to this object. + */ + void addDirective(String key, String value) { + if ((key == null) || (value == null)) { + throw new IllegalArgumentException("Neither the key nor the value should be null."); + } + m_directives.put(key, value); + } + + public String getDirective(String key) { + return m_directives.get(key); + } + + public String[] getKeys() { + return m_directives.keySet().toArray(new String[m_directives.size()]); + } + + public String getUrl() { + return m_url; + } + + @Override + public boolean equals(Object other) { + if ((other == null) || !getClass().equals(other.getClass())) { + return false; + } + + DeploymentArtifactImpl dai = (DeploymentArtifactImpl) other; + + boolean result = true; + + result &= getUrl().equals(dai.getUrl()); + + result &= (getKeys().length == dai.getKeys().length); + + for (String key : getKeys()) { + result &= getDirective(key).equals(dai.getDirective(key)); + } + + return result; + } + + @Override + public int hashCode() { + int result = getUrl().hashCode(); + + for (String key : getKeys()) { + result ^= getDirective(key).hashCode(); + } + + return result; + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(getUrl() + " [ "); + for (String key : getKeys()) { + result.append(key) + .append(": ") + .append(getDirective(key)) + .append(" "); + } + result.append("]"); + + return result.toString(); + } + +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/DeploymentVersionObjectImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/DeploymentVersionObjectImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/DeploymentVersionObjectImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/DeploymentVersionObjectImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,99 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import net.luminis.liq.client.repository.object.DeploymentArtifact; +import net.luminis.liq.client.repository.object.DeploymentVersionObject; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +import com.thoughtworks.xstream.io.HierarchicalStreamWriter; + +/** + * Implementation class for the DeploymentVersionObject. For 'what it does', see DeploymentVersionObject, + * for 'how it works', see RepositoryObjectImpl. + */ +public class DeploymentVersionObjectImpl extends RepositoryObjectImpl implements DeploymentVersionObject { + private final static String XML_NODE = "deploymentversion"; + private final static String ARTIFACTS_XML_NODE = "artifacts"; + private DeploymentArtifact[] m_deploymentArtifacts; + + /** + * Creates a new DeploymentVersionObjectImpl. + * @param attributes A map of attributes; must include KEY_GATEWAYID, KEY_VERSION. + * @param deploymentArtifacts A (possibly empty) array of DeploymentArtifacts. + * @param notifier A change notifier to be used by this object. + */ + DeploymentVersionObjectImpl(Map attributes, ChangeNotifier notifier) { + super(checkAttributes(attributes, new String[] {KEY_GATEWAYID, KEY_VERSION}, new boolean[] {false, false}), notifier, XML_NODE); + } + + DeploymentVersionObjectImpl(Map attributes, Map tags, ChangeNotifier notifier) { + super(checkAttributes(attributes, new String[] {KEY_GATEWAYID, KEY_VERSION}, new boolean[] {false, false}), tags, notifier, XML_NODE); + } + + DeploymentVersionObjectImpl(HierarchicalStreamReader reader, ChangeNotifier notifier) { + super(reader, notifier, XML_NODE); + } + + synchronized void setDeploymentArtifacts(DeploymentArtifact[] deploymentArtifacts) { + if (m_deploymentArtifacts != null) { + throw new IllegalStateException("Deployment artifacts are already set; this can only be done once."); + } + if (deploymentArtifacts == null) { + throw new IllegalArgumentException("The argument should not be null."); + } + else { + m_deploymentArtifacts = deploymentArtifacts; + } + } + + @Override + protected void readCustom(HierarchicalStreamReader reader) { + List result = new ArrayList(); + reader.moveDown(); + while (reader.hasMoreChildren()) { + reader.moveDown(); + DeploymentArtifactImpl deploymentArtifactImpl = new DeploymentArtifactImpl(reader); + result.add(deploymentArtifactImpl); + reader.moveUp(); + } + setDeploymentArtifacts(result.toArray(new DeploymentArtifact[result.size()])); + reader.moveUp(); + } + + @Override + protected synchronized void writeCustom(HierarchicalStreamWriter writer) { + if (m_deploymentArtifacts == 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) { + ((DeploymentArtifactImpl) da).marshal(writer); + } + writer.endNode(); + } + + private static String[] DEFINING_KEYS = new String[] {KEY_GATEWAYID, KEY_VERSION}; + @Override + String[] getDefiningKeys() { + return DEFINING_KEYS; + } + + public String getGatewayID() { + return getAttribute(KEY_GATEWAYID); + } + + 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(); + } +} + Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/DeploymentVersionRepositoryImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/DeploymentVersionRepositoryImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/DeploymentVersionRepositoryImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/DeploymentVersionRepositoryImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,106 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; + +import net.luminis.liq.client.repository.RepositoryUtil; +import net.luminis.liq.client.repository.object.DeploymentArtifact; +import net.luminis.liq.client.repository.object.DeploymentVersionObject; +import net.luminis.liq.client.repository.repository.DeploymentVersionRepository; + +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.Version; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; + +/** + * Implementation class for the GatewayRepository. For 'what it does', see GatewayRepository, + * 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 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. + */ + private DeploymentArtifact[] m_tempDeploymentArtifacts; + private final Object m_creationLock = new Object(); + + @Override + DeploymentVersionObjectImpl createNewInhabitant(Map attributes) { + synchronized (m_creationLock) { + DeploymentVersionObjectImpl result = new DeploymentVersionObjectImpl(attributes, this); + result.setDeploymentArtifacts(m_tempDeploymentArtifacts); + m_tempDeploymentArtifacts = null; + return result; + } + } + + @Override + DeploymentVersionObjectImpl createNewInhabitant(Map attributes, Map tags) { + synchronized (m_creationLock) { + DeploymentVersionObjectImpl result = new DeploymentVersionObjectImpl(attributes, tags, this); + result.setDeploymentArtifacts(m_tempDeploymentArtifacts); + m_tempDeploymentArtifacts = null; + return result; + } + } + + @Override + DeploymentVersionObjectImpl createNewInhabitant(HierarchicalStreamReader reader) { + return new DeploymentVersionObjectImpl(reader, this); + } + + public DeploymentVersionObject create(Map attributes, Map tags, DeploymentArtifact[] artifacts) { + synchronized (m_creationLock) { + m_tempDeploymentArtifacts = artifacts; + return super.create(attributes, tags); + } + } + + private Comparator versionComparator = new Comparator() { + public int compare(DeploymentVersionObject o1, DeploymentVersionObject o2) { + return Version.parseVersion(o1.getVersion()).compareTo(Version.parseVersion(o2.getVersion())); + } + }; + + public List getDeploymentVersions(String gatewayID) { + List result = null; + try { + result = get(createFilter("(" + DeploymentVersionObject.KEY_GATEWAYID + "=" + RepositoryUtil.escapeFilterValue(gatewayID) + ")")); + Collections.sort(result, versionComparator); + } + catch (InvalidSyntaxException e) { + // Too bad, probably an illegal gatewayID. + result = new ArrayList(); + } + return result; + } + + public DeploymentVersionObject getMostRecentDeploymentVersion(String gatewayID) { + List versions = getDeploymentVersions(gatewayID); + DeploymentVersionObject result = null; + if ((versions != null) && (versions.size() > 0)) { + result = versions.get(versions.size() - 1); + } + return result; + } + + public DeploymentArtifact createDeploymentArtifact(String url, Map directives) { + DeploymentArtifactImpl result = new DeploymentArtifactImpl(url); + for (Map.Entry entry : directives.entrySet()) { + result.addDirective(entry.getKey(), entry.getValue()); + } + return result; + } +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GatewayObjectImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GatewayObjectImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GatewayObjectImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GatewayObjectImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,66 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.List; +import java.util.Map; + +import net.luminis.liq.client.repository.object.GatewayObject; +import net.luminis.liq.client.repository.object.License2GatewayAssociation; +import net.luminis.liq.client.repository.object.LicenseObject; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; + +/** + * Implementation class for the GatewayObject. For 'what it does', see GatewayObject, + * for 'how it works', see RepositoryObjectImpl. + */ +public class GatewayObjectImpl extends RepositoryObjectImpl implements GatewayObject { + private final static String XML_NODE = "gateway"; + + GatewayObjectImpl(Map attributes, ChangeNotifier notifier) { + super(checkAttributes(attributes, KEY_ID), notifier, XML_NODE); + } + + GatewayObjectImpl(Map attributes, Map tags, ChangeNotifier notifier) { + super(checkAttributes(attributes, KEY_ID), tags, notifier, XML_NODE); + } + + GatewayObjectImpl(HierarchicalStreamReader reader, ChangeNotifier notifier) { + super(reader, notifier, XML_NODE); + if(getAttribute(KEY_AUTO_APPROVE) == null) { + addAttribute(KEY_AUTO_APPROVE, String.valueOf(false)); + } + } + + public List getLicenses() { + return getAssociations(LicenseObject.class); + } + + public String getID() { + return getAttribute(KEY_ID); + } + + public List getAssociationsWith(LicenseObject license) { + return getAssociationsWith(license, LicenseObject.class, License2GatewayAssociation.class); + } + + private static String[] DEFINING_KEYS = new String[] {KEY_ID}; + @Override + String[] getDefiningKeys() { + return DEFINING_KEYS; + } + + public boolean getAutoApprove() { + String value = getAttribute(KEY_AUTO_APPROVE); + if (value == null) { + return false; + } + else { + return Boolean.parseBoolean(value); + } + } + + public void setAutoApprove(boolean approve) { + addAttribute(KEY_AUTO_APPROVE, String.valueOf(approve)); + + } +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GatewayRepositoryImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GatewayRepositoryImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GatewayRepositoryImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GatewayRepositoryImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,36 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.Map; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; + +import net.luminis.liq.client.repository.object.GatewayObject; +import net.luminis.liq.client.repository.repository.GatewayRepository; + +/** + * Implementation class for the GatewayRepository. For 'what it does', see GatewayRepository, + * for 'how it works', see ObjectRepositoryImpl. + */ +public class GatewayRepositoryImpl extends ObjectRepositoryImpl implements GatewayRepository { + private final static String XML_NODE = "gateways"; + + public GatewayRepositoryImpl(ChangeNotifier notifier) { + super(notifier, XML_NODE); + } + + @Override + GatewayObjectImpl createNewInhabitant(Map attributes, Map tags) { + return new GatewayObjectImpl(attributes, tags, this); + } + + @Override + GatewayObjectImpl createNewInhabitant(Map attributes) { + return new GatewayObjectImpl(attributes, this); + } + + @Override + GatewayObjectImpl createNewInhabitant(HierarchicalStreamReader reader) { + return new GatewayObjectImpl(reader, this); + } + +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Group2LicenseAssociationImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Group2LicenseAssociationImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Group2LicenseAssociationImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Group2LicenseAssociationImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,30 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.Map; + +import net.luminis.liq.client.repository.object.Group2LicenseAssociation; +import net.luminis.liq.client.repository.object.GroupObject; +import net.luminis.liq.client.repository.object.LicenseObject; + +import org.osgi.framework.InvalidSyntaxException; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; + +/** + * Implementation class for the Group2LicenseAssociation. For 'what it does', see Group2LicenseAssociation, + * for 'how it works', see AssociationImpl. + */ +public class Group2LicenseAssociationImpl extends AssociationImpl implements Group2LicenseAssociation { + private final static String XML_NODE = "group2license"; + + public Group2LicenseAssociationImpl(Map attributes, ChangeNotifier notifier, GroupRepositoryImpl groupRepository, LicenseRepositoryImpl licenseRepository) throws InvalidSyntaxException { + super(attributes, notifier, GroupObject.class, LicenseObject.class, groupRepository, licenseRepository, XML_NODE); + } + public Group2LicenseAssociationImpl(Map attributes, Map tags, ChangeNotifier notifier, GroupRepositoryImpl groupRepository, LicenseRepositoryImpl licenseRepository) throws InvalidSyntaxException { + super(attributes, tags, notifier, GroupObject.class, LicenseObject.class, groupRepository, licenseRepository, XML_NODE); + } + public Group2LicenseAssociationImpl(HierarchicalStreamReader reader, ChangeNotifier notifier, GroupRepositoryImpl groupRepository, LicenseRepositoryImpl licenseRepository) throws InvalidSyntaxException { + super(reader, notifier, GroupObject.class, LicenseObject.class, null, null, groupRepository, licenseRepository, XML_NODE); + } + +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Group2LicenseAssociationRepositoryImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Group2LicenseAssociationRepositoryImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Group2LicenseAssociationRepositoryImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Group2LicenseAssociationRepositoryImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,60 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.Map; + +import net.luminis.liq.client.repository.object.Group2LicenseAssociation; +import net.luminis.liq.client.repository.object.GroupObject; +import net.luminis.liq.client.repository.object.LicenseObject; +import net.luminis.liq.client.repository.repository.Group2LicenseAssociationRepository; + +import org.osgi.framework.InvalidSyntaxException; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; + +/** + * Implementation class for the Group2LicenseAssociationRepository. For 'what it does', see Group2LicenseAssociationRepository, + * for 'how it works', see AssociationRepositoryImpl. + */ +public class Group2LicenseAssociationRepositoryImpl extends AssociationRepositoryImpl implements Group2LicenseAssociationRepository { + private final static String XML_NODE = "groups2licenses"; + + private final GroupRepositoryImpl m_groupRepository; + private final LicenseRepositoryImpl m_licenseRepository; + + public Group2LicenseAssociationRepositoryImpl(GroupRepositoryImpl groupRepository, LicenseRepositoryImpl licenseRepository, ChangeNotifier notifier) { + super(notifier, XML_NODE); + m_groupRepository = groupRepository; + m_licenseRepository = licenseRepository; + } + + @Override + Group2LicenseAssociationImpl createNewInhabitant(Map attributes) { + try { + return new Group2LicenseAssociationImpl(attributes, this, m_groupRepository, m_licenseRepository); + } + catch (InvalidSyntaxException e) { + throw new IllegalArgumentException("Unable to create association: ", e); + } + } + + @Override + Group2LicenseAssociationImpl createNewInhabitant(Map attributes, Map tags) { + try { + return new Group2LicenseAssociationImpl(attributes, tags, this, m_groupRepository, m_licenseRepository); + } + catch (InvalidSyntaxException e) { + throw new IllegalArgumentException("Unable to create association: ", e); + } + } + + @Override + Group2LicenseAssociationImpl createNewInhabitant(HierarchicalStreamReader reader) { + try { + return new Group2LicenseAssociationImpl(reader, this, m_groupRepository, m_licenseRepository); + } + catch (InvalidSyntaxException e) { + throw new IllegalArgumentException("Unable to create association: ", e); + } + } + +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GroupObjectImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GroupObjectImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GroupObjectImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GroupObjectImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,71 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.List; +import java.util.Map; + +import net.luminis.liq.client.repository.object.Artifact2GroupAssociation; +import net.luminis.liq.client.repository.object.ArtifactObject; +import net.luminis.liq.client.repository.object.Group2LicenseAssociation; +import net.luminis.liq.client.repository.object.GroupObject; +import net.luminis.liq.client.repository.object.LicenseObject; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; + +/** + * Implementation class for the GroupObject. For 'what it does', see GroupObject, + * for 'how it works', see RepositoryObjectImpl. + */ +public class GroupObjectImpl extends RepositoryObjectImpl implements GroupObject { + private final static String XML_NODE = "group"; + + GroupObjectImpl(Map attributes, Map tags, ChangeNotifier notifier) { + super(checkAttributes(attributes, KEY_NAME), tags, notifier, XML_NODE); + } + + GroupObjectImpl(Map attributes, ChangeNotifier notifier) { + super(checkAttributes(attributes, KEY_NAME), notifier, XML_NODE); + } + + GroupObjectImpl(HierarchicalStreamReader reader, ChangeNotifier notifier) { + super(reader, notifier, XML_NODE); + } + + public List getArtifacts() { + return getAssociations(ArtifactObject.class); + } + + public List getLicenses() { + return getAssociations(LicenseObject.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 getAssociationsWith(ArtifactObject artifact) { + return getAssociationsWith(artifact, ArtifactObject.class, Artifact2GroupAssociation.class); + } + + public List getAssociationsWith(LicenseObject license) { + return getAssociationsWith(license, LicenseObject.class, Group2LicenseAssociation.class); + } + + private static String[] DEFINING_KEYS = new String[] {KEY_NAME}; + @Override + String[] getDefiningKeys() { + return DEFINING_KEYS; + } + +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GroupRepositoryImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GroupRepositoryImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GroupRepositoryImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/GroupRepositoryImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,36 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.Map; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; + +import net.luminis.liq.client.repository.object.GroupObject; +import net.luminis.liq.client.repository.repository.GroupRepository; + +/** + * Implementation class for the GroupRepository. For 'what it does', see GroupRepository, + * for 'how it works', see ObjectRepositoryImpl. + */ +public class GroupRepositoryImpl extends ObjectRepositoryImpl implements GroupRepository { + private final static String XML_NODE = "groups"; + + public GroupRepositoryImpl(ChangeNotifier notifier) { + super(notifier, XML_NODE); + } + + @Override + GroupObjectImpl createNewInhabitant(Map attributes, Map tags) { + return new GroupObjectImpl(attributes, tags, this); + } + + @Override + GroupObjectImpl createNewInhabitant(Map attributes) { + return new GroupObjectImpl(attributes, this); + } + + @Override + GroupObjectImpl createNewInhabitant(HierarchicalStreamReader reader) { + return new GroupObjectImpl(reader, this); + } + +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/License2GatewayAssociationImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/License2GatewayAssociationImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/License2GatewayAssociationImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/License2GatewayAssociationImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,30 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.Map; + +import net.luminis.liq.client.repository.object.GatewayObject; +import net.luminis.liq.client.repository.object.License2GatewayAssociation; +import net.luminis.liq.client.repository.object.LicenseObject; + +import org.osgi.framework.InvalidSyntaxException; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; + +/** + * Implementation class for the License2GatewayAssociation. For 'what it does', see License2GatewayAssociation, + * for 'how it works', see AssociationImpl. + */ +public class License2GatewayAssociationImpl extends AssociationImpl implements License2GatewayAssociation { + private final static String XML_NODE = "license2gateway"; + + public License2GatewayAssociationImpl(Map attributes, ChangeNotifier notifier, LicenseRepositoryImpl licenseRepository, GatewayRepositoryImpl gatewayRepository) throws InvalidSyntaxException { + super(attributes, notifier, LicenseObject.class, GatewayObject.class, licenseRepository, gatewayRepository, XML_NODE); + } + public License2GatewayAssociationImpl(Map attributes, Map tags, ChangeNotifier notifier, LicenseRepositoryImpl licenseRepository, GatewayRepositoryImpl gatewayRepository) throws InvalidSyntaxException { + super(attributes, tags, notifier, LicenseObject.class, GatewayObject.class, licenseRepository, gatewayRepository, XML_NODE); + } + public License2GatewayAssociationImpl(HierarchicalStreamReader reader, ChangeNotifier notifier, LicenseRepositoryImpl licenseRepository, GatewayRepositoryImpl gatewayRepository) throws InvalidSyntaxException { + super(reader, notifier, LicenseObject.class, GatewayObject.class, null, null, licenseRepository, gatewayRepository, XML_NODE); + } + +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/License2GatewayAssociationRepositoryImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/License2GatewayAssociationRepositoryImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/License2GatewayAssociationRepositoryImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/License2GatewayAssociationRepositoryImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,71 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.Map; + +import net.luminis.liq.client.repository.object.GatewayObject; +import net.luminis.liq.client.repository.object.License2GatewayAssociation; +import net.luminis.liq.client.repository.object.LicenseObject; +import net.luminis.liq.client.repository.repository.License2GatewayAssociationRepository; + +import org.osgi.framework.InvalidSyntaxException; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; +/** + * Implementation class for the License2GatewayAssociationRepository. For 'what it does', see License2GatewayAssociationRepository, + * for 'how it works', see AssociationRepositoryImpl. + */ + +public class License2GatewayAssociationRepositoryImpl extends AssociationRepositoryImpl implements License2GatewayAssociationRepository { + private final static String XML_NODE = "licenses2gateways"; + + private final LicenseRepositoryImpl m_licenseRepository; + private final GatewayRepositoryImpl m_gatewayRepository; + + public License2GatewayAssociationRepositoryImpl(LicenseRepositoryImpl licenseRepository, GatewayRepositoryImpl gatewayRepository, ChangeNotifier notifier) { + super(notifier, XML_NODE); + m_licenseRepository = licenseRepository; + m_gatewayRepository = gatewayRepository; + } + + @Override + License2GatewayAssociationImpl createNewInhabitant(Map attributes) { + try { + return new License2GatewayAssociationImpl(attributes, this, m_licenseRepository, m_gatewayRepository); + } + catch (InvalidSyntaxException e) { + throw new IllegalArgumentException("Unable to create association: ", e); + } + } + + @Override + License2GatewayAssociationImpl createNewInhabitant(Map attributes, Map tags) { + try { + return new License2GatewayAssociationImpl(attributes, tags, this, m_licenseRepository, m_gatewayRepository); + } + catch (InvalidSyntaxException e) { + throw new IllegalArgumentException("Unable to create association: ", e); + } + } + + @Override + License2GatewayAssociationImpl createNewInhabitant(HierarchicalStreamReader reader) { + try { + return new License2GatewayAssociationImpl(reader, this, m_licenseRepository, m_gatewayRepository); + } + catch (InvalidSyntaxException e) { + throw new IllegalArgumentException("Unable to create association: ", e); + } + } + + public License2GatewayAssociation createLicense2GatewayFilter(LicenseObject license, String gatewayFilter) { + try { + m_gatewayRepository.createFilter(gatewayFilter); + } + catch (InvalidSyntaxException ise) { + throw new IllegalArgumentException("Gateway filter '" + gatewayFilter + "' cannot be parsed into a valid Filter.", ise); + } + + return create(license.getAssociationFilter(null), gatewayFilter); + } + +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/LicenseObjectImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/LicenseObjectImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/LicenseObjectImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/LicenseObjectImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,71 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.List; +import java.util.Map; + +import net.luminis.liq.client.repository.object.GatewayObject; +import net.luminis.liq.client.repository.object.Group2LicenseAssociation; +import net.luminis.liq.client.repository.object.GroupObject; +import net.luminis.liq.client.repository.object.License2GatewayAssociation; +import net.luminis.liq.client.repository.object.LicenseObject; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; + +/** + * Implementation class for the LicenseObject. For 'what it does', see LicenseObject, + * for 'how it works', see RepositoryObjectImpl. + */ +public class LicenseObjectImpl extends RepositoryObjectImpl implements LicenseObject { + private final static String XML_NODE = "license"; + + LicenseObjectImpl(Map attributes, Map tags, ChangeNotifier notifier) { + super(checkAttributes(attributes, KEY_NAME), tags, notifier, XML_NODE); + } + + LicenseObjectImpl(Map attributes, ChangeNotifier notifier) { + super(checkAttributes(attributes, KEY_NAME), notifier, XML_NODE); + } + + LicenseObjectImpl(HierarchicalStreamReader reader, ChangeNotifier notifier) { + super(reader, notifier, XML_NODE); + } + + public List getGateways() { + return getAssociations(GatewayObject.class); + } + + public List getGroups() { + return getAssociations(GroupObject.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 getAssociationsWith(GroupObject group) { + return getAssociationsWith(group, GroupObject.class, Group2LicenseAssociation.class); + } + + public List getAssociationsWith(GatewayObject gateway) { + return getAssociationsWith(gateway, GatewayObject.class, License2GatewayAssociation.class); + } + + private static String[] DEFINING_KEYS = new String[] {KEY_NAME}; + @Override + String[] getDefiningKeys() { + return DEFINING_KEYS; + } + +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/LicenseRepositoryImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/LicenseRepositoryImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/LicenseRepositoryImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/LicenseRepositoryImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,36 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.Map; + +import net.luminis.liq.client.repository.object.LicenseObject; +import net.luminis.liq.client.repository.repository.LicenseRepository; + +import com.thoughtworks.xstream.io.HierarchicalStreamReader; + +/** + * Implementation class for the LicenseRepository. For 'what it does', see LicenseRepository, + * for 'how it works', see ObjectRepositoryImpl. + */ +public class LicenseRepositoryImpl extends ObjectRepositoryImpl implements LicenseRepository { + private final static String XML_NODE = "licenses"; + + public LicenseRepositoryImpl(ChangeNotifier notifier) { + super(notifier, XML_NODE); + } + + @Override + LicenseObjectImpl createNewInhabitant(Map attributes, Map tags) { + return new LicenseObjectImpl(attributes, tags, this); + } + + @Override + LicenseObjectImpl createNewInhabitant(Map attributes) { + return new LicenseObjectImpl(attributes, this); + } + + @Override + LicenseObjectImpl createNewInhabitant(HierarchicalStreamReader reader) { + return new LicenseObjectImpl(reader, this); + } + +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ObjectRepositoryImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ObjectRepositoryImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ObjectRepositoryImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ObjectRepositoryImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,238 @@ +package net.luminis.liq.client.repository.impl; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.CopyOnWriteArrayList; + +import net.luminis.liq.client.repository.ObjectRepository; +import net.luminis.liq.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 An implementation type of the repository object that this repository will store. + * @param The non-generic interface that I implements. + */ +abstract class ObjectRepositoryImpl, T extends RepositoryObject> implements ObjectRepository, EventHandler, ChangeNotifier { + protected BundleContext m_context; /* injected by dependency manager */ + + private final List m_repo = new CopyOnWriteArrayList(); + 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 attributes, Map 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(); + } + + /** + * 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); + 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)) { + ((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 get() { + return new ArrayList(m_repo); + } + + public List get(Filter filter) { + List result = new ArrayList(); + for (T entry : m_repo) { + if (filter.match(entry.getDictionary())) { + result.add(entry); + } + } + return result; + } + + 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 attributes, Map 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 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: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositoryAdminImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositoryAdminImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositoryAdminImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositoryAdminImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,372 @@ +package net.luminis.liq.client.repository.impl; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.util.Map; + +import net.luminis.liq.client.repository.ObjectRepository; +import net.luminis.liq.client.repository.RepositoryAdmin; +import net.luminis.liq.client.repository.RepositoryAdminLoginContext; +import net.luminis.liq.client.repository.RepositoryObject; +import net.luminis.liq.client.repository.RepositoryObject.WorkingState; +import net.luminis.liq.client.repository.impl.RepositoryAdminLoginContextImpl.RepositorySetDescriptor; +import net.luminis.liq.client.repository.repository.ArtifactRepository; +import net.luminis.liq.repository.Repository; +import net.luminis.liq.repository.ext.BackupRepository; +import net.luminis.liq.repository.ext.CachedRepository; +import net.luminis.liq.repository.impl.CachedRepositoryImpl; +import net.luminis.liq.repository.impl.FilebasedBackupRepository; +import net.luminis.liq.repository.impl.RemoteRepository; + +import org.osgi.framework.BundleContext; +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 ObjectRepositoryImpl + * descendants.
    + * The actual repository managing is delegated to RepositorySets, while the logic + * for binding these sets together is located in this class. Set actual RepositorySets + * to be used are defined in login(...).
    + */ +public class RepositoryAdminImpl implements RepositoryAdmin { + /** + * Maps from interface classes of the ObjectRepositories to their implementations. + */ + @SuppressWarnings("unchecked") + private Map, ObjectRepositoryImpl> m_repositories; + + private final ChangeNotifier m_changeNotifier; + private volatile BundleContext m_context; /* Injected by dependency manager */ + private volatile PreferencesService m_preferences; /* Injected by dependency manager */ + private volatile LogService m_log; /* Injected by dependency manager */ + + private final Object m_lock = new Object(); + + 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"; + private User m_user; + private RepositorySet[] m_repositorySets; + private final Activator m_repositoryFactory; + + RepositoryAdminImpl(Activator factory, ChangeNotifier changeNotifier) { + m_repositoryFactory = factory; + m_changeNotifier = changeNotifier; + } + + @SuppressWarnings("unchecked") + void initialize(Map, ObjectRepositoryImpl> repositories) { + m_repositories = repositories; + } + + @SuppressWarnings("unchecked") + public void start() { + initialize(m_repositoryFactory.publishRepositories()); + } + + public void stop() { + m_repositoryFactory.pullRepositories(); + } + + 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 { + ensureLogin(); + synchronized (m_lock) { + for (RepositorySet set : m_repositorySets) { + set.revert(); + } + m_changeNotifier.notifyChanged(TOPIC_REFRESH_SUFFIX, null); + } + } + + public boolean isCurrent() throws IOException { + ensureLogin(); + synchronized (m_lock) { + boolean result = true; + for (RepositorySet set : m_repositorySets) { + result &= (set.isCurrent() || !set.writeAccess()); + } + return result; + } + } + + public boolean isModified() { + ensureLogin(); + boolean result = false; + for (RepositorySet set : m_repositorySets) { + result |= set.isModified(); + } + return result; + } + + public RepositoryAdminLoginContext createLoginContext(User user) { + if (user == null) { + throw new IllegalArgumentException("User may not be null."); + } + return new RepositoryAdminLoginContextImpl(user); + } + + 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); + // TODO I don't like this line, it should not be here... + ((ArtifactRepositoryImpl) 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 + */ + 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(); + } + + m_user = null; + m_repositorySets = new RepositorySet[0]; + } + m_changeNotifier.notifyChanged(TOPIC_LOGOUT_SUFFIX, null); + if (exception != null) { + throw exception; + } + } + + 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 { + // First, some sanity checks on the list of descriptors. + for (RepositorySetDescriptor rsd : context.getDescriptors()) { + 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."); + } + // Do other sets have a reference to this same class? + for (RepositorySetDescriptor other : context.getDescriptors()) { + if (other != rsd) { + for (Class otherC : other.m_objectRepositories) { + if (c.equals(otherC)) { + throw new IllegalArgumentException(rsd.toString() + " references repository class " + c.getName() + ", but so does " + other.toString()); + } + } + } + } + } + } + + RepositorySet[] result = new RepositorySet[context.getDescriptors().size()]; + + /* + * Create the lists of repositories and topics, and create and register + * the sets with these. + */ + for (int nRsd = 0; nRsd < result.length; nRsd++) { + RepositorySetDescriptor rsd = context.getDescriptors().get(nRsd); + ObjectRepositoryImpl[] impls = new ObjectRepositoryImpl[rsd.m_objectRepositories.length]; + String[] topics = new String[rsd.m_objectRepositories.length]; + for (int nRepo = 0; nRepo < impls.length; nRepo++) { + impls[nRepo] = m_repositories.get(rsd.m_objectRepositories[nRepo]); + topics[nRepo] = impls[nRepo].getTopicAll(true); + } + result[nRsd] = loadRepositorySet(context.getUser(), rsd, impls); + result[nRsd].registerHandler(m_context, 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 directory = repositoryPrefs.get(PREFS_LOCAL_FILE_LOCATION, ""); + + if ((directory == "") || !m_context.getDataFile(PREFS_LOCAL_FILE_ROOT + "/" + directory).isDirectory()) { + if (!m_context.getDataFile(PREFS_LOCAL_FILE_ROOT + "/" + directory).isDirectory() && (directory != "")) { + m_log.log(LogService.LOG_WARNING, "Directory '" + directory + "' should exist according to the preferences, but it does not."); + } + // The file did not exist, so create a new one. + 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); + } + catch (IOException e) { + // We cannot create the temp file? Then something is seriously wrong, so rethrow. + throw e; + } + + directoryFile.delete(); // No problem if this goes wrong, it just means it wasn't there yet. + if (!directoryFile.mkdir()) { + throw new IOException("Error creating the local repository storage directory."); + } + repositoryPrefs.put(PREFS_LOCAL_FILE_LOCATION, 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(User user, Repository repository, Preferences repositoryPrefs) throws IOException { + long mostRecentVersion = repositoryPrefs.getLong("version", CachedRepositoryImpl.UNCOMMITTED_VERSION); + return new CachedRepositoryImpl(user, repository, getBackupFromPreferences(repositoryPrefs), mostRecentVersion); + } + + /** + * Helper method for login, which loads a set of repositories. + * @param user A User object + * @param rsd A RepositorySetDescriptor, defining the set to be created. + * @param repos An array of ObjectRepositoryImpl 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); + 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(user, repo, repoPrefs), rsd.m_name, rsd.m_writeAccess); + } + + public int getNumberWithWorkingState(Class clazz, WorkingState state) { + int result = 0; + for (RepositorySet set : m_repositorySets) { + result += set.getNumberWithWorkingState(clazz, state); + } + return result; + } + + public WorkingState getWorkingState(RepositoryObject object) { + for (RepositorySet set : m_repositorySets) { + WorkingState result = set.getWorkingState(object); + if (result != null) { + return result; + } + } + return WorkingState.Unchanged; + } +} Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositoryAdminLoginContextImpl.java URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositoryAdminLoginContextImpl.java?rev=788992&view=auto ============================================================================== --- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositoryAdminLoginContextImpl.java (added) +++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositoryAdminLoginContextImpl.java Sat Jun 27 15:53:04 2009 @@ -0,0 +1,109 @@ +package net.luminis.liq.client.repository.impl; + +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import net.luminis.liq.client.repository.ObjectRepository; +import net.luminis.liq.client.repository.RepositoryAdminLoginContext; +import net.luminis.liq.client.repository.repository.Artifact2GroupAssociationRepository; +import net.luminis.liq.client.repository.repository.ArtifactRepository; +import net.luminis.liq.client.repository.repository.DeploymentVersionRepository; +import net.luminis.liq.client.repository.repository.GatewayRepository; +import net.luminis.liq.client.repository.repository.Group2LicenseAssociationRepository; +import net.luminis.liq.client.repository.repository.GroupRepository; +import net.luminis.liq.client.repository.repository.License2GatewayAssociationRepository; +import net.luminis.liq.client.repository.repository.LicenseRepository; + +import org.osgi.service.useradmin.User; + +class RepositoryAdminLoginContextImpl implements RepositoryAdminLoginContext { + private final User m_user; + private final List m_descriptors = new ArrayList(); + private URL m_obrBase; + + RepositoryAdminLoginContextImpl(User user) { + m_user = user; + } + + @SuppressWarnings("unchecked") + public RepositoryAdminLoginContext addRepositories(URL repositoryLocation, String repositoryCustomer, String repositoryName, boolean writeAccess, Class... objectRepositories) { + if ((repositoryLocation == null) || (repositoryCustomer == null) || (repositoryName == null)) { + throw new IllegalArgumentException("No parameter should be null."); + } + if ((objectRepositories == null) || (objectRepositories.length == 0)) { + throw new IllegalArgumentException("objectRepositories should not be null or empty."); + } + m_descriptors.add(new RepositorySetDescriptor(repositoryLocation, repositoryCustomer, repositoryName, writeAccess, objectRepositories)); + return this; + } + + @SuppressWarnings("unchecked") + public RepositoryAdminLoginContext addShopRepository(URL repositoryLocation, String repositoryCustomer, String repositoryName, boolean writeAccess) { + return addRepositories(repositoryLocation, repositoryCustomer, repositoryName, writeAccess, + ArtifactRepository.class, + GroupRepository.class, + Artifact2GroupAssociationRepository.class, + LicenseRepository.class, + Group2LicenseAssociationRepository.class); + } + + @SuppressWarnings("unchecked") + public RepositoryAdminLoginContext addGatewayRepository(URL repositoryLocation, String repositoryCustomer, String repositoryName, boolean writeAccess) { + return addRepositories(repositoryLocation, repositoryCustomer, repositoryName, writeAccess, + GatewayRepository.class, + License2GatewayAssociationRepository.class); + } + + @SuppressWarnings("unchecked") + public RepositoryAdminLoginContext addDeploymentRepository(URL repositoryLocation, String repositoryCustomer, String repositoryName, boolean writeAccess) { + return addRepositories(repositoryLocation, repositoryCustomer, repositoryName, writeAccess, + DeploymentVersionRepository.class); + } + + + public RepositoryAdminLoginContext setObrBase(URL base) { + m_obrBase = base; + return this; + } + + URL getObrBase() { + return m_obrBase; + } + + User getUser() { + return m_user; + } + + public List getDescriptors() { + return m_descriptors; + } + + /** + * Helper class to store all relevant information about a repository in a convenient location before + * we start using it. + */ + static 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[] m_objectRepositories; + + @SuppressWarnings("unchecked") + RepositorySetDescriptor(URL location, String customer, String name, boolean writeAccess, Class... 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; + } + } + +}