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 2009/06/27 17:53:26 UTC
svn commit: r788992 [11/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...
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositoryObjectImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositoryObjectImpl.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositoryObjectImpl.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositoryObjectImpl.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,608 @@
+package net.luminis.liq.client.repository.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import net.luminis.liq.client.repository.Associatable;
+import net.luminis.liq.client.repository.Association;
+import net.luminis.liq.client.repository.RepositoryObject;
+import net.luminis.liq.client.repository.RepositoryUtil;
+
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+
+/**
+ * Represents a value-object as is part of the repository.<br>
+ * It stores the 'member' values of the repository object, and allows putting tags on this object by using <code>put()</code>
+ * and <code>remove()</code>. It 'looks' like a dictionary to allow filtering of it, using an ldap filter.
+ */
+public class RepositoryObjectImpl<T extends RepositoryObject> extends Dictionary<String, Object> implements RepositoryObject, EventHandler {
+ private final Map<String, String> m_attributes = new HashMap<String, String>();
+ private final Map<String, String> m_tags = new HashMap<String, String>();
+ @SuppressWarnings("unchecked")
+ private final Map<Class, List<Association>> m_associations = new HashMap<Class, List<Association>>();
+
+ private final ChangeNotifier m_notifier;
+
+ private final String m_xmlNode;
+ private volatile boolean m_deleted = false;
+ private volatile boolean m_busy = false;
+
+ public RepositoryObjectImpl(ChangeNotifier notifier, String xmlNode) {
+ this((Map<String, String>) null, null, notifier, xmlNode);
+ }
+
+ public RepositoryObjectImpl(Map<String, String> attributes, ChangeNotifier notifier, String xmlNode) {
+ this(attributes, null, notifier, xmlNode);
+ }
+
+ public RepositoryObjectImpl(HierarchicalStreamReader reader, ChangeNotifier notifier, String xmlNode) {
+ this(readMap(reader), readMap(reader), notifier, xmlNode);
+ readCustom(reader);
+ }
+
+ public RepositoryObjectImpl(Map<String, String> attributes, Map<String, String> tags, ChangeNotifier notifier, String xmlNode) {
+ m_xmlNode = xmlNode;
+ if (attributes != null) {
+ m_attributes.putAll(attributes);
+ }
+ if (tags != null) {
+ m_tags.putAll(tags);
+ }
+ if (notifier == null) {
+ throw new IllegalArgumentException();
+ }
+ m_notifier = notifier;
+ }
+
+ protected void notifyChanged(Properties props) {
+ if (props == null) {
+ props = new Properties();
+ }
+ props.put(EVENT_ENTITY, this);
+ m_notifier.notifyChanged(TOPIC_CHANGED_SUFFIX, props, m_busy);
+ }
+
+ /**
+ * Returns an enumeration of the values in this object's dictionary.
+ */
+
+ @Override
+ public Enumeration<Object> elements() {
+ synchronized (m_attributes) {
+ return new ValuesEnumeration();
+ }
+ }
+
+ /**
+ * Gets the object associated with this key. Will return null when the key is not used; if the key is available for both the
+ * tags and the object's basic information, an array of two Strings will be returned.
+ */
+
+ @Override
+ public Object get(Object key) {
+ synchronized (m_attributes) {
+ String manifest = m_attributes.get(key);
+ String tag = m_tags.get(key);
+
+ if (manifest == null) {
+ return tag;
+ }
+ else if (tag == null) {
+ return manifest;
+ }
+ else {
+ return new String[] { tag, manifest };
+ }
+ }
+ }
+
+ /**
+ * Return whether the dictionary is empty.
+ */
+
+ @Override
+ public boolean isEmpty() {
+ synchronized (m_attributes) {
+ return m_attributes.isEmpty() && m_tags.isEmpty();
+ }
+ }
+
+ /**
+ * Returns an enumeration of the keys in this object.
+ */
+
+ @Override
+ public Enumeration<String> keys() {
+ synchronized (m_attributes) {
+ Set<String> keys = new HashSet<String>();
+ keys.addAll(m_attributes.keySet());
+ keys.addAll(m_tags.keySet());
+ return new KeysEnumeration(keys.iterator());
+ }
+ }
+
+ /**
+ * @throws UnsupportedOperationException
+ */
+
+ @Override
+ public Object put(@SuppressWarnings("unused")
+ String key, @SuppressWarnings("unused")
+ Object value) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * @throws UnsupportedOperationException
+ */
+
+ @Override
+ public Object remove(@SuppressWarnings("unused")
+ Object key) {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Returns the number of keys in both this object's tags, and its 'member' keys.
+ */
+
+ @Override
+ public int size() {
+ synchronized (m_attributes) {
+ Set<String> keys = new HashSet<String>();
+ keys.addAll(m_attributes.keySet());
+ keys.addAll(m_tags.keySet());
+ return keys.size();
+ }
+ }
+
+ /**
+ * Helper class that implements an enumeration for use in <code>keys()</code>.
+ */
+ private class KeysEnumeration implements Enumeration<String> {
+ private final Iterator<String> m_iter;
+
+ public KeysEnumeration(Iterator<String> iter) {
+ m_iter = iter;
+ }
+
+
+ public boolean hasMoreElements() {
+ return m_iter.hasNext();
+ }
+
+
+ public String nextElement() {
+ return m_iter.next();
+ }
+
+ }
+
+ /**
+ * Helper class that implements an enumeration for use in <code>elements()</code>.
+ */
+ private class ValuesEnumeration implements Enumeration<Object> {
+ private final Enumeration<String> m_iter = keys();
+
+
+ public boolean hasMoreElements() {
+ return m_iter.hasMoreElements();
+ }
+
+
+ public Object nextElement() {
+ return get(m_iter.nextElement());
+ }
+
+ }
+
+
+ public String addAttribute(String key, String value) {
+ for (String s : getDefiningKeys()) {
+ if (s.equals(key)) {
+ throw new UnsupportedOperationException("The defining attribute " + key + " is not allowed to be changed.");
+ }
+ }
+ synchronized (m_attributes) {
+ ensureCurrent();
+ notifyChanged(null);
+ return m_attributes.put(key, value);
+ }
+ }
+
+
+ public String addTag(String key, String value) {
+ synchronized (m_attributes) {
+ ensureCurrent();
+ notifyChanged(null);
+ return m_tags.put(key, value);
+ }
+ }
+
+
+ public String getAttribute(String key) {
+ synchronized (m_attributes) {
+ return m_attributes.get(key);
+ }
+ }
+
+
+ public String getTag(String key) {
+ synchronized (m_attributes) {
+ return m_tags.get(key);
+ }
+ }
+
+
+ public Enumeration<String> getAttributeKeys() {
+ synchronized (m_attributes) {
+ return new KeysEnumeration(new HashSet<String>(m_attributes.keySet()).iterator());
+ }
+ }
+
+
+ public Dictionary<String, Object> getDictionary() {
+ return this;
+ }
+
+
+ public Enumeration<String> getTagKeys() {
+ synchronized (m_attributes) {
+ return new KeysEnumeration(new HashSet<String>(m_tags.keySet()).iterator());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void add(Association association, Class clazz) {
+ synchronized (m_associations) {
+ List<Association> associations = m_associations.get(clazz);
+ if (associations == null) {
+ associations = new ArrayList<Association>();
+ m_associations.put(clazz, associations);
+ }
+ associations.add(association);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public void remove(Association association, Class clazz) {
+ synchronized (m_associations) {
+ List<Association> associations = m_associations.get(clazz);
+ if (associations != null) {
+ associations.remove(association);
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public <A extends Associatable> List<A> getAssociations(Class<A> clazz) {
+ synchronized (m_associations) {
+ List<A> result = new ArrayList<A>();
+ List<Association> associations = m_associations.get(clazz);
+ if (associations != null) {
+ for (Association association : associations) {
+ List<A> otherSide = association.getTo(this);
+ if (otherSide != null) {
+ // If the other side is null, the association
+ // is not satisfied.
+ result.addAll(otherSide);
+ }
+ }
+ }
+ return result;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean isAssociated(Object obj, Class clazz) {
+ synchronized (m_associations) {
+ if (obj == null) {
+ return false;
+ }
+ List<Association> associations = m_associations.get(clazz);
+ if (associations != null) {
+ for (Association association : associations) {
+ if (association.getTo(this).contains(obj)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public <TA extends Associatable, A extends Association> List<A> getAssociationsWith(Associatable other, Class<TA> clazz, Class<A> associationType) {
+ List<A> result = new ArrayList<A>();
+ synchronized (m_associations) {
+ if (other == null) {
+ return result;
+ }
+ List<Association> associations = m_associations.get(clazz);
+ if (associations != null) {
+ for (Association association : associations) {
+ if (association.getTo(this).contains(other)) {
+ result.add((A) association);
+ }
+ }
+ }
+ return result;
+ }
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public boolean equals(Object o) {
+ synchronized(m_attributes) {
+ if ((o == null) || !(getClass().isInstance(o))) {
+ return false;
+ }
+ if (m_attributes.size() == 0) {
+ return this == o;
+ }
+ for (String s : getDefiningKeys()) {
+ String ourAttribute = m_attributes.get(s);
+ String otherAttribute = (String) ((RepositoryObjectImpl) o).m_attributes.get(s);
+ if ((ourAttribute == null) && (otherAttribute != null)) {
+ return false;
+ }
+ else if ((ourAttribute != null) && (otherAttribute == null)) {
+ return false;
+ }
+ else if ((ourAttribute == null) && (otherAttribute == null)) {
+ continue;
+ }
+ else if (!otherAttribute.equals(ourAttribute)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ /**
+ * Returns an array of keys which are considered to be defining for this object's
+ * attributes. The basic implementation just uses every key that is used; this
+ * function is intended to be overridden by deriving classes, providing a real
+ * set.
+ *
+ * Note that the array returned from this function should be read from only;
+ * writing to it will change the state of the object.
+ */
+ String[] getDefiningKeys() {
+ return m_attributes.keySet().toArray(new String[m_attributes.size()]);
+ }
+
+ @Override
+ public int hashCode() {
+ synchronized(m_attributes) {
+ return m_attributes.hashCode();
+ }
+ }
+
+ void marshal(HierarchicalStreamWriter writer) {
+ synchronized (m_attributes) {
+ writer.startNode(m_xmlNode);
+ writeMap(writer, m_attributes, "attributes");
+ writeMap(writer, m_tags, "tags");
+ writeCustom(writer);
+ writer.endNode();
+ }
+ }
+
+ /**
+ * This method is intended to be overridden by deriving classes, to read custom information
+ * from the XML representation of this object. This method should end with the writer at
+ * the same 'level' as before, that is, using equally many moveDown() and moveUp() calls.
+ * @param reader A reader to read from the XML stream.
+ */
+ protected void readCustom(HierarchicalStreamReader reader) {
+ // do nothing
+ }
+
+ /**
+ * This method is intended to be overridden by deriving classes, to write custom information
+ * to the XML representation of this object. This method should end with the writer at
+ * the same 'level' as before, that is, using equally many moveDown() and moveUp() calls.
+ * @param writer A writer to write to the XML stream.
+ */
+ protected void writeCustom(HierarchicalStreamWriter writer) {
+ // do nothing
+ }
+
+ static void writeMap(HierarchicalStreamWriter writer, Map<String, String> entries, String name) {
+ writer.startNode(name);
+ for (Map.Entry<String, String> entry : entries.entrySet()) {
+ writer.startNode(entry.getKey());
+ assert (entry.getValue() != null);
+ writer.setValue(entry.getValue());
+ writer.endNode();
+ }
+ writer.endNode();
+ }
+
+ static Map<String, String> readMap(HierarchicalStreamReader reader) {
+ reader.moveDown();
+ Map<String, String> result = new HashMap<String, String>();
+ while (reader.hasMoreChildren()) {
+ reader.moveDown();
+ result.put(reader.getNodeName(), reader.getValue());
+ reader.moveUp();
+ }
+ reader.moveUp();
+ return result;
+ }
+
+ /**
+ * Helper function to check the existence of keys in a map. Each attribute is required
+ * to be non-empty.
+ * @param attributes A map of attribute-value combinations.
+ * @param mandatory An array of attributes which have to be present in the map.
+ * @return <code>attributes</code> if this map meets the requirements. If not, <code>IllegalArgumentException</code>
+ * will be thrown.
+ */
+ static Map<String, String> checkAttributes(Map<String, String> attributes, String... mandatory) {
+ boolean[] booleans = new boolean[mandatory.length];
+ Arrays.fill(booleans, false);
+ return checkAttributes(attributes, mandatory, booleans);
+ }
+
+ /**
+ * Helper function to check the existence of keys in a map.
+ * @param attributes A map of attribute-value combinations.
+ * @param mandatory An array of attributes which have to be present in the map.
+ * @param emptyAttributeAllowed An array of booleans, indicating which of the attributes is allowed
+ * to be equal. Items in this array are matched by index on the elements in <code>mandatory</code>, so
+ * the length should be equal.
+ * @return <code>attributes</code> if this map meets the requirements. If not, <code>IllegalArgumentException</code>
+ * will be thrown.
+ */
+ static Map<String, String> checkAttributes(Map<String, String> attributes, String[] mandatory, boolean[] emptyAttributeAllowed) {
+ if (!(mandatory.length == emptyAttributeAllowed.length)) {
+ throw new IllegalArgumentException("The length of the mandatory- and the emptyAttributeAllow-array should be equal.");
+ }
+ for (int i = 0; i < mandatory.length; i++) {
+ String attribute = mandatory[i];
+ boolean emptyAllowed = emptyAttributeAllowed[i];
+ if (!attributes.containsKey(attribute)) {
+ throw new IllegalArgumentException(attribute + " is a mandatory attribute.");
+ }
+ else if ((!emptyAllowed) && (attributes.get(attribute).length() == 0)) {
+ throw new IllegalArgumentException(attribute + " is not allowed to be empty.");
+ }
+ }
+ return attributes;
+ }
+
+ public String getXmlNode() {
+ return m_xmlNode;
+ }
+
+ public void handleEvent(Event e) {
+ }
+
+ void setDeleted() {
+ m_deleted = true;
+ }
+
+ public boolean isDeleted() {
+ return m_deleted;
+ }
+
+ void ensureNotDeleted() {
+ if (isDeleted()) {
+ throw new IllegalStateException("This object is deleted, and should no longer be used.");
+ }
+ }
+
+ void setBusy(boolean busy) {
+ // setBusy should 'wait' until all altering operations have passed. To do so,
+ // it gets the locks for the other 'set' objects. Once it has all these locks,
+ // we are sure no thread is performing a set-action.
+ synchronized(m_attributes) {
+ synchronized(m_associations) {
+ if (m_busy && !busy) {
+ m_associations.notifyAll();
+ m_attributes.notifyAll();
+ }
+ m_busy = busy;
+ }
+ }
+ }
+
+ public boolean getBusy() {
+ return m_busy;
+ }
+
+ // NEVER CALL WITHOUT m_attributes lock
+ private void ensureNotBusy() {
+ boolean interrupted = false;
+ while (m_busy) {
+ try {
+ m_attributes.wait();
+ }
+ catch (InterruptedException e) {
+ interrupted = true;
+ }
+ }
+ if (interrupted) {
+ Thread.currentThread().interrupt();
+ }
+ }
+
+ void ensureCurrent() {
+ ensureNotBusy();
+ ensureNotDeleted();
+ }
+
+ public String getDefinition() {
+ StringBuilder result = new StringBuilder();
+
+ result.append(getXmlNode().replaceAll("\\\\", "\\\\\\\\").replaceAll("-", "\\-"));
+
+ for (String key : getDefiningKeys()) {
+ String value = getAttribute(key);
+ if (value != null) {
+ result.append("-")
+ .append(key.replaceAll("\\\\", "\\\\\\\\").replaceAll("-", "\\-").replaceAll("\\/", "/"))
+ .append("-")
+ .append(value.replaceAll("\\\\", "\\\\\\\\").replaceAll("-", "\\-").replaceAll("\\/", "/"));
+ // About the /: the forward slash will be used by the preference admin, but we don't want that.
+ }
+ }
+
+ return result.toString();
+ }
+
+ /**
+ * Creates a filter string for use in associations, optionally with some
+ * additional properties. The basic implementation will use all <code>getDefiningKeys</code>.
+ * @param properties Properties indicating specifics of the filter to be created.
+ * @return A string representation of a filter, for use in <code>Association</code>s.
+ */
+ public String getAssociationFilter(Map<String, String> properties) {
+ StringBuilder filter = new StringBuilder("(&");
+
+ for (String key : getDefiningKeys()) {
+ filter.append("(" + key + "=" + RepositoryUtil.escapeFilterValue(getAttribute(key)) + ")");
+ }
+
+ filter.append(")");
+
+ return filter.toString();
+ }
+
+ /**
+ * Determines the cardinality of this endpoint of an association, given
+ * the passed properties.
+ * @param properties Properties indicating specifics of this endpoint.
+ * @return The necessary cardinality.
+ */
+ public int getCardinality(Map<String, String> properties) {
+ return Integer.MAX_VALUE;
+ }
+
+ /**
+ * Returns a <code>Comparator</code> for this type of object, suitable
+ * for the endpoint properties that are passed.
+ * @return A <code>Comparator</code> for this type of object
+ */
+ public Comparator<T> getComparator() {
+ return null;
+ }
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositorySerializer.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositorySerializer.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositorySerializer.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositorySerializer.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,110 @@
+package net.luminis.liq.client.repository.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.thoughtworks.xstream.XStream;
+import com.thoughtworks.xstream.converters.Converter;
+import com.thoughtworks.xstream.converters.MarshallingContext;
+import com.thoughtworks.xstream.converters.UnmarshallingContext;
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
+
+/**
+ * Helper class that takes a RepositorySet<br>
+ * TODO We might move out xstream at some time in the future; before that
+ * time, it could be a smart idea to wrap xstream's writer in a delegate
+ * object, so this will not require changes to the repositories
+ * and objects.
+ */
+class RepositorySerializer implements Converter {
+ @SuppressWarnings("unchecked")
+ private final Map<String, ObjectRepositoryImpl> m_tagToRepo = new HashMap<String, ObjectRepositoryImpl>();
+
+ private final RepositorySet m_set;
+
+ private final XStream m_stream;
+
+ @SuppressWarnings("unchecked")
+ RepositorySerializer(RepositorySet set) {
+ m_set = set;
+ for (ObjectRepositoryImpl repo : m_set.getRepos()) {
+ m_tagToRepo.put(repo.getXmlNode(), repo);
+ }
+ m_stream = new XStream();
+ m_stream.alias("repository", getClass());
+ m_stream.registerConverter(this);
+ }
+
+ @SuppressWarnings("unchecked")
+ public void marshal(Object target, HierarchicalStreamWriter writer, MarshallingContext context) {
+ for (ObjectRepositoryImpl repo : m_set.getRepos()) {
+ repo.marshal(writer);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) {
+ while(reader.hasMoreChildren()) {
+ reader.moveDown();
+ String nodeName = reader.getNodeName();
+ ObjectRepositoryImpl o = m_tagToRepo.get(nodeName);
+ o.unmarshal(reader);
+ reader.moveUp();
+ }
+ return this;
+ }
+
+ @SuppressWarnings("unchecked")
+ public boolean canConvert(Class target) {
+ return target == getClass();
+ }
+
+ @SuppressWarnings("unchecked")
+ public void toXML(OutputStream out) {
+ for (ObjectRepositoryImpl repo : m_set.getRepos()) {
+ repo.setBusy(true);
+ }
+ m_stream.toXML(this, out);
+ for (ObjectRepositoryImpl repo : m_set.getRepos()) {
+ repo.setBusy(false);
+ }
+ }
+
+ /**
+ * Reads the repositories with which this RepositoryRoot had been initialized with from the
+ * given XML file.
+ * @param in The input stream.
+ */
+ @SuppressWarnings("unchecked")
+ public void fromXML(InputStream in) {
+ // The repositories get cleared, since a user *could* add stuff before
+ // checking out.
+ for (ObjectRepositoryImpl repo : m_set.getRepos()) {
+ repo.setBusy(true);
+ repo.removeAll();
+ }
+ ClassLoader cl = Thread.currentThread().getContextClassLoader();
+ try {
+ Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+ if (in.available() > 0) {
+ m_stream.fromXML(in, this);
+ }
+ }
+ catch (IOException e) {
+ // This means the stream has been closed before we got it.
+ // Since the repository is now in a consistent state, just move on.
+ e.printStackTrace();
+ }
+ finally {
+ Thread.currentThread().setContextClassLoader(cl);
+ }
+ for (ObjectRepositoryImpl repo : m_set.getRepos()) {
+ repo.setBusy(false);
+ }
+ }
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositorySet.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositorySet.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositorySet.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/RepositorySet.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,325 @@
+package net.luminis.liq.client.repository.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PipedInputStream;
+import java.io.PipedOutputStream;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+
+import net.luminis.liq.client.repository.ObjectRepository;
+import net.luminis.liq.client.repository.RepositoryAdmin;
+import net.luminis.liq.client.repository.RepositoryObject;
+import net.luminis.liq.client.repository.RepositoryObject.WorkingState;
+import net.luminis.liq.repository.ext.CachedRepository;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+import org.osgi.service.log.LogService;
+import org.osgi.service.prefs.BackingStoreException;
+import org.osgi.service.prefs.Preferences;
+import org.osgi.service.useradmin.User;
+
+/**
+ * This class encapsulates a set of <code>ObjectRepositoryImpl</code>s, and manages
+ * auxiliary information and functionality that is linked to that set.
+ */
+class RepositorySet {
+ private final static String PREFS_LOCAL_WORKING_STATE = "workingState";
+ private final static String PREFS_LOCAL_WORKING_STATE_VALUE = "workingStateValue";
+ private final static String PREFS_LOCAL_FILE_VERSION = "version";
+
+ private final User m_user;
+ private final Preferences m_prefs;
+ @SuppressWarnings("unchecked")
+ private final ObjectRepositoryImpl[] m_repos;
+ private final CachedRepository m_repository;
+ private final String m_name;
+ private final boolean m_writeAccess;
+
+ private final Map<RepositoryObject, WorkingState> m_workingState = new HashMap<RepositoryObject, WorkingState>();
+ private ServiceRegistration m_modifiedHandler;
+ private final ChangeNotifier m_notifier;
+ private final LogService m_log;
+
+ /* ********
+ * Basics
+ * ********/
+
+ @SuppressWarnings("unchecked")
+ /**
+ * Creates a new <code>RepositorySet</code>. Notes:
+ * <ul>
+ * <li>When storing association repositories in <code>repos</code>, it is wise to
+ * put these in last. This has to do with the method of deserialization, which assumes
+ * that endpoints of an association are available at the time of deserialization.</li>
+ * </ul>
+ */
+ RepositorySet(ChangeNotifier notifier, LogService log, User user, Preferences prefs, ObjectRepositoryImpl[] repos, CachedRepository repository, String name, boolean writeAccess) {
+ m_notifier = notifier;
+ m_log = log;
+ m_user = user;
+ m_prefs = prefs;
+ m_repos = repos;
+ m_repository = repository;
+ m_name = name;
+ m_writeAccess = writeAccess;
+ }
+
+ boolean isModified() {
+ boolean modified = false;
+ for (Map.Entry<RepositoryObject, WorkingState> entry : m_workingState.entrySet()) {
+ modified |= !(entry.getValue().equals(WorkingState.Unchanged));
+ }
+ return modified;
+ }
+
+ User getUser() {
+ return m_user;
+ }
+
+ @SuppressWarnings("unchecked")
+ ObjectRepositoryImpl[] getRepos() {
+ return m_repos;
+ }
+
+ String getName() {
+ return m_name;
+ }
+
+ /* ********
+ * Preferences
+ * ********/
+
+ void savePreferences() {
+ Preferences workingNode = m_prefs.node(PREFS_LOCAL_WORKING_STATE);
+ try {
+ workingNode.clear();
+ }
+ catch (BackingStoreException e) {
+ // Something went wrong clearing the node... Too bad, this means we
+ // cannot store the properties.
+ m_log.log(LogService.LOG_WARNING, "Could not store all preferences for " + workingNode.absolutePath());
+ e.printStackTrace();
+ }
+ for (Map.Entry<RepositoryObject, WorkingState> entry : m_workingState.entrySet()) {
+ workingNode.node(entry.getKey().getDefinition()).put(PREFS_LOCAL_WORKING_STATE_VALUE, entry.getValue().toString());
+ }
+
+ m_prefs.putLong(PREFS_LOCAL_FILE_VERSION, m_repository.getMostRecentVersion());
+ }
+
+ /**
+ * Only call this after the repository has been deserialized.
+ */
+ void loadPreferences() {
+ Preferences workingNode = m_prefs.node(PREFS_LOCAL_WORKING_STATE);
+ Map<String, WorkingState> entries = new HashMap<String, WorkingState>();
+ // First, get all nodes and their workingstate.
+ try {
+ for (String node : workingNode.childrenNames()) {
+ String state = workingNode.node(node).get(PREFS_LOCAL_WORKING_STATE_VALUE, WorkingState.Unchanged.toString());
+ entries.put(node, WorkingState.valueOf(state));
+ }
+ }
+ catch (BackingStoreException e) {
+ // Something went wrong reading from the store, just work with whatever we have in the map.
+ e.printStackTrace();
+ }
+ // Then, go through all objects and check whether they match a definition we know.
+ // This prevents calling getDefinition more than once per object.
+ for (ObjectRepository<RepositoryObject> repo : m_repos) {
+ for (RepositoryObject o : repo.get()) {
+ WorkingState state = entries.get(o.getDefinition());
+ if (state != null) {
+ m_workingState.put(o, state);
+ }
+ }
+ }
+ }
+
+ /* ********
+ * Persistence
+ * ********/
+
+ boolean readLocal() throws IOException {
+ InputStream input = m_repository.getLocal(false);
+ if (input.available() > 0) {
+ read(input);
+ return true;
+ }
+ else {
+ try {
+ input.close();
+ }
+ catch (IOException e) {
+ // This does not matter now.
+ }
+ return false;
+ }
+ }
+
+ void read(InputStream input) {
+ new RepositorySerializer(this).fromXML(input);
+ try {
+ input.close();
+ }
+ catch (IOException e) {
+ // Not much we can do...
+ e.printStackTrace();
+ }
+ }
+
+ void writeLocal() throws IOException {
+ PipedInputStream input = new PipedInputStream();
+ final PipedOutputStream output = new PipedOutputStream(input);
+ new Thread(new Runnable() {
+ public void run() {
+ new RepositorySerializer(RepositorySet.this).toXML(output);
+ try {
+ output.flush();
+ output.close();
+ }
+ catch (IOException e) {
+ // There is no way to tell this to the user, but the other side will
+ // notice that the pipe is broken.
+ }
+ }
+ }, "write(" + m_name + ")").start();
+ m_repository.writeLocal(input);
+ input.close();
+ }
+
+ void commit() throws IOException {
+ if (!isCurrent()) {
+ throw new IllegalStateException("When committing the " + m_name + ", it should be current.");
+ }
+ writeLocal();
+ if (m_writeAccess) {
+ m_repository.commit();
+ }
+ resetModified(false);
+ }
+
+ void checkout() throws IOException {
+ read(m_repository.checkout(false));
+ resetModified(true);
+ }
+
+ void revert() throws IOException {
+ m_repository.revert();
+ read(m_repository.getLocal(false));
+ resetModified(false);
+ }
+
+ boolean isCurrent() throws IOException {
+ return m_repository.isCurrent();
+ }
+
+ @SuppressWarnings("unchecked")
+ void clearRepositories() {
+ for (ObjectRepositoryImpl repo : getRepos()) {
+ repo.setBusy(true);
+ }
+ for (ObjectRepositoryImpl repo : getRepos()) {
+ repo.removeAll();
+ }
+ for (ObjectRepositoryImpl repo : getRepos()) {
+ repo.setBusy(false);
+ }
+ }
+
+ /* ********
+ * Event handling
+ * ********/
+
+ void registerHandler(BundleContext context, String... topics) {
+ if (m_modifiedHandler != null) {
+ throw new IllegalStateException("A handler is already registered; only one can be used at a time.");
+ }
+ Dictionary<String, String[]> topic = new Hashtable<String, String[]>();
+ topic.put(EventConstants.EVENT_TOPIC, topics);
+ m_modifiedHandler = context.registerService(EventHandler.class.getName(), new ModifiedHandler(), topic);
+ }
+
+ public void unregisterHandler() {
+ m_modifiedHandler.unregister();
+ m_modifiedHandler = null;
+ }
+
+ WorkingState getWorkingState(RepositoryObject object) {
+ if (m_workingState.containsKey(object)) {
+ return m_workingState.get(object);
+ }
+ return null;
+ }
+
+ int getNumberWithWorkingState(Class<? extends RepositoryObject> clazz, WorkingState state) {
+ int result = 0;
+ for (Map.Entry<RepositoryObject, WorkingState> entry : m_workingState.entrySet()) {
+ if (clazz.isInstance(entry.getKey()) && state.equals(entry.getValue())) {
+ result ++;
+ }
+ }
+ return result;
+ }
+
+ private void resetModified(boolean fill) {
+ m_workingState.clear();
+ if (fill) {
+ for (ObjectRepository<? extends RepositoryObject> repo : m_repos) {
+ for (RepositoryObject object : repo.get()) {
+ m_workingState.put(object, WorkingState.Unchanged);
+ }
+ }
+ }
+ m_notifier.notifyChanged(RepositoryAdmin.TOPIC_STATUSCHANGED_SUFFIX, null);
+ }
+
+ class ModifiedHandler implements EventHandler {
+
+ public void handleEvent(Event event) {
+ /*
+ * NOTE: if recalculating the state for every event turns out to be
+ * too expensive, we can cache the 'modified' state and not recalculate
+ * it every time.
+ */
+
+ boolean wasModified = isModified();
+ RepositoryObject object = (RepositoryObject) event.getProperty(RepositoryObject.EVENT_ENTITY);
+
+ WorkingState newState = WorkingState.Unchanged;
+ if (event.getTopic().endsWith("/ADDED")) {
+ newState = WorkingState.New;
+ }
+ else if (event.getTopic().endsWith("/CHANGED")) {
+ newState = WorkingState.Changed;
+ }
+ else if (event.getTopic().endsWith("/REMOVED")) {
+ newState = WorkingState.Removed;
+ }
+
+ if (!newState.equals(m_workingState.get(object))) {
+ m_workingState.put(object, newState);
+ Properties props = new Properties();
+ props.put(RepositoryObject.EVENT_ENTITY, object);
+ m_notifier.notifyChanged(RepositoryAdmin.TOPIC_STATUSCHANGED_SUFFIX, props);
+ }
+
+ if (!wasModified) {
+ m_notifier.notifyChanged(RepositoryAdmin.TOPIC_STATUSCHANGED_SUFFIX, null);
+ }
+ }
+ }
+
+ public boolean writeAccess() {
+ return m_writeAccess;
+ }
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/Artifact2GroupAssociation.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/Artifact2GroupAssociation.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/Artifact2GroupAssociation.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/Artifact2GroupAssociation.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,15 @@
+package net.luminis.liq.client.repository.object;
+
+import net.luminis.liq.client.repository.Association;
+
+/**
+ * Interface to a Artifact2GroupAssociation. Most functionality is defined by the generic Association.
+ */
+public interface Artifact2GroupAssociation extends Association<ArtifactObject, GroupObject> {
+ public static final String TOPIC_ENTITY_ROOT = Artifact2GroupAssociation.class.getSimpleName() + "/";
+
+ public static final String TOPIC_ADDED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ADDED_SUFFIX;
+ public static final String TOPIC_REMOVED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_REMOVED_SUFFIX;
+ public static final String TOPIC_CHANGED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_CHANGED_SUFFIX;
+ public static final String TOPIC_ALL = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ALL_SUFFIX;
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/ArtifactObject.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/ArtifactObject.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/ArtifactObject.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/ArtifactObject.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,86 @@
+package net.luminis.liq.client.repository.object;
+
+import java.util.List;
+
+import net.luminis.liq.client.repository.RepositoryObject;
+
+/**
+ * Interface to an ArtifactObject. The basic functionality is defined by RepositoryObject, but extended for
+ * artifact-specific information.
+ */
+public interface ArtifactObject extends RepositoryObject {
+ /**
+ * Key to be used in the <code>ArtifactObject</code>'s attributes.
+ * Indicates the location of the persistent storage of the artifact.
+ */
+ public static final String KEY_URL = "url";
+ /**
+ * Key to be used in the <code>ArtifactObject</code>'s attributes.
+ * Indicates the PID of the resource processor that should be used to process this artifact.
+ * For a bundle, it is empty.
+ */
+ public static final String KEY_PROCESSOR_PID = "processorPid";
+ /**
+ * Key to be used in the <code>ArtifactObject</code>'s attributes.
+ * Indicates the mimetype of this artifact. For artifacts which do not
+ * have an adequately discriminating mimetype, it can be extended with
+ * something non-standard.
+ */
+ public static final String KEY_MIMETYPE = "mimetype";
+ /**
+ * Key to be used in the <code>ArtifactObject</code>'s attributes.
+ * Holds a human-readable name for this artifact.
+ */
+ public static final String KEY_ARTIFACT_NAME = "artifactName";
+ /**
+ * Key to be used in the <code>ArtifactObject</code>'s attributes.
+ * Holds a human-readable description for this artifact.
+ */
+ public static final String KEY_ARTIFACT_DESCRIPTION = "artifactDescription";
+
+ public static final String TOPIC_ENTITY_ROOT = ArtifactObject.class.getSimpleName() + "/";
+
+ public static final String TOPIC_ADDED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ADDED_SUFFIX;
+ public static final String TOPIC_REMOVED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_REMOVED_SUFFIX;
+ public static final String TOPIC_CHANGED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_CHANGED_SUFFIX;
+ public static final String TOPIC_ALL = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ALL_SUFFIX;
+
+ /**
+ * Returns all <code>GroupObject</code>s this object is associated with. If there
+ * are none, an empty list will be returned.
+ */
+ public List<GroupObject> getGroups();
+ /**
+ * Returns all associations this artifact has with a given group.
+ */
+ public List<Artifact2GroupAssociation> getAssociationsWith(GroupObject group);
+
+ /**
+ * Returns the mimetype of this artifact.
+ */
+ public String getMimetype();
+ /**
+ * Returns the PID of the resource processor of this artifact.
+ */
+ public String getProcessorPID();
+ /**
+ * Sets the PID of the resource processor of this artifact.
+ */
+ public void setProcessorPID(String processorPID);
+ /**
+ * Returns the URL to this artifact.
+ */
+ public String getURL();
+ /**
+ * Return a descriptive name for this object. May return <code>null</code>.
+ */
+ public String getName();
+ /**
+ * Returns a description for this object. May return <code>null</code>.
+ */
+ public String getDescription();
+ /**
+ * Sets a description for this artifact.
+ */
+ public void setDescription(String value);
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/DeploymentArtifact.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/DeploymentArtifact.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/DeploymentArtifact.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/DeploymentArtifact.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,46 @@
+package net.luminis.liq.client.repository.object;
+
+import java.net.URL;
+
+/**
+ * Interface to a deployment artifact, which is used to gather information about
+ * the deployment of a single artifact.
+ */
+public interface DeploymentArtifact {
+
+ /**
+ * Key, intended to be used for artifacts which are bundles and will publish
+ * a resource processor (see OSGi compendium section 114.10).
+ */
+ public static final String DIRECTIVE_ISCUSTOMIZER = "DeploymentPackage-Customizer";
+
+ /**
+ * Key, intended to be used for resources which require a resource processor
+ * (see OSGi compendium section 114.10).
+ */
+ public static final String DIRECTIVE_KEY_PROCESSORID = "Resource-Processor";
+
+ /**
+ * Key, intended to be used for matching processed (see ArtifactPreprocessor) to their
+ * 'original' one.
+ */
+ public static final String DIRECTIVE_KEY_BASEURL = "Base-Url";
+
+ /**
+ * @return the URL for this deployment artifact.
+ */
+ public String getUrl();
+
+ /**
+ * @param key A key String, such as the <code>DIRECTIVE_</code> constants in
+ * <code>DeploymentArtifact</code>.
+ * @return the value for the given directive key, or <code>null</code> if not found.
+ */
+ public String getDirective(String key);
+
+ /**
+ * @return an array of all keys that are used in this object, to be used in <code>getDirective</code>.
+ */
+ public String[] getKeys();
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/DeploymentVersionObject.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/DeploymentVersionObject.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/DeploymentVersionObject.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/DeploymentVersionObject.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,40 @@
+package net.luminis.liq.client.repository.object;
+
+import net.luminis.liq.client.repository.RepositoryObject;
+
+/**
+ * The interface to a DeploymentVersion. The basic functionality is defined
+ * by RepositoryObject, but extended for deployment version-specific information.
+ *
+ * DeploymentVersions need some additional information about the artifacts they
+ * are associated with; see DeploymentArtifact.
+ */
+public interface DeploymentVersionObject extends RepositoryObject {
+
+ public static final String KEY_GATEWAYID = "gatewayID";
+ public static final String KEY_VERSION = "version";
+
+ public static final String TOPIC_ENTITY_ROOT = DeploymentVersionObject.class.getSimpleName() + "/";
+
+ public static final String TOPIC_ADDED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ADDED_SUFFIX;
+ public static final String TOPIC_REMOVED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_REMOVED_SUFFIX;
+ public static final String TOPIC_CHANGED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_CHANGED_SUFFIX;
+ public static final String TOPIC_ALL = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ALL_SUFFIX;
+
+ /**
+ * Gets the gateway which is related to this version.
+ */
+ public String getGatewayID();
+
+ /**
+ * Gets the version number of this deployment version.
+ */
+ public String getVersion();
+
+ /**
+ * @return an array of all deployment artifacts that will be part of this deployment version.
+ * The order of the artifacts in the array is equal to the order they should appear in a
+ * deployment package.
+ */
+ public DeploymentArtifact[] getDeploymentArtifacts();
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/GatewayObject.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/GatewayObject.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/GatewayObject.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/GatewayObject.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,41 @@
+package net.luminis.liq.client.repository.object;
+
+import java.util.List;
+
+import net.luminis.liq.client.repository.RepositoryObject;
+
+public interface GatewayObject extends RepositoryObject {
+ public static final String KEY_ID = "id";
+ public static final String KEY_AUTO_APPROVE = "autoapprove";
+
+ public static final String TOPIC_ENTITY_ROOT = GatewayObject.class.getSimpleName() + "/";
+
+ public static final String TOPIC_ADDED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ADDED_SUFFIX;
+ public static final String TOPIC_REMOVED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_REMOVED_SUFFIX;
+ public static final String TOPIC_CHANGED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_CHANGED_SUFFIX;
+ public static final String TOPIC_ALL = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ALL_SUFFIX;
+
+ /**
+ * Returns all <code>LicenseObject</code>s this object is associated with. If there
+ * are none, an empty list will be returned.
+ */
+ public List<LicenseObject> getLicenses();
+ /**
+ * Returns all associations this gateway has with a given license.
+ */
+ public List<License2GatewayAssociation> getAssociationsWith(LicenseObject license);
+ /**
+ * Gets the ID of this GatewayObject.
+ */
+ public String getID();
+
+ /**
+ * Enable or disable automatic approval.
+ */
+ public void setAutoApprove(boolean approve);
+
+ /**
+ * Get the auto approval value of this gateway.
+ */
+ public boolean getAutoApprove();
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/Group2LicenseAssociation.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/Group2LicenseAssociation.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/Group2LicenseAssociation.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/Group2LicenseAssociation.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,15 @@
+package net.luminis.liq.client.repository.object;
+
+import net.luminis.liq.client.repository.Association;
+
+/**
+ * Interface to a Group2LicenseAssociation. Most functionality is defined by the generic Association.
+ */
+public interface Group2LicenseAssociation extends Association<GroupObject, LicenseObject> {
+ public static final String TOPIC_ENTITY_ROOT = Group2LicenseAssociation.class.getSimpleName() + "/";
+
+ public static final String TOPIC_ADDED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ADDED_SUFFIX;
+ public static final String TOPIC_REMOVED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_REMOVED_SUFFIX;
+ public static final String TOPIC_CHANGED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_CHANGED_SUFFIX;
+ public static final String TOPIC_ALL = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ALL_SUFFIX;
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/GroupObject.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/GroupObject.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/GroupObject.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/GroupObject.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,60 @@
+package net.luminis.liq.client.repository.object;
+
+import java.util.List;
+
+import net.luminis.liq.client.repository.RepositoryObject;
+
+/**
+ * Interface to a GroupObject. The basic functionality is defined by RepositoryObject, but extended for
+ * Group-specific information.
+ */
+public interface GroupObject extends RepositoryObject {
+ public static final String KEY_DESCRIPTION = "description";
+ public static final String KEY_NAME = "name";
+
+ public static final String TOPIC_ENTITY_ROOT = GroupObject.class.getSimpleName() + "/";
+
+ public static final String TOPIC_ADDED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ADDED_SUFFIX;
+ public static final String TOPIC_REMOVED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_REMOVED_SUFFIX;
+ public static final String TOPIC_CHANGED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_CHANGED_SUFFIX;
+ public static final String TOPIC_ALL = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ALL_SUFFIX;
+
+ /**
+ * Returns all <code>ArtifactObject</code>s this object is associated with. If there
+ * are none, an empty list will be returned.
+ */
+ public List<ArtifactObject> getArtifacts();
+ /**
+ * Returns all <code>LicenseObject</code>s this object is associated with. If there
+ * are none, an empty list will be returned.
+ */
+ public List<LicenseObject> getLicenses();
+
+ /**
+ * Returns all associations this group has with a given bundle.
+ */
+ public List<Artifact2GroupAssociation> getAssociationsWith(ArtifactObject artifact);
+ /**
+ * Returns all associations this group has with a given license.
+ */
+ public List<Group2LicenseAssociation> getAssociationsWith(LicenseObject license);
+
+ /**
+ * Returns the name of this bundle.
+ */
+ public String getName();
+ /**
+ * Sets the name of this bundle.
+ */
+ public void setName(String name);
+ /**
+ * Returns the description of this bundle.
+ */
+ public String getDescription();
+ /**
+ * Sets the description of this bundle.
+ */
+ public void setDescription(String description);
+
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/License2GatewayAssociation.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/License2GatewayAssociation.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/License2GatewayAssociation.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/License2GatewayAssociation.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,15 @@
+package net.luminis.liq.client.repository.object;
+
+import net.luminis.liq.client.repository.Association;
+
+/**
+ * Interface to a License2GatewayAssociation. Most functionality is defined by the generic Association.
+ */
+public interface License2GatewayAssociation extends Association<LicenseObject, GatewayObject> {
+ public static final String TOPIC_ENTITY_ROOT = License2GatewayAssociation.class.getSimpleName() + "/";
+
+ public static final String TOPIC_ADDED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ADDED_SUFFIX;
+ public static final String TOPIC_REMOVED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_REMOVED_SUFFIX;
+ public static final String TOPIC_CHANGED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_CHANGED_SUFFIX;
+ public static final String TOPIC_ALL = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ALL_SUFFIX;
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/LicenseObject.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/LicenseObject.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/LicenseObject.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/object/LicenseObject.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,58 @@
+package net.luminis.liq.client.repository.object;
+
+import java.util.List;
+
+import net.luminis.liq.client.repository.RepositoryObject;
+
+/**
+ * Interface to a LicenseObject. The basic functionality is defined by RepositoryObject, but extended for
+ * License-specific information.
+ */
+public interface LicenseObject extends RepositoryObject {
+ public static final String TOPIC_ENTITY_ROOT = LicenseObject.class.getSimpleName() + "/";
+
+ public static final String TOPIC_ADDED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ADDED_SUFFIX;
+ public static final String TOPIC_REMOVED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_REMOVED_SUFFIX;
+ public static final String TOPIC_CHANGED = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_CHANGED_SUFFIX;
+ public static final String TOPIC_ALL = PUBLIC_TOPIC_ROOT + TOPIC_ENTITY_ROOT + TOPIC_ALL_SUFFIX;
+
+ public static final String KEY_DESCRIPTION = "description";
+ public static final String KEY_NAME = "name";
+
+ /**
+ * Returns all <code>GroupObject</code>s this object is associated with. If there
+ * are none, an empty list will be returned.
+ */
+ public List<GroupObject> getGroups();
+ /**
+ * Returns all <code>GatewayObject</code>s this object is associated with. If there
+ * are none, an empty list will be returned.
+ */
+ public List<GatewayObject> getGateways();
+
+ /**
+ * Returns all associations this license has with a given group.
+ */
+ public List<Group2LicenseAssociation> getAssociationsWith(GroupObject group);
+ /**
+ * Returns all associations this license has with a given gateway.
+ */
+ public List<License2GatewayAssociation> getAssociationsWith(GatewayObject gateway);
+
+ /**
+ * Returns the name of this bundle.
+ */
+ public String getName();
+ /**
+ * Sets the name of this bundle.
+ */
+ public void setName(String name);
+ /**
+ * Returns the description of this bundle.
+ */
+ public String getDescription();
+ /**
+ * Sets the description of this bundle.
+ */
+ public void setDescription(String description);
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/Artifact2GroupAssociationRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/Artifact2GroupAssociationRepository.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/Artifact2GroupAssociationRepository.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/Artifact2GroupAssociationRepository.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,12 @@
+package net.luminis.liq.client.repository.repository;
+
+import net.luminis.liq.client.repository.AssociationRepository;
+import net.luminis.liq.client.repository.object.Artifact2GroupAssociation;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+import net.luminis.liq.client.repository.object.GroupObject;
+
+/**
+ * Interface to a Artifact2GroupAssociationRepository. The functionality is defined by the generic AssociationRepository.
+ */
+public interface Artifact2GroupAssociationRepository extends AssociationRepository<ArtifactObject, GroupObject, Artifact2GroupAssociation> {
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/ArtifactRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/ArtifactRepository.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/ArtifactRepository.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/ArtifactRepository.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,92 @@
+package net.luminis.liq.client.repository.repository;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.List;
+
+import net.luminis.liq.client.repository.ObjectRepository;
+import net.luminis.liq.client.repository.helper.PropertyResolver;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+import net.luminis.liq.client.repository.object.GatewayObject;
+
+/**
+ * Interface to a ArtifactRepository. The functionality is defined by the generic AssociationRepository.
+ */
+public interface ArtifactRepository extends ObjectRepository<ArtifactObject>{
+ /**
+ * Gets a list of all ArtifactObject's which are resource processing bundles.
+ */
+ public List<ArtifactObject> getResourceProcessors();
+
+ /**
+ * Tries to import an artifact into storage, while extracting necessary metadata.
+ * @param artifact a URL pointing to the 'physical' artifact.
+ * @param upload Indicates whether this artifact should be uploaded to our own OBR.
+ * @return An <code>ArtifactObject</code> representing the passed in artifact, if
+ * (a) the artifact is recognized, (b) there is storage available and (c) there is
+ * a resource processor available for this type of artifact.
+ * @throws IllegalArgumentException when the <code>artifact</code> cannot be processed.
+ * @throws IOException when there is a problem transferring the <code>artifact</code> to storage.
+ */
+ public ArtifactObject importArtifact(URL artifact, boolean upload) throws IllegalArgumentException, IOException;
+
+ /**
+ * Checks whether an artifact is 'usable', that is, there is a resource processor available for it,
+ * if necessary.
+ * @param artifact A URL pointing to an artifact.
+ * @return <code>true</code> if the artifact is recognized, and a processor for it is available. <code>false</code>
+ * otherwise, including when the artifact cannot be reached.
+ */
+ public boolean recognizeArtifact(URL artifact);
+
+ /**
+ * Tries to import an artifact into storage, while extracting necessary metadata.
+ * @param artifact a URL pointing to the 'physical' artifact.
+ * @param mimetype a String giving this object's mimetype.
+ * @param upload Indicates whether this artifact should be uploaded to our own OBR.
+ * @return An <code>ArtifactObject</code> representing the passed in artifact, if
+ * (a) there is storage available and (b) there is a resource processor
+ * available for this type of artifact.
+ * @throws IllegalArgumentException when the <code>artifact</code> cannot be processed.
+ * @throws IOException when there is a problem transferring the <code>artifact</code> to storage.
+ */
+ public ArtifactObject importArtifact(URL artifact, String mimetype, boolean upload) throws IllegalArgumentException, IOException;
+
+ /**
+ * Tries to locate a preprocessor for the passed artifact, an processes it. If no processing
+ * needs to be done, the original artifact's URL will be returned.
+ * @param artifact An artifact
+ * @param props A tree of properties objects, to be used for replacement.
+ * @param gatewayID The gatewayID of the gateway for which this artifact is being processed.
+ * @param version The deployment version for which this artifact is being processed.
+ * @return A URL to a new, processed artifact, or to the original one, in case nothing needed to be processed.
+ * @throws IOException Thrown if reading the original artifact goes wrong, or storing the processed one.
+ */
+ public String preprocessArtifact(ArtifactObject artifact, GatewayObject gateway, String gatewayID, String version) throws IOException ;
+
+ /**
+ * Indicates whether the template should be processed again, given the properties, and the version to which it
+ * should be compared.
+ * @param url A string representing a URL to the original artifact.
+ * @param props A PropertyResolver which can be used to fill in 'holes' in the template.
+ * @param gatewayID The gatewayID of the gateway for which this artifact is being processed.
+ * @param version The deployment version for which this artifact is being processed.
+ * @param lastVersion The deployment version to which the current one should be compared.
+ * @param newVersion The new, potential version.
+ * @param obrBase A base OBR to upload the new artifact to.
+ * @return Whether or not a new version has to be created.
+ * @throws IOException
+ */
+ public boolean needsNewVersion(ArtifactObject artifact, GatewayObject gateway, String gatewayID, String fromVersion);
+
+ /**
+ * Sets the OBR that this artifact repository should use to upload artifacts to.
+ */
+ public void setObrBase(URL obrBase);
+
+ /**
+ * Gets the OBR that this artifact repository should use to upload artifacts to.
+ * Note that this method may return <code>null</code> if no base was set earlier.
+ */
+ public URL getObrBase();
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/DeploymentVersionRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/DeploymentVersionRepository.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/DeploymentVersionRepository.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/DeploymentVersionRepository.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,45 @@
+package net.luminis.liq.client.repository.repository;
+
+import java.util.List;
+import java.util.Map;
+
+import net.luminis.liq.client.repository.ObjectRepository;
+import net.luminis.liq.client.repository.object.DeploymentArtifact;
+import net.luminis.liq.client.repository.object.DeploymentVersionObject;
+
+/**
+ * Interface to a DeploymentVersionRepository. The functionality is defined by the generic ObjectRepository.
+ */
+public interface DeploymentVersionRepository extends ObjectRepository<DeploymentVersionObject> {
+ /**
+ * Creates a new inhabitant based on the given attributes and bundle URLs. The object
+ * will be stored in this repository's store, and will be returned.
+ * @throws IllegalArgumentException Will be thrown when the attributes cannot be accepted.
+ */
+ public DeploymentVersionObject create(Map<String, String> attributes, Map<String, String> tags, DeploymentArtifact[] artifacts);
+
+ /**
+ * Gets all available deployment versions for this gateway. If none can be
+ * found, an empty list will be returned.
+ * @param gatewayID The gateway to be used.
+ * @return A list of <code>DeploymentVersionObject</code>s which are related to
+ * this gateway, sorted lexically by version.
+ */
+ public List<DeploymentVersionObject> getDeploymentVersions(String gatewayID);
+
+ /**
+ * Get the most recent known deployment version for a given gateway.
+ * @param gatewayID The gateway to be used.
+ * @return A <code>DeploymentVersionObject</code> which is the most recent one to be deployed
+ * to the gateway. If none can be found, <code>null</code> will be returned.
+ */
+ public DeploymentVersionObject getMostRecentDeploymentVersion(String gatewayID);
+
+ /**
+ * Creates a DeploymentArtifact object.
+ * @param url The url to be used in this object.
+ * @param directives A map of directives to be packed into the object.
+ * @return The newly created deployment artifact object.
+ */
+ public DeploymentArtifact createDeploymentArtifact(String url, Map<String, String> directives);
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/GatewayRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/GatewayRepository.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/GatewayRepository.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/GatewayRepository.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,10 @@
+package net.luminis.liq.client.repository.repository;
+
+import net.luminis.liq.client.repository.ObjectRepository;
+import net.luminis.liq.client.repository.object.GatewayObject;
+
+/**
+ * Interface to a GatewayRepository. The functionality is defined by the generic AssociationRepository.
+ */
+public interface GatewayRepository extends ObjectRepository<GatewayObject>{
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/Group2LicenseAssociationRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/Group2LicenseAssociationRepository.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/Group2LicenseAssociationRepository.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/Group2LicenseAssociationRepository.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,12 @@
+package net.luminis.liq.client.repository.repository;
+
+import net.luminis.liq.client.repository.AssociationRepository;
+import net.luminis.liq.client.repository.object.Group2LicenseAssociation;
+import net.luminis.liq.client.repository.object.GroupObject;
+import net.luminis.liq.client.repository.object.LicenseObject;
+
+/**
+ * Interface to a Group2LicenseAssociationRepository. The functionality is defined by the generic AssociationRepository.
+ */
+public interface Group2LicenseAssociationRepository extends AssociationRepository<GroupObject, LicenseObject, Group2LicenseAssociation> {
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/GroupRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/GroupRepository.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/GroupRepository.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/GroupRepository.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,10 @@
+package net.luminis.liq.client.repository.repository;
+
+import net.luminis.liq.client.repository.ObjectRepository;
+import net.luminis.liq.client.repository.object.GroupObject;
+
+/**
+ * Interface to a GroupRepository. The functionality is defined by the generic AssociationRepository.
+ */
+public interface GroupRepository extends ObjectRepository<GroupObject> {
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/License2GatewayAssociationRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/License2GatewayAssociationRepository.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/License2GatewayAssociationRepository.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/License2GatewayAssociationRepository.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,20 @@
+package net.luminis.liq.client.repository.repository;
+
+import net.luminis.liq.client.repository.AssociationRepository;
+import net.luminis.liq.client.repository.object.GatewayObject;
+import net.luminis.liq.client.repository.object.License2GatewayAssociation;
+import net.luminis.liq.client.repository.object.LicenseObject;
+
+/**
+ * Interface to a License2GatewayAssociationRepository. The functionality is defined by the generic AssociationRepository.
+ */
+public interface License2GatewayAssociationRepository extends AssociationRepository<LicenseObject, GatewayObject, License2GatewayAssociation> {
+ /**
+ * Creates an assocation from a given license to multiple gateways, which correspond to the given
+ * filter string. For parameters to use in the filter, see <code>GatewayObject</code>'s <code>KEY_</code> constants.
+ * @param license A license object for the left side of this association.
+ * @param gatewayFilter An LDAP-filter for the gateways to use.
+ * @return The newly created association.
+ */
+ public License2GatewayAssociation createLicense2GatewayFilter(LicenseObject license, String gatewayFilter);
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/LicenseRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/LicenseRepository.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/LicenseRepository.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/repository/LicenseRepository.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,10 @@
+package net.luminis.liq.client.repository.repository;
+
+import net.luminis.liq.client.repository.ObjectRepository;
+import net.luminis.liq.client.repository.object.LicenseObject;
+
+/**
+ * Interface to a LicenseRepository. The functionality is defined by the generic AssociationRepository.
+ */
+public interface LicenseRepository extends ObjectRepository<LicenseObject>{
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/stateful/StatefulGatewayObject.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/stateful/StatefulGatewayObject.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/stateful/StatefulGatewayObject.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/stateful/StatefulGatewayObject.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,191 @@
+package net.luminis.liq.client.repository.stateful;
+
+import java.util.List;
+
+import net.luminis.liq.client.repository.RepositoryObject;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+import net.luminis.liq.client.repository.object.DeploymentArtifact;
+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.log.LogEvent;
+
+/**
+ * <code>StatefulGatewayObject</code> represents the information that a <code>GatewayObject</code>
+ * has, plus added functionality for gathering information from a deployment repository and,
+ * optionally, from an AuditLog.
+ */
+public interface StatefulGatewayObject extends RepositoryObject {
+
+ public static final String TOPIC_ADDED = StatefulGatewayObject.class.getName().replace('.', '/') + "/ADDED";
+ public static final String TOPIC_REMOVED = StatefulGatewayObject.class.getName().replace('.', '/') + "/REMOVED";
+ public static final String TOPIC_CHANGED = StatefulGatewayObject.class.getName().replace('.', '/') + "/CHANGED";
+ public static final String TOPIC_STATUS_CHANGED = StatefulGatewayObject.class.getName().replace('.', '/') + "/STATUS_CHANGED";
+ /** Indicates a change to the audit events for the StatefulGatewayObject in "entity".*/
+ public static final String TOPIC_AUDITEVENTS_CHANGED = StatefulGatewayObject.class.getName().replace('.', '/') + "/AUDITEVENTS_CHANGED";
+ /** Key used in the event with topic <code>TOPIC_AUDITEVENTS_CHANGED</code>. Contains a List<LogDescriptor> containing all
+ * events we have not seen yet. NOTE: The first auditevent "change" causing the <code>StatefulGatewayObject</code> to
+ * be instantiated will trigger a <code>TOPIC_AUDITEVENTS_CHANGED</code> event *before* a <code>TOPIC_ADDED</code> event. */
+ public static final String KEY_AUDITEVENTS = "auditevents";
+ public static final String TOPIC_ALL = StatefulGatewayObject.class.getName().replace('.', '/') + "/*";
+
+ public final static String KEY_ID = GatewayObject.KEY_ID;
+ public final static String KEY_REGISTRATION_STATE = "KEY_REGISTRATION_STATE";
+ public final static String KEY_STORE_STATE = "KEY_STORE_STATE";
+ public final static String KEY_PROVISIONING_STATE = "KEY_PROVISIONING_STATE";
+ public final static String KEY_LAST_INSTALL_VERSION = "KEY_LAST_INSTALL_VERSION";
+ public final static String KEY_LAST_INSTALL_SUCCESS = "KEY_LAST_INSTALL_SUCCESS";
+ public final static String KEY_ACKNOWLEDGED_INSTALL_VERSION = "KEY_ACKNOWLEDGED_INSTALL_VERSION";
+ public final static String[] KEYS_ALL = new String[] {KEY_ID, KEY_REGISTRATION_STATE, KEY_STORE_STATE, KEY_PROVISIONING_STATE, KEY_LAST_INSTALL_VERSION, KEY_LAST_INSTALL_SUCCESS, KEY_ACKNOWLEDGED_INSTALL_VERSION};
+
+ /**
+ * Represents a current deployment package version which cannot be found, i.e.,
+ * either there is no information about deployment packages in the AuditLog,
+ * or no AuditLog is available.
+ */
+ public final static String UNKNOWN_VERSION = "(unknown)";
+
+ /**
+ * Gets the current registration status of the gateway.
+ */
+ public RegistrationState getRegistrationState();
+
+ /**
+ * Gets the current store status of the gateway.
+ */
+ public StoreState getStoreState();
+
+ /**
+ * Gets the current provisioning status of the gateway.
+ */
+ public ProvisioningState getProvisioningState();
+
+ /**
+ * Gets the most recent deployment package version on the gateway, according
+ * to the deployment repository. If no version can be determined,
+ * <code>UNKNOWN_VERSION</code> will be returned.
+ */
+ public String getCurrentVersion();
+
+ /**
+ * Gets the list of AuditLog Events for this gateway. If no auditlog events
+ * can be found, and empty list will be returned. The events are ordered ascending by timestamp.
+ */
+ public List<LogEvent> getAuditEvents();
+
+ /**
+ * Registers this gateway, which for now only exists in the AuditLog, into the
+ * <code>GatewayRepository</code>.
+ * @throws IllegalStateException when the precondition is not met, i.e., the
+ * gateway is not known only in the AuditLog, but also in the <code>GatewayRepository</code>.
+ */
+ public void register() throws IllegalStateException;
+
+ /**
+ * Indicates whether this <code>StatefulGatewayObject</code> is backed by a <code>GatewayObject</code>.
+ * @return whether this <code>StatefulGatewayObject</code> is backed by a <code>GatewayObject</code>.
+ */
+ public boolean isRegistered();
+
+ /**
+ * Approves all differences between what is currently in the shop and gateway operator
+ * repository, and the deployment repository. This will generate a new version in the
+ * deployment repository.
+ * @return The number of the new version.
+ * @throws IllegalStateException when it is currently not possible to create a deployment version.
+ */
+ public String approve();
+
+ /**
+ * Indicates whether an <code>approve()</code> is necessary, i.e., there is a difference between
+ * the set of bundles for this gateway according to the shop, and according to the deployment
+ * repository.
+ * @return <code>true</code> if there is a difference between the shop and deployment repository;
+ * <code>false</code> otherwise.
+ */
+ public boolean needsApprove();
+
+ /**
+ * Returns the auto-approval flag for this gateway.
+ * @return <code>true</code> if auto approve has been set;
+ * <code>false</code> otherwise.
+ */
+ public boolean getAutoApprove();
+
+ /**
+ * Set the auto approve value for this gateway, the property is stored within the gateway
+ * @param approve <code>true</code> to enable auto approve;
+ * <code>false</code> otherwise.
+ */
+ public void setAutoApprove(boolean approve);
+
+ /**
+ * Gets the list of artifact objects that should be on the gateway, according to the shop.
+ * @return the list of artifact objects that should be on the gateway, according to the shop.
+ */
+ public ArtifactObject[] getArtifactsFromShop();
+
+ /**
+ * Gets the list of deployment artifacts that should be on the gateway, according to the deployment repository.
+ * @return the list of artifact objects that should be on the gateway, according to the deployment repository.
+ */
+ public DeploymentArtifact[] getArtifactsFromDeployment();
+
+ /**
+ * Returns the latest available installed version in the auditlog.
+ * @return The latest version statement from the auditlog for an install if
+ * one is available; otherwise, an empty string.
+ */
+ public String getLastInstallVersion();
+
+ /**
+ * Returns whether the last install on the gateway way successful.
+ * @return <code>true</code> if there information about a last install and
+ * that was successful, <code>false</code> otherwise.
+ */
+ public boolean getLastInstallSuccess();
+
+ /**
+ * Signals to the object that the outcome of a given install on the gateway
+ * is 'seen', and that the <code>ProvisioningState</code> can now return to <code>Idle</code>.
+ * @param version A string representing a version.
+ */
+ public void acknowledgeInstallVersion(String version);
+
+ /**
+ * Gets the underlying <code>GatewayObject</code> of this <code>StatefulGatewayObject</code>.
+ * @return The <code>GatewayObject</code> linked to this <code>StatefulGatewayObject</code>; if none
+ * is available, an <code>IllegalStateException</code> will be thrown.
+ */
+ public GatewayObject getGatewayObject();
+
+ /**
+ * Returns all <code>LicenseObject</code>s this object is associated with. If there
+ * are none, an empty list will be returned.
+ */
+ public List<LicenseObject> getLicenses();
+
+ /**
+ * Returns all associations this gateway has with a given license.
+ */
+ public List<License2GatewayAssociation> getAssociationsWith(LicenseObject license);
+
+ /**
+ * Gets the ID of this GatewayObject.
+ */
+ public String getID();
+
+ public enum RegistrationState {
+ Unregistered, Registered;
+ }
+
+ public enum StoreState {
+ New, Unapproved, Approved;
+ }
+
+ public enum ProvisioningState {
+ Idle, InProgress, OK, Failed;
+ }
+
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/stateful/StatefulGatewayRepository.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/stateful/StatefulGatewayRepository.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/stateful/StatefulGatewayRepository.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/stateful/StatefulGatewayRepository.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,37 @@
+package net.luminis.liq.client.repository.stateful;
+
+import java.util.Map;
+
+import net.luminis.liq.client.repository.ObjectRepository;
+
+/**
+ * Represents a repository of <ode>StatefulGatewayObject</code>'s.
+ */
+public interface StatefulGatewayRepository extends ObjectRepository<StatefulGatewayObject> {
+
+ /**
+ * Registers a gateway with given attributes. This will result in the creation
+ * of a <code>GatewayObject</code> in the <code>GatewayRepository</code>, and
+ * the creation of a <code>StatefulGatewayObject</code>, which will also be
+ * returned.
+ * @param attributes The attributes to create the <code>GatewayObject</code> with.
+ * @return The newly registered gateway object.
+ */
+ public StatefulGatewayObject preregister(Map<String, String> attributes, Map<String, String> tags);
+
+ /**
+ * Unregisters a gateway, removing it from the <code>GatewayRepository</code>. Note
+ * that a <code>StatefulGatewayObject</code> might stay around if it is backed
+ * by audit log entries. If the given ID is not that of an existing <code>GatewayObject</code>,
+ * an <code>IllegalArgumentException</code> will be thrown.
+ * @param gatewayID A string representing a gateway ID.
+ */
+ public void unregister(String gatewayID);
+
+ /**
+ * Explicitly instruct the <code>StatefulGatewayRepository</code> to update
+ * its contents; for instance, after syncing the audit log.
+ */
+ public void refresh();
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/stateful/impl/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/stateful/impl/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/stateful/impl/Activator.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/stateful/impl/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,70 @@
+package net.luminis.liq.client.repository.stateful.impl;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import net.luminis.liq.client.repository.RepositoryAdmin;
+import net.luminis.liq.client.repository.helper.bundle.BundleHelper;
+import net.luminis.liq.client.repository.object.Artifact2GroupAssociation;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+import net.luminis.liq.client.repository.object.DeploymentVersionObject;
+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 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.stateful.StatefulGatewayRepository;
+import net.luminis.liq.server.log.store.LogStore;
+
+import org.apache.felix.dependencymanager.DependencyActivatorBase;
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+import org.osgi.service.log.LogService;
+
+/**
+ * Activator for the StatefulGatewayRepository bundle.
+ */
+public class Activator extends DependencyActivatorBase {
+
+ @Override
+ public synchronized void init(BundleContext context, DependencyManager manager) throws Exception {
+ StatefulGatewayRepositoryImpl statefulGatewayRepositoryImpl = new StatefulGatewayRepositoryImpl();
+ manager.add(createService()
+ .setInterface(StatefulGatewayRepository.class.getName(), null)
+ .setImplementation(statefulGatewayRepositoryImpl)
+ .add(createServiceDependency().setService(ArtifactRepository.class).setRequired(true))
+ .add(createServiceDependency().setService(GatewayRepository.class).setRequired(true))
+ .add(createServiceDependency().setService(DeploymentVersionRepository.class).setRequired(true))
+ .add(createServiceDependency().setService(LogStore.class, "(&("+Constants.OBJECTCLASS+"="+LogStore.class.getName()+")(name=auditlog))").setRequired(false))
+ .add(createServiceDependency().setService(BundleHelper.class).setRequired(true))
+ .add(createServiceDependency().setService(EventAdmin.class).setRequired(true))
+ .add(createServiceDependency().setService(LogService.class).setRequired(false)));
+ Dictionary<String, String[]> topic = new Hashtable<String, String[]>();
+ topic.put(EventConstants.EVENT_TOPIC, new String[] {
+ ArtifactObject.TOPIC_ALL,
+ Artifact2GroupAssociation.TOPIC_ALL,
+ GroupObject.TOPIC_ALL,
+ Group2LicenseAssociation.TOPIC_ALL,
+ LicenseObject.TOPIC_ALL,
+ License2GatewayAssociation.TOPIC_ALL,
+ GatewayObject.TOPIC_ALL,
+ DeploymentVersionObject.TOPIC_ALL,
+ RepositoryAdmin.TOPIC_REFRESH, RepositoryAdmin.TOPIC_LOGIN});
+ manager.add(createService()
+ .setInterface(EventHandler.class.getName(), topic)
+ .setImplementation(statefulGatewayRepositoryImpl));
+ }
+
+ @Override
+ public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ // service deregistration will happen automatically.
+ }
+
+}