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 [9/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/ne...
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/bundle/BundleHelper.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/bundle/BundleHelper.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/bundle/BundleHelper.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/bundle/BundleHelper.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,37 @@
+package net.luminis.liq.client.repository.helper.bundle;
+
+import net.luminis.liq.client.repository.helper.ArtifactHelper;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+
+import org.osgi.framework.Constants;
+
+/**
+ * Definitions for a BundleHelper, which are used to treat an artifact as a bundle.
+ */
+public interface BundleHelper extends ArtifactHelper {
+ public static final String KEY_SYMBOLICNAME = Constants.BUNDLE_SYMBOLICNAME;
+ public static final String KEY_NAME = Constants.BUNDLE_NAME;
+ public static final String KEY_VERSION = Constants.BUNDLE_VERSION;
+ public static final String KEY_VENDOR = Constants.BUNDLE_VENDOR;
+ public static final String KEY_RESOURCE_PROCESSOR_PID = "Deployment-ProvidesResourceProcessor";
+
+ public static final String MIMETYPE = "application/vnd.osgi.bundle";
+
+ /**
+ * Used to include an OSGi version range (see section 3.2.5 of the core specification) with an association.
+ * When included in the association's properties, this statement will cause the association to automatically
+ * match the highest available bundle version that matches the statement; an open ended range can be
+ * created by passing "0.0.0".<br>
+ * Not specifying this attribute will lead to the <code>Artifact2GroupAssociation</code<'s default behavior,
+ * using all matches for the filter string.
+ */
+ public static final String KEY_ASSOCIATION_VERSIONSTATEMENT = "associationVersionStatement";
+
+ public boolean isResourceProcessor(ArtifactObject object);
+ public String getResourceProcessorPIDs(ArtifactObject object);
+ public String getSymbolicName(ArtifactObject object);
+ public String getName(ArtifactObject object);
+ public String getVersion(ArtifactObject object);
+ public String getVendor(ArtifactObject object);
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/bundle/impl/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/bundle/impl/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/bundle/impl/Activator.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/bundle/impl/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,41 @@
+package net.luminis.liq.client.repository.helper.bundle.impl;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import net.luminis.liq.client.repository.helper.ArtifactHelper;
+import net.luminis.liq.client.repository.helper.ArtifactRecognizer;
+import net.luminis.liq.client.repository.helper.bundle.BundleHelper;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+
+import org.apache.felix.dependencymanager.DependencyActivatorBase;
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Activator class for the Bundle ArtifactHelper.
+ */
+public class Activator extends DependencyActivatorBase {
+
+ @Override
+ public synchronized void init(BundleContext context, DependencyManager manager) throws Exception {
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put(ArtifactObject.KEY_MIMETYPE, BundleHelper.MIMETYPE);
+ BundleHelperImpl helperImpl = new BundleHelperImpl();
+ manager.add(createService()
+ .setInterface(ArtifactHelper.class.getName(), props)
+ .setImplementation(helperImpl));
+ manager.add(createService()
+ .setInterface(ArtifactRecognizer.class.getName(), null)
+ .setImplementation(helperImpl));
+ manager.add(createService()
+ .setInterface(BundleHelper.class.getName(), null)
+ .setImplementation(helperImpl));
+ }
+
+ @Override
+ public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ // Nothing to do
+ }
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/bundle/impl/BundleHelperImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/bundle/impl/BundleHelperImpl.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/bundle/impl/BundleHelperImpl.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/bundle/impl/BundleHelperImpl.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,264 @@
+package net.luminis.liq.client.repository.helper.bundle.impl;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.Attributes;
+import java.util.jar.JarInputStream;
+import java.util.jar.Manifest;
+
+import net.luminis.liq.client.repository.RepositoryUtil;
+import net.luminis.liq.client.repository.helper.ArtifactHelper;
+import net.luminis.liq.client.repository.helper.ArtifactPreprocessor;
+import net.luminis.liq.client.repository.helper.ArtifactRecognizer;
+import net.luminis.liq.client.repository.helper.bundle.BundleHelper;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+import net.luminis.liq.util.VersionRange;
+
+import org.osgi.framework.Version;
+
+/**
+ * BundleHelperImpl provides the Artifact Repository with Helper and Recognizer services.
+ */
+public class BundleHelperImpl implements ArtifactRecognizer, BundleHelper {
+ /** A custom <code>Comparator</code>, used to sort bundles in increasing version */
+ private static final Comparator <ArtifactObject> BUNDLE_COMPARATOR = new Comparator<ArtifactObject>() {
+ public int compare(ArtifactObject left, ArtifactObject right) {
+ Version vLeft = new Version(left.getAttribute(BundleHelper.KEY_VERSION));
+ Version vRight = new Version(right.getAttribute(BundleHelper.KEY_VERSION));
+ return vRight.compareTo(vLeft);
+ }
+ };
+
+ /*
+ * From ArtifactHelper
+ */
+
+ public boolean canUse(ArtifactObject object) {
+ if (object == null) {
+ return false;
+ }
+ return (object.getMimetype().equals(MIMETYPE));
+ }
+
+ public <TYPE extends ArtifactObject> String getAssociationFilter(TYPE obj, Map<String, String> properties) {
+ /*
+ * Creates an endpoint filter for an association. If there is a KEY_ASSOCIATION_VERSIONSTATEMENT, a filter
+ * will be created that matches exactly the given range.
+ */
+ if ((properties != null) && properties.containsKey(KEY_ASSOCIATION_VERSIONSTATEMENT)) {
+ String versions = properties.get(KEY_ASSOCIATION_VERSIONSTATEMENT);
+ VersionRange versionRange = null;
+ try {
+ versionRange = VersionRange.parse(versions);
+ }
+ catch (IllegalArgumentException iae) {
+ throw new IllegalArgumentException("version " + ((versions != null) ? versions + " " : "(null) ") + "cannot be parsed into a valid version range statement.");
+ }
+
+ StringBuilder bundleStatement = new StringBuilder("(&(" + KEY_SYMBOLICNAME + "=" + RepositoryUtil.escapeFilterValue(obj.getAttribute(KEY_SYMBOLICNAME)) + ")");
+
+ bundleStatement.append("(" + KEY_VERSION + ">=" + versionRange.getLow() + ")");
+ if (!versionRange.isLowInclusive()) {
+ bundleStatement.append("(!(" + KEY_VERSION + "=" + versionRange.getLow() + "))");
+ }
+
+ if (versionRange.getHigh() != null) {
+ bundleStatement.append("(" + KEY_VERSION + "<=" + versionRange.getHigh() + ")");
+ if (!versionRange.isHighInclusive()) {
+ bundleStatement.append("(!(" + KEY_VERSION + "=" + versionRange.getHigh() + "))");
+ }
+ }
+
+ bundleStatement.append(")");
+
+ return bundleStatement.toString();
+ }
+ else
+ {
+ if (obj.getAttribute(KEY_VERSION) != null) {
+ return "(&(" + KEY_SYMBOLICNAME + "=" + RepositoryUtil.escapeFilterValue(obj.getAttribute(KEY_SYMBOLICNAME)) + ")(" + KEY_VERSION + "=" + RepositoryUtil.escapeFilterValue(obj.getAttribute(KEY_VERSION)) + "))";
+ }
+ else {
+ return "(&(" + KEY_SYMBOLICNAME + "=" + RepositoryUtil.escapeFilterValue(obj.getAttribute(KEY_SYMBOLICNAME)) + ")(!(" + KEY_VERSION + "=*)))";
+ }
+ }
+ }
+
+ public <TYPE extends ArtifactObject> int getCardinality(TYPE obj, Map<String, String> properties) {
+ /* Normally, all objects that match the filter given by the previous version should be part of the
+ * association. However, when a version statement has been given, only one should be used. */
+ if ((properties != null) && properties.containsKey(BundleHelper.KEY_ASSOCIATION_VERSIONSTATEMENT)) {
+ return 1;
+ }
+ else {
+ return Integer.MAX_VALUE;
+ }
+ }
+
+ public Comparator<ArtifactObject> getComparator() {
+ return BUNDLE_COMPARATOR;
+ }
+
+ public Map<String, String> checkAttributes(Map<String, String> attributes) {
+ return normalizeVersion(attributes);
+ }
+
+ /**
+ * For the filter to work correctly, we need to make sure the version statement is an
+ * OSGi version.
+ */
+ private static Map<String, String> normalizeVersion(Map<String, String> input) {
+ String version = input.get(KEY_VERSION);
+ if (version != null) {
+ try {
+ Version theVersion = new Version(version);
+ input.put(KEY_VERSION, theVersion.toString());
+ }
+ catch (IllegalArgumentException iae) {
+ throw new IllegalArgumentException("The version statement in the bundle cannot be parsed to a valid version.", iae);
+ }
+ }
+
+ return input;
+ }
+
+ /*
+ * From BundleHelper
+ */
+
+ public String[] getDefiningKeys() {
+ return new String[] {KEY_SYMBOLICNAME, KEY_VERSION};
+ }
+
+ public String[] getMandatoryAttributes() {
+ return new String[] {KEY_SYMBOLICNAME};
+ }
+
+ public String getResourceProcessorPIDs(ArtifactObject object) {
+ ensureBundle(object);
+ return object.getAttribute(KEY_RESOURCE_PROCESSOR_PID);
+ }
+
+ public String getSymbolicName(ArtifactObject object) {
+ ensureBundle(object);
+ return object.getAttribute(KEY_SYMBOLICNAME);
+ }
+
+ public String getName(ArtifactObject object) {
+ ensureBundle(object);
+ return object.getAttribute(KEY_NAME);
+ }
+
+ public String getVersion(ArtifactObject object) {
+ ensureBundle(object);
+ return object.getAttribute(KEY_VERSION);
+ }
+
+ public String getVendor(ArtifactObject object) {
+ ensureBundle(object);
+ return object.getAttribute(KEY_VENDOR);
+ }
+
+ public boolean isResourceProcessor(ArtifactObject object) {
+ ensureBundle(object);
+ return object.getAttribute(KEY_RESOURCE_PROCESSOR_PID) != null;
+ }
+
+ private void ensureBundle(ArtifactObject object) {
+ if ((object == null) || !object.getMimetype().equals(MIMETYPE)) {
+ throw new IllegalArgumentException("This ArtifactObject cannot be handled by a BundleHelper.");
+ }
+ }
+
+ /*
+ * From ArtifactRecognizer
+ */
+
+ public boolean canHandle(String mimetype) {
+ return MIMETYPE.equals(mimetype);
+ }
+
+ public Map<String, String> extractMetaData(URL artifact) throws IllegalArgumentException {
+ /*
+ * Opens the URL as a Jar input stream, gets the manifest, and extracts headers from there.
+ */
+ JarInputStream jis = null;
+ try {
+ jis = new JarInputStream(artifact.openStream());
+
+ Attributes manifestAttributes = jis.getManifest().getMainAttributes();
+ Map<String, String> result = new HashMap<String, String>();
+
+ for (String key : new String[] {KEY_NAME, KEY_SYMBOLICNAME, KEY_VERSION, KEY_VENDOR, KEY_RESOURCE_PROCESSOR_PID}) {
+ String value = manifestAttributes.getValue(key);
+ if (value != null) {
+ result.put(key, value);
+ }
+ }
+
+ if (result.get(KEY_VERSION) == null) {
+ result.put(KEY_VERSION, "0.0.0");
+ }
+
+ result.put(ArtifactHelper.KEY_MIMETYPE, MIMETYPE);
+ result.put(ArtifactObject.KEY_PROCESSOR_PID, "");
+ String name = manifestAttributes.getValue(KEY_NAME);
+ String version = manifestAttributes.getValue(KEY_VERSION);
+ if (name == null) {
+ name = manifestAttributes.getValue(KEY_SYMBOLICNAME);
+ }
+ result.put(ArtifactObject.KEY_ARTIFACT_NAME, name + (version == null ? "" : "-" + version));
+
+ return result;
+ }
+ catch (Exception e) {
+ throw new IllegalArgumentException("Error extracting metadata from artifact.", e);
+ }
+ finally {
+ try {
+ jis.close();
+ }
+ catch (IOException e) {
+ // Too bad.
+ }
+ }
+ }
+
+ public String recognize(URL artifact) {
+ /*
+ * Tries to find out whether this artifact is a bundle by (a) trying to open it as a
+ * jar, (b) trying to extract the manifest, and (c) checking whether that manifest
+ * contains a Bundle-SymbolicName header.
+ */
+ JarInputStream jis = null;
+ try {
+ jis = new JarInputStream(artifact.openStream());
+
+ Manifest manifest = jis.getManifest();
+
+ Attributes mainAttributes = manifest.getMainAttributes();
+ if (mainAttributes.getValue(KEY_SYMBOLICNAME) != null) {
+ return MIMETYPE;
+ }
+ }
+ catch (Exception e) {
+ return null;
+ }
+ finally {
+ try {
+ jis.close();
+ }
+ catch (Exception e) {
+ // Too bad.
+ }
+ }
+ return null;
+ }
+
+ public ArtifactPreprocessor getPreprocessor() {
+ return null;
+ }
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/configuration/ConfigurationHelper.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/configuration/ConfigurationHelper.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/configuration/ConfigurationHelper.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/configuration/ConfigurationHelper.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,13 @@
+package net.luminis.liq.client.repository.helper.configuration;
+
+import net.luminis.liq.client.repository.helper.ArtifactHelper;
+
+/**
+ * Definitions for ConfigurationHelper,used to treat an artifact as an AutoConf file.
+ */
+public interface ConfigurationHelper extends ArtifactHelper {
+ public static final String KEY_FILENAME = "filename";
+
+ public static final String MIMETYPE = "application/xml:osgi-autoconf";
+ public static final String PROCESSOR = "org.osgi.deployment.rp.autoconf";
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/configuration/impl/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/configuration/impl/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/configuration/impl/Activator.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/configuration/impl/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,38 @@
+package net.luminis.liq.client.repository.helper.configuration.impl;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import net.luminis.liq.client.repository.helper.ArtifactHelper;
+import net.luminis.liq.client.repository.helper.ArtifactRecognizer;
+import net.luminis.liq.client.repository.helper.configuration.ConfigurationHelper;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+
+import org.apache.felix.dependencymanager.DependencyActivatorBase;
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Activator class for the Configuration ArtifactHelper.
+ */
+public class Activator extends DependencyActivatorBase {
+
+ @Override
+ public synchronized void init(BundleContext context, DependencyManager manager) throws Exception {
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put(ArtifactObject.KEY_MIMETYPE, ConfigurationHelper.MIMETYPE);
+ ConfigurationHelperImpl helperImpl = new ConfigurationHelperImpl();
+ manager.add(createService()
+ .setInterface(ArtifactHelper.class.getName(), props)
+ .setImplementation(helperImpl));
+ manager.add(createService()
+ .setInterface(ArtifactRecognizer.class.getName(), null)
+ .setImplementation(helperImpl));
+ }
+
+ @Override
+ public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ // Nothing to do
+ }
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,89 @@
+package net.luminis.liq.client.repository.helper.configuration.impl;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import net.luminis.liq.client.repository.helper.ArtifactPreprocessor;
+import net.luminis.liq.client.repository.helper.ArtifactRecognizer;
+import net.luminis.liq.client.repository.helper.base.VelocityArtifactPreprocessor;
+import net.luminis.liq.client.repository.helper.configuration.ConfigurationHelper;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+
+public class ConfigurationHelperImpl implements ArtifactRecognizer, ConfigurationHelper {
+
+ public boolean canHandle(String mimetype) {
+ return MIMETYPE.equals(mimetype);
+ }
+
+ public Map<String, String> extractMetaData(URL artifact) throws IllegalArgumentException {
+ Map<String, String> result = new HashMap<String, String>();
+ result.put(KEY_FILENAME, new File(artifact.getFile()).getName());
+ result.put(ArtifactObject.KEY_PROCESSOR_PID, PROCESSOR);
+ result.put(ArtifactObject.KEY_MIMETYPE, MIMETYPE);
+ result.put(ArtifactObject.KEY_ARTIFACT_NAME, result.get(KEY_FILENAME));
+ return result;
+ }
+
+ public String recognize(URL artifact) {
+ try {
+ InputStream in = artifact.openStream();
+ Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in);
+ Node first = doc.getFirstChild();
+ NamedNodeMap attributes = first.getAttributes();
+ Node metatype = attributes.getNamedItem("xmlns:metatype");
+ if (new String("http://www.osgi.org/xmlns/metatype/v1.0.0").equals(metatype.getTextContent())) {
+ return MIMETYPE;
+ }
+ }
+ catch (Exception e) {
+ // Does not matter.
+ }
+
+ return null;
+ }
+
+ public boolean canUse(ArtifactObject object) {
+ return MIMETYPE.equals(object.getMimetype());
+ }
+
+ public Map<String, String> checkAttributes(Map<String, String> attributes) {
+ // All necessary checks will be done by the constructor using getMandatoryAttributes.
+ return attributes;
+ }
+
+ public <TYPE extends ArtifactObject> String getAssociationFilter(TYPE obj, Map<String, String> properties) {
+ return "(" + KEY_FILENAME + "=" + obj.getAttribute(KEY_FILENAME) + ")";
+ }
+
+ public <TYPE extends ArtifactObject> int getCardinality(TYPE obj, Map<String, String> properties) {
+ return Integer.MAX_VALUE;
+ }
+
+ public Comparator<ArtifactObject> getComparator() {
+ return null;
+ }
+
+ public String[] getDefiningKeys() {
+ return new String[] {KEY_FILENAME};
+ }
+
+ public String[] getMandatoryAttributes() {
+ return new String[] {KEY_FILENAME};
+ }
+
+ private final static VelocityArtifactPreprocessor VELOCITY_ARTIFACT_PREPROCESSOR = new VelocityArtifactPreprocessor();
+ public ArtifactPreprocessor getPreprocessor() {
+ return VELOCITY_ARTIFACT_PREPROCESSOR;
+ }
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/user/UserAdminHelper.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/user/UserAdminHelper.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/user/UserAdminHelper.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/user/UserAdminHelper.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,11 @@
+package net.luminis.liq.client.repository.helper.user;
+
+import net.luminis.liq.client.repository.helper.ArtifactHelper;
+
+/**
+ * Definitions for the UserAdminHelper artifact helper.
+ */
+public interface UserAdminHelper extends ArtifactHelper {
+ public static final String MIMETYPE = "application/vnd.luminis.useradmin";
+ public static final String PROCESSOR = "net.luminis.liq.resourceprocessor.useradmin";
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/user/impl/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/user/impl/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/user/impl/Activator.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/user/impl/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,40 @@
+package net.luminis.liq.client.repository.helper.user.impl;
+
+import java.util.Properties;
+
+import net.luminis.liq.client.repository.helper.ArtifactHelper;
+import net.luminis.liq.client.repository.helper.ArtifactRecognizer;
+import net.luminis.liq.client.repository.helper.user.UserAdminHelper;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+
+import org.apache.felix.dependencymanager.DependencyActivatorBase;
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+/**
+ * Activator class for the UserAdmin ArtifactHelper.
+ */
+public class Activator extends DependencyActivatorBase {
+
+ @Override
+ public synchronized void init(BundleContext context, DependencyManager manager) throws Exception {
+ Properties props = new Properties();
+ props.put(ArtifactObject.KEY_MIMETYPE, UserAdminHelper.MIMETYPE);
+ UserHelperImpl helperImpl = new UserHelperImpl();
+ manager.add(createService()
+ .setInterface(ArtifactHelper.class.getName(), props)
+ .setImplementation(helperImpl));
+ props = new Properties();
+ props.put(Constants.SERVICE_RANKING, 10);
+ manager.add(createService()
+ .setInterface(ArtifactRecognizer.class.getName(), props)
+ .setImplementation(helperImpl));
+ }
+
+ @Override
+ public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ // Nothing to do
+ }
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/user/impl/UserHelperImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/user/impl/UserHelperImpl.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/user/impl/UserHelperImpl.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/helper/user/impl/UserHelperImpl.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,91 @@
+package net.luminis.liq.client.repository.helper.user.impl;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import net.luminis.liq.client.repository.helper.ArtifactPreprocessor;
+import net.luminis.liq.client.repository.helper.ArtifactRecognizer;
+import net.luminis.liq.client.repository.helper.base.VelocityArtifactPreprocessor;
+import net.luminis.liq.client.repository.helper.user.UserAdminHelper;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+public class UserHelperImpl implements ArtifactRecognizer, UserAdminHelper {
+
+ public boolean canHandle(String mimetype) {
+ return MIMETYPE.equals(mimetype);
+ }
+
+ public Map<String, String> extractMetaData(URL artifact) throws IllegalArgumentException {
+ Map<String, String> result = new HashMap<String, String>();
+ result.put(ArtifactObject.KEY_PROCESSOR_PID, PROCESSOR);
+ result.put(ArtifactObject.KEY_MIMETYPE, MIMETYPE);
+ result.put(ArtifactObject.KEY_ARTIFACT_NAME, new File(artifact.getFile()).getName());
+ return result;
+ }
+
+ public String recognize(URL artifact) {
+ try {
+ InputStream in = artifact.openStream();
+ Document doc = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(in);
+ Node root = doc.getFirstChild();
+ if (!root.getNodeName().equals("roles")) {
+ return null;
+ }
+ for (Node node = root.getFirstChild(); root != null; root = root.getNextSibling()) {
+ if (!node.getNodeName().equals("group") && !node.getNodeName().equals("user") && !node.getNodeName().equals("#text")) {
+ return null;
+ }
+ }
+ return MIMETYPE;
+ }
+ catch (Exception e) {
+ // Does not matter.
+ }
+
+ return null;
+ }
+
+ public boolean canUse(ArtifactObject object) {
+ return MIMETYPE.equals(object.getMimetype());
+ }
+
+ public Map<String, String> checkAttributes(Map<String, String> attributes) {
+ // All necessary checks will be done by the constructor using getMandatoryAttributes.
+ return attributes;
+ }
+
+ public <TYPE extends ArtifactObject> String getAssociationFilter(TYPE obj, Map<String, String> properties) {
+ return "(" + ArtifactObject.KEY_ARTIFACT_NAME + "=" + obj.getAttribute(ArtifactObject.KEY_ARTIFACT_NAME) + ")";
+ }
+
+ public <TYPE extends ArtifactObject> int getCardinality(TYPE obj, Map<String, String> properties) {
+ return Integer.MAX_VALUE;
+ }
+
+ public Comparator<ArtifactObject> getComparator() {
+ return null;
+ }
+
+ public String[] getDefiningKeys() {
+ return new String[] {ArtifactObject.KEY_ARTIFACT_NAME};
+ }
+
+ public String[] getMandatoryAttributes() {
+ return new String[] {ArtifactObject.KEY_ARTIFACT_NAME};
+ }
+
+ private final static VelocityArtifactPreprocessor VELOCITY_ARTIFACT_PREPROCESSOR = new VelocityArtifactPreprocessor();
+ public ArtifactPreprocessor getPreprocessor() {
+ return VELOCITY_ARTIFACT_PREPROCESSOR;
+ }
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Activator.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Activator.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Activator.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Activator.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,191 @@
+package net.luminis.liq.client.repository.impl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import 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.helper.ArtifactHelper;
+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.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.apache.felix.dependencymanager.DependencyActivatorBase;
+import org.apache.felix.dependencymanager.DependencyManager;
+import org.apache.felix.dependencymanager.Service;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+import org.osgi.service.log.LogService;
+import org.osgi.service.prefs.PreferencesService;
+
+/**
+ * Activator for the RepositoryAdmin bundle. Creates and registers the necessary repositories,
+ * plus the repository admin.
+ */
+public class Activator extends DependencyActivatorBase {
+ private DependencyManager m_manager;
+ List<Service[]> m_services;
+
+ private RepositoryAdminImpl m_repositoryAdminImpl;
+ private ChangeNotifierManager m_changeNotifierManager;
+
+ private ArtifactRepositoryImpl m_artifactRepositoryImpl;
+ private GroupRepositoryImpl m_groupRepositoryImpl;
+ private Artifact2GroupAssociationRepositoryImpl m_artifact2GroupAssociationRepositoryImpl;
+ private LicenseRepositoryImpl m_licenseRepositoryImpl;
+ private Group2LicenseAssociationRepositoryImpl m_group2LicenseAssociationRepositoryImpl;
+ private GatewayRepositoryImpl m_gatewayRepositoryImpl;
+ private License2GatewayAssociationRepositoryImpl m_license2GatewayAssociationRepositoryImpl;
+ private DeploymentVersionRepositoryImpl m_deploymentVersionRepositoryImpl;
+
+ @Override
+ public synchronized void init(BundleContext context, DependencyManager manager) throws Exception {
+ m_manager = manager;
+
+ m_changeNotifierManager = new ChangeNotifierManager();
+ manager.add(createService()
+ .setImplementation(m_changeNotifierManager)
+ .add(createServiceDependency().setService(EventAdmin.class).setRequired(true)));
+
+ m_repositoryAdminImpl = new RepositoryAdminImpl(this, m_changeNotifierManager.getConfiguredNotifier(RepositoryAdmin.PRIVATE_TOPIC_ROOT, RepositoryAdmin.PUBLIC_TOPIC_ROOT, RepositoryAdmin.TOPIC_ENTITY_ROOT));
+ manager.add(createService()
+ .setInterface(RepositoryAdmin.class.getName(), null)
+ .setImplementation(m_repositoryAdminImpl)
+ .add(createServiceDependency().setService(PreferencesService.class).setRequired(true))
+ .add(createServiceDependency().setService(LogService.class).setRequired(false)));
+ }
+
+ private <T extends RepositoryObject> Service[] registerRepository(Class<? extends ObjectRepository<T>> iface, ObjectRepositoryImpl<?, T> imp, String[] topics) {
+ Service repositoryService = createService()
+ .setInterface(iface.getName(), null)
+ .setImplementation(imp)
+ .add(createServiceDependency().setService(LogService.class).setRequired(false));
+ Dictionary<String, String[]> topic = new Hashtable<String, String[]>();
+ topic.put(EventConstants.EVENT_TOPIC, topics);
+ Service handlerService = createService()
+ .setInterface(EventHandler.class.getName(), topic)
+ .setImplementation(imp);
+
+ m_manager.add(repositoryService);
+ m_manager.add(handlerService);
+ return new Service[] {repositoryService, handlerService};
+ }
+
+ @SuppressWarnings("unchecked")
+ synchronized Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> publishRepositories() {
+ // create the repository objects, if this is the first time this method is called.
+ if (m_artifactRepositoryImpl == null) {
+ m_artifactRepositoryImpl = new ArtifactRepositoryImpl(m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, ArtifactObject.TOPIC_ENTITY_ROOT));
+ m_groupRepositoryImpl = new GroupRepositoryImpl(m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, GroupObject.TOPIC_ENTITY_ROOT));
+ m_artifact2GroupAssociationRepositoryImpl = new Artifact2GroupAssociationRepositoryImpl(m_artifactRepositoryImpl, m_groupRepositoryImpl, m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, Artifact2GroupAssociation.TOPIC_ENTITY_ROOT));
+ m_licenseRepositoryImpl = new LicenseRepositoryImpl(m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, LicenseObject.TOPIC_ENTITY_ROOT));
+ m_group2LicenseAssociationRepositoryImpl = new Group2LicenseAssociationRepositoryImpl(m_groupRepositoryImpl, m_licenseRepositoryImpl, m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, Group2LicenseAssociation.TOPIC_ENTITY_ROOT));
+ m_gatewayRepositoryImpl = new GatewayRepositoryImpl(m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, GatewayObject.TOPIC_ENTITY_ROOT));
+ m_license2GatewayAssociationRepositoryImpl = new License2GatewayAssociationRepositoryImpl(m_licenseRepositoryImpl, m_gatewayRepositoryImpl, m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, License2GatewayAssociation.TOPIC_ENTITY_ROOT));
+ m_deploymentVersionRepositoryImpl = new DeploymentVersionRepositoryImpl(m_changeNotifierManager.getConfiguredNotifier(RepositoryObject.PRIVATE_TOPIC_ROOT, RepositoryObject.PUBLIC_TOPIC_ROOT, DeploymentVersionObject.TOPIC_ENTITY_ROOT));
+ }
+ // first, register the artifact repository manually; it needs some special care.
+ Service artifactRepoService = createService()
+ .setInterface(ArtifactRepository.class.getName(), null)
+ .setImplementation(m_artifactRepositoryImpl)
+ .add(createServiceDependency().setService(LogService.class).setRequired(false))
+ .add(createServiceDependency().setService(ArtifactHelper.class).setRequired(false).setAutoConfig(false).setCallbacks(this, "addArtifactHelper", "removeArtifactHelper"));
+ Dictionary<String, String[]> topic = new Hashtable<String, String[]>();
+ topic.put(EventConstants.EVENT_TOPIC, new String[] {});
+ Service artifactHandlerService = createService()
+ .setInterface(EventHandler.class.getName(), topic)
+ .setImplementation(m_artifactRepositoryImpl);
+ m_manager.add(artifactRepoService);
+ m_manager.add(artifactHandlerService);
+
+ m_services = new ArrayList<Service[]>();
+ m_services.add(new Service[] {artifactRepoService, artifactHandlerService});
+
+ // register all repositories are services. Keep the service objects around, we need them to pull the services later.
+ m_services.add(registerRepository(Artifact2GroupAssociationRepository.class, m_artifact2GroupAssociationRepositoryImpl, new String[] {createPrivateObjectTopic(ArtifactObject.TOPIC_ENTITY_ROOT), createPrivateObjectTopic(GroupObject.TOPIC_ENTITY_ROOT)}));
+ m_services.add(registerRepository(GroupRepository.class, m_groupRepositoryImpl, new String[] {}));
+ m_services.add(registerRepository(Group2LicenseAssociationRepository.class, m_group2LicenseAssociationRepositoryImpl, new String[] {createPrivateObjectTopic(GroupObject.TOPIC_ENTITY_ROOT), createPrivateObjectTopic(LicenseObject.TOPIC_ENTITY_ROOT)}));
+ m_services.add(registerRepository(LicenseRepository.class, m_licenseRepositoryImpl, new String[] {}));
+ m_services.add(registerRepository(License2GatewayAssociationRepository.class, m_license2GatewayAssociationRepositoryImpl, new String[] {createPrivateObjectTopic(LicenseObject.TOPIC_ENTITY_ROOT), createPrivateObjectTopic(GatewayObject.TOPIC_ENTITY_ROOT)}));
+ m_services.add(registerRepository(GatewayRepository.class, m_gatewayRepositoryImpl, new String[] {}));
+ m_services.add(registerRepository(DeploymentVersionRepository.class, m_deploymentVersionRepositoryImpl, new String[] {}));
+
+ // prepare the results.
+ Map<Class<? extends ObjectRepository>, ObjectRepositoryImpl> result = new HashMap<Class<? extends ObjectRepository>, ObjectRepositoryImpl>();
+
+ result.put(ArtifactRepository.class, m_artifactRepositoryImpl);
+ result.put(Artifact2GroupAssociationRepository.class, m_artifact2GroupAssociationRepositoryImpl);
+ result.put(GroupRepository.class, m_groupRepositoryImpl);
+ result.put(Group2LicenseAssociationRepository.class, m_group2LicenseAssociationRepositoryImpl);
+ result.put(LicenseRepository.class, m_licenseRepositoryImpl);
+ result.put(License2GatewayAssociationRepository.class, m_license2GatewayAssociationRepositoryImpl);
+ result.put(GatewayRepository.class, m_gatewayRepositoryImpl);
+ result.put(DeploymentVersionRepository.class, m_deploymentVersionRepositoryImpl);
+
+ return result;
+ }
+
+ /**
+ * Helper method for use in publishRepositories
+ */
+ private static String createPrivateObjectTopic(String entityRoot) {
+ return RepositoryObject.PRIVATE_TOPIC_ROOT + entityRoot + RepositoryObject.TOPIC_ALL_SUFFIX;
+ }
+
+ /**
+ * Pulls all repository services; is used to make sure the repositories go away before the RepositoryAdmin does.
+ */
+ synchronized void pullRepositories() {
+ for (Service[] services : m_services) {
+ for (Service service : services) {
+ m_manager.remove(service);
+ }
+ }
+ }
+
+ @Override
+ public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ if (m_repositoryAdminImpl.loggedIn()) {
+ try {
+ m_repositoryAdminImpl.logout(true);
+ }
+ catch (IOException ioe) {
+ // Not much to do about this. We could log it?
+ }
+ }
+ m_repositoryAdminImpl = null;
+ }
+
+ public void addArtifactHelper(ServiceReference ref, ArtifactHelper helper) {
+ String mimetype = (String) ref.getProperty(ArtifactHelper.KEY_MIMETYPE);
+ m_artifactRepositoryImpl.addHelper(mimetype, helper);
+ }
+
+ public synchronized void removeArtifactHelper(ServiceReference ref, ArtifactHelper helper) {
+ String mimetype = (String) ref.getProperty(ArtifactHelper.KEY_MIMETYPE);
+ m_artifactRepositoryImpl.removeHelper(mimetype, helper);
+ }
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Artifact2GroupAssociationImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Artifact2GroupAssociationImpl.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Artifact2GroupAssociationImpl.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Artifact2GroupAssociationImpl.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,32 @@
+package net.luminis.liq.client.repository.impl;
+
+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.GroupObject;
+
+import org.osgi.framework.InvalidSyntaxException;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/**
+ * Implementation class for the Artifact2GroupAssociation. For 'what it does', see Artifact2GroupAssociation,
+ * for 'how it works', see AssociationImpl.
+ */
+public class Artifact2GroupAssociationImpl extends AssociationImpl<ArtifactObject, GroupObject, Artifact2GroupAssociation> implements Artifact2GroupAssociation {
+ private final static String XML_NODE = "artifact2group";
+
+ public Artifact2GroupAssociationImpl(Map<String, String> attributes, ChangeNotifier notifier, ArtifactRepositoryImpl artifactRepository, GroupRepositoryImpl groupRepository) throws InvalidSyntaxException {
+ super(attributes, notifier, ArtifactObject.class, GroupObject.class, artifactRepository, groupRepository, XML_NODE);
+ }
+
+ public Artifact2GroupAssociationImpl(Map<String, String> attributes, Map<String, String> tags, ChangeNotifier notifier, ArtifactRepositoryImpl artifactRepository, GroupRepositoryImpl groupRepository) throws InvalidSyntaxException {
+ super(attributes, tags, notifier, ArtifactObject.class, GroupObject.class, artifactRepository, groupRepository, XML_NODE);
+ }
+
+ public Artifact2GroupAssociationImpl(HierarchicalStreamReader reader, ChangeNotifier notifier, ArtifactRepositoryImpl artifactRepository, GroupRepositoryImpl groupRepository) throws InvalidSyntaxException {
+ super(reader, notifier, ArtifactObject.class, GroupObject.class, null, null, artifactRepository, groupRepository, XML_NODE);
+ }
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Artifact2GroupAssociationRepositoryImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Artifact2GroupAssociationRepositoryImpl.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Artifact2GroupAssociationRepositoryImpl.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/Artifact2GroupAssociationRepositoryImpl.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,59 @@
+package net.luminis.liq.client.repository.impl;
+
+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.GroupObject;
+import net.luminis.liq.client.repository.repository.Artifact2GroupAssociationRepository;
+
+import org.osgi.framework.InvalidSyntaxException;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/**
+ * Implementation class for the Artifact2GroupAssociationRepository. For 'what it does', see Artifact2GroupAssociationRepository,
+ * for 'how it works', see AssociationRepositoryImpl.
+ */
+public class Artifact2GroupAssociationRepositoryImpl extends AssociationRepositoryImpl<ArtifactObject, GroupObject, Artifact2GroupAssociationImpl, Artifact2GroupAssociation> implements Artifact2GroupAssociationRepository {
+ private final static String XML_NODE = "artifacts2groups";
+
+ private final ArtifactRepositoryImpl m_bundleRepository;
+ private final GroupRepositoryImpl m_groupRepository;
+
+ public Artifact2GroupAssociationRepositoryImpl(ArtifactRepositoryImpl bundleRepository, GroupRepositoryImpl groupRepository, ChangeNotifier notifier) {
+ super(notifier, XML_NODE);
+ m_bundleRepository = bundleRepository;
+ m_groupRepository = groupRepository;
+ }
+
+ @Override
+ Artifact2GroupAssociationImpl createNewInhabitant(Map<String, String> attributes) {
+ try {
+ return new Artifact2GroupAssociationImpl(attributes, this, m_bundleRepository, m_groupRepository);
+ }
+ catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException("Unable to create association: ", e);
+ }
+ }
+
+ @Override
+ Artifact2GroupAssociationImpl createNewInhabitant(Map<String, String> attributes, Map<String, String> tags) {
+ try {
+ return new Artifact2GroupAssociationImpl(attributes, tags, this, m_bundleRepository, m_groupRepository);
+ }
+ catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException("Unable to create association: ", e);
+ }
+ }
+
+ @Override
+ Artifact2GroupAssociationImpl createNewInhabitant(HierarchicalStreamReader reader) {
+ try {
+ return new Artifact2GroupAssociationImpl(reader, this, m_bundleRepository, m_groupRepository);
+ }
+ catch (InvalidSyntaxException e) {
+ throw new IllegalArgumentException("Unable to create association: ", e);
+ }
+ }
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ArtifactObjectImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ArtifactObjectImpl.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ArtifactObjectImpl.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ArtifactObjectImpl.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,121 @@
+package net.luminis.liq.client.repository.impl;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+
+import net.luminis.liq.client.repository.helper.ArtifactHelper;
+import net.luminis.liq.client.repository.object.Artifact2GroupAssociation;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+import net.luminis.liq.client.repository.object.GroupObject;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/**
+ * Implementation class for the ArtifactObject. For 'what it does', see ArtifactObject,
+ * for 'how it works', see RepositoryObjectImpl.<br>
+ * <br>
+ * Some functionality of this class is delegated to implementers of {@link ArtifactHelper}.
+ */
+public class ArtifactObjectImpl extends RepositoryObjectImpl<ArtifactObject> implements ArtifactObject {
+ private final static String XML_NODE = "artifact";
+
+ /*
+ * As a general rule, RepositoryObjects do not know about their repository. However, since the Helper
+ * to be used is dictated by the repository, this rule is broken for this class.
+ */
+ private ArtifactRepositoryImpl m_repo;
+
+ ArtifactObjectImpl(Map<String, String> attributes, String[] mandatoryAttributes, ChangeNotifier notifier, ArtifactRepositoryImpl repo) {
+ super(checkAttributes(attributes, completeMandatoryAttributes(mandatoryAttributes)), notifier, XML_NODE);
+ m_repo = repo;
+ }
+
+ ArtifactObjectImpl(Map<String, String> attributes, String[] mandatoryAttributes, Map<String, String> tags, ChangeNotifier notifier, ArtifactRepositoryImpl repo) {
+ super(checkAttributes(attributes, completeMandatoryAttributes(mandatoryAttributes)), tags, notifier, XML_NODE);
+ m_repo = repo;
+ }
+
+ private static String[] completeMandatoryAttributes(String[] mandatory) {
+ String[] result = new String[mandatory.length + 2];
+ for (int i = 0; i < mandatory.length; i++) {
+ result[i] = mandatory[i];
+ }
+ result[mandatory.length] = KEY_MIMETYPE;
+ result[mandatory.length + 1 ] = KEY_URL;
+ return result;
+ }
+
+ ArtifactObjectImpl(HierarchicalStreamReader reader, ChangeNotifier notifier, ArtifactRepositoryImpl repo) {
+ super(reader, notifier, XML_NODE);
+ m_repo = repo;
+ }
+
+ public List<GroupObject> getGroups() {
+ return getAssociations(GroupObject.class);
+ }
+
+ public List<Artifact2GroupAssociation> getAssociationsWith(GroupObject group) {
+ return getAssociationsWith(group, GroupObject.class, Artifact2GroupAssociation.class);
+ }
+
+ @Override
+ public String getAssociationFilter(Map<String, String> properties) {
+ return getHelper().getAssociationFilter(this, properties);
+ }
+
+ @Override
+ public int getCardinality(Map<String, String> properties) {
+ return getHelper().getCardinality(this, properties);
+ }
+
+ @Override
+ public Comparator<ArtifactObject> getComparator() {
+ return getHelper().getComparator();
+ }
+
+ @Override
+ String[] getDefiningKeys() {
+ String[] fromHelper = getHelper().getDefiningKeys();
+
+ String[] result = new String[fromHelper.length + 1];
+ for (int i = 0; i < fromHelper.length; i++) {
+ result[i] = fromHelper[i];
+ }
+ result[fromHelper.length] = KEY_URL;
+
+ return result;
+ }
+
+ public String getURL() {
+ return getAttribute(KEY_URL);
+ }
+
+ public String getMimetype() {
+ return getAttribute(KEY_MIMETYPE);
+ }
+
+ public String getProcessorPID() {
+ return getAttribute(KEY_PROCESSOR_PID);
+ }
+
+ public void setProcessorPID(String processorPID) {
+ addAttribute(KEY_PROCESSOR_PID, processorPID);
+ }
+
+ public String getName() {
+ return getAttribute(KEY_ARTIFACT_NAME);
+ }
+
+ public String getDescription() {
+ return getAttribute(KEY_ARTIFACT_DESCRIPTION);
+ }
+
+ private synchronized ArtifactHelper getHelper() {
+ return m_repo.getHelper(getMimetype());
+ }
+
+ public void setDescription(String value) {
+ addAttribute(KEY_ARTIFACT_DESCRIPTION, value);
+ }
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ArtifactRepositoryImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ArtifactRepositoryImpl.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ArtifactRepositoryImpl.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/ArtifactRepositoryImpl.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,550 @@
+package net.luminis.liq.client.repository.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import net.luminis.liq.client.repository.RepositoryObject;
+import net.luminis.liq.client.repository.RepositoryUtil;
+import net.luminis.liq.client.repository.helper.ArtifactHelper;
+import net.luminis.liq.client.repository.helper.ArtifactPreprocessor;
+import net.luminis.liq.client.repository.helper.ArtifactRecognizer;
+import net.luminis.liq.client.repository.helper.PropertyResolver;
+import net.luminis.liq.client.repository.helper.bundle.BundleHelper;
+import net.luminis.liq.client.repository.object.ArtifactObject;
+import net.luminis.liq.client.repository.object.GatewayObject;
+import net.luminis.liq.client.repository.object.GroupObject;
+import net.luminis.liq.client.repository.object.LicenseObject;
+import net.luminis.liq.client.repository.repository.ArtifactRepository;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/**
+ * Implementation class for the ArtifactRepository. For 'what it does', see ArtifactRepository,
+ * for 'how it works', see ObjectRepositoryImpl.<br>
+ * <br>
+ * This class has some extended functionality when compared to <code>ObjectRepositoryImpl</code>,
+ * <ul>
+ * <li> it keeps track of all <code>ArtifactHelper</code>s, and serves them to its inhabitants.
+ * <li> it handles importing of artifacts.
+ * </ul>
+ */
+public class ArtifactRepositoryImpl extends ObjectRepositoryImpl<ArtifactObjectImpl, ArtifactObject> implements ArtifactRepository {
+ private final static String XML_NODE = "artifacts";
+ private volatile BundleContext m_context; /*Injected by dependency manager*/
+ private volatile LogService m_log; /*Injected by dependency manager*/
+ private Map<String, ArtifactHelper> m_helpers = new HashMap<String, ArtifactHelper>();
+ private URL m_obrBase;
+
+ /**
+ * Custom comparator which sorts service references by service rank, highest rank first.
+ */
+ private static Comparator<ServiceReference> SERVICE_RANK_COMPARATOR = new Comparator<ServiceReference>() {
+ public int compare(ServiceReference o1, ServiceReference o2) {
+ int rank1 = 0;
+ int rank2 = 0;
+ try {
+ Object rankObject1 = o1.getProperty(Constants.SERVICE_RANKING);
+ rank1 = (rankObject1 == null) ? 0 : ((Integer) rankObject1).intValue();
+ }
+ catch (ClassCastException cce) {
+ // No problem.
+ }
+ try {
+ Object rankObject2 = o2.getProperty(Constants.SERVICE_RANKING);
+ rank1 = (rankObject2 == null) ? 0 : ((Integer) rankObject2).intValue();
+ }
+ catch (ClassCastException cce) {
+ // No problem.
+ }
+
+ return rank1 - rank2;
+ }
+ };
+
+
+ public ArtifactRepositoryImpl(ChangeNotifier notifier) {
+ super(notifier, XML_NODE);
+ }
+
+ public List<ArtifactObject> getResourceProcessors() {
+ try {
+ return super.get(createFilter("(" + BundleHelper.KEY_RESOURCE_PROCESSOR_PID + "=*)"));
+ }
+ catch (InvalidSyntaxException e) {
+ m_log.log(LogService.LOG_ERROR, "getResourceProcessors' filter returned an InvalidSyntaxException.", e);
+ }
+ return new ArrayList<ArtifactObject>();
+ }
+
+ @Override
+ public List<ArtifactObject> get(Filter filter) {
+ // Note that this excludes any Bundle artifacts which are resource processors.
+ try {
+ Filter extendedFilter = createFilter("(&" + filter.toString() + "(!(" + BundleHelper.KEY_RESOURCE_PROCESSOR_PID + "=*)))");
+ return super.get(extendedFilter);
+ }
+ catch (InvalidSyntaxException e) {
+ m_log.log(LogService.LOG_ERROR, "Extending " + filter.toString() + " resulted in an InvalidSyntaxException.", e);
+ }
+ return new ArrayList<ArtifactObject>();
+ }
+
+ @Override
+ public List<ArtifactObject> get() {
+ // Note that this excludes any Bundle artifacts which are resource processors.
+ try {
+ return super.get(createFilter("(!(" + RepositoryUtil.escapeFilterValue(BundleHelper.KEY_RESOURCE_PROCESSOR_PID) + "=*))"));
+ }
+ catch (InvalidSyntaxException e) {
+ m_log.log(LogService.LOG_ERROR, "get's filter returned an InvalidSyntaxException.", e);
+ }
+ return new ArrayList<ArtifactObject>();
+ }
+
+ @Override
+ ArtifactObjectImpl createNewInhabitant(Map<String, String> attributes) {
+ ArtifactHelper helper = getHelper(attributes.get(ArtifactObject.KEY_MIMETYPE));
+ return new ArtifactObjectImpl(helper.checkAttributes(attributes), helper.getMandatoryAttributes(), this, this);
+ }
+
+ @Override
+ ArtifactObjectImpl createNewInhabitant(Map<String, String> attributes, Map<String, String> tags) {
+ ArtifactHelper helper = getHelper(attributes.get(ArtifactObject.KEY_MIMETYPE));
+ return new ArtifactObjectImpl(helper.checkAttributes(attributes), helper.getMandatoryAttributes(), tags, this, this);
+ }
+
+ @Override
+ ArtifactObjectImpl createNewInhabitant(HierarchicalStreamReader reader) {
+ return new ArtifactObjectImpl(reader, this, this);
+ }
+
+ /**
+ * Helper method for this repository's inhabitants, which finds the necessary helpers.
+ * @param mimetype The mimetype for which a helper should be found.
+ * @return An artifact helper for the given mimetype.
+ * @throws IllegalArgumentException when the mimetype is invalid, or no helpers are available.
+ */
+ ArtifactHelper getHelper(String mimetype) {
+ synchronized(m_helpers) {
+ if ((mimetype == null) || (mimetype.length() == 0)) {
+ throw new IllegalArgumentException("Without a mimetype, we cannot find a helper.");
+ }
+
+ ArtifactHelper helper = m_helpers.get(mimetype.toLowerCase());
+
+ if (helper == null) {
+ throw new IllegalArgumentException("There are no ArtifactHelpers known for type '" + mimetype + "'.");
+ }
+
+ return helper;
+ }
+ }
+
+ /**
+ * Method intended for adding artifact helpers by the bundle's activator.
+ */
+ void addHelper(String mimetype, ArtifactHelper helper) {
+ synchronized(m_helpers) {
+ if ((mimetype == null) || (mimetype.length() == 0)) {
+ m_log.log(LogService.LOG_WARNING, "An ArtifactHelper has been published without a proper mimetype.");
+ }
+ else {
+ m_helpers.put(mimetype.toLowerCase(), helper);
+ }
+ }
+ }
+
+ /**
+ * Method intended for removing artifact helpers by the bundle's activator.
+ */
+ void removeHelper(String mimetype, ArtifactHelper helper) {
+ synchronized(m_helpers) {
+ if ((mimetype == null) || (mimetype.length() == 0)) {
+ m_log.log(LogService.LOG_WARNING, "An ArtifactHelper is being removed without a proper mimetype.");
+ }
+ else {
+ m_helpers.remove(mimetype.toLowerCase());
+ }
+ }
+ }
+
+ /**
+ * Utility function that takes either a URL or a String representing a mimetype,
+ * and returns the corresponding <code>ArtifactHelper</code>, <code>ArtifactRecognizer</code>
+ * and, if not specified, the mimetype.
+ * @param input Either a <code>URL</code> pointing to a physical artifact, or a <code>String</code>
+ * representing a mime type.
+ * @return A mapping from a class (<code>ArtifactRecognizer</code>, <code>ArtifactHelper</code> or
+ * <code>String</code> to an instance of that class as a result.
+ */
+ protected Map<Class<?>, Object> findRecognizerAndHelper(Object input) throws IllegalArgumentException {
+ // check input.
+ URL url = null;
+ String mimetype = null;
+ if (input instanceof URL) {
+ url = (URL) input;
+ }
+ else if (input instanceof String) {
+ mimetype = (String) input;
+ }
+ else {
+ throw new IllegalArgumentException("findRecognizer received an unrecognized input.");
+ }
+
+ // Get all published ArtifactRecognizers.
+ ServiceReference[] refs = null;
+ try {
+ refs = m_context.getServiceReferences(ArtifactRecognizer.class.getName(), null);
+ }
+ catch (InvalidSyntaxException e) {
+ // We do not pass in a filter, so this should not happen.
+ m_log.log(LogService.LOG_WARNING, "A null filter resulted in an InvalidSyntaxException from getServiceReferences.");
+ }
+
+ if (refs == null) {
+ throw new IllegalArgumentException("There are no artifact recognizers available.");
+ }
+
+ // If available, sort the references by service ranking.
+ Arrays.sort(refs, SERVICE_RANK_COMPARATOR);
+
+ // Check all referenced services to find one that matches our input.
+ ArtifactRecognizer recognizer = null;
+ String foundMimetype = null;
+ for (ServiceReference ref : refs) {
+ ArtifactRecognizer candidate = (ArtifactRecognizer) m_context.getService(ref);
+ if (mimetype != null) {
+ if (candidate.canHandle(mimetype)) {
+ recognizer = candidate;
+ break;
+ }
+ }
+ else {
+ String candidateMime = candidate.recognize(url);
+ if (candidateMime != null) {
+ foundMimetype = candidateMime;
+ recognizer = candidate;
+ break;
+ }
+ }
+ }
+
+ if (recognizer == null) {
+ throw new IllegalArgumentException("There is no artifact recognizer that recognizes artifact " + ((url == null) ? "(null)" : url.toString()));
+ }
+
+ // Package the results in the map.
+ Map<Class<?>, Object> result = new HashMap<Class<?>, Object>();
+ result.put(ArtifactRecognizer.class, recognizer);
+ if (mimetype == null) {
+ result.put(ArtifactHelper.class, getHelper(foundMimetype));
+ result.put(String.class, foundMimetype);
+ }
+ else {
+ result.put(ArtifactHelper.class, getHelper(mimetype));
+ }
+
+ return result;
+ }
+
+ public boolean recognizeArtifact(URL artifact) {
+ try {
+ Map<Class<?>, Object> fromArtifact = findRecognizerAndHelper(artifact);
+ String mimetype = (String) fromArtifact.get(String.class);
+ return mimetype != null;
+ }
+ catch (Exception e) {
+ //too bad... Nothing to do now.
+ return false;
+ }
+ }
+
+ public ArtifactObject importArtifact(URL artifact, boolean upload) throws IllegalArgumentException, IOException {
+ try {
+ if ((artifact == null) || (artifact.toString().length() == 0)) {
+ throw new IllegalArgumentException("The URL to import cannot be null or empty.");
+ }
+ checkURL(artifact);
+
+ Map<Class<?>, Object> fromArtifact = findRecognizerAndHelper(artifact);
+ ArtifactRecognizer recognizer = (ArtifactRecognizer) fromArtifact.get(ArtifactRecognizer.class);
+ ArtifactHelper helper = (ArtifactHelper) fromArtifact.get(ArtifactHelper.class);
+ String mimetype = (String) fromArtifact.get(String.class);
+
+ return importArtifact(artifact, recognizer, helper, mimetype, false, upload);
+ }
+ catch (IllegalArgumentException iae) {
+ m_log.log(LogService.LOG_INFO, "Error importing artifact: " + iae.getMessage());
+ throw iae;
+ }
+ catch (IOException ioe) {
+ m_log.log(LogService.LOG_INFO, "Error storing artifact: " + ioe.getMessage());
+ throw ioe;
+ }
+ }
+
+ public ArtifactObject importArtifact(URL artifact, String mimetype, boolean upload) throws IllegalArgumentException, IOException {
+ try {
+ if ((artifact == null) || (artifact.toString().length() == 0)) {
+ throw new IllegalArgumentException("The URL to import cannot be null or empty.");
+ }
+ if ((mimetype == null) || (mimetype.length() == 0)) {
+ throw new IllegalArgumentException("The mimetype of the artifact to import cannot be null or empty.");
+ }
+
+ checkURL(artifact);
+
+ Map<Class<?>, Object> fromMimetype = findRecognizerAndHelper(mimetype);
+ ArtifactRecognizer recognizer = (ArtifactRecognizer) fromMimetype.get(ArtifactRecognizer.class);
+ ArtifactHelper helper = (ArtifactHelper) fromMimetype.get(ArtifactHelper.class);
+
+ return importArtifact(artifact, recognizer, helper, mimetype, true, upload);
+ }
+ catch (IllegalArgumentException iae) {
+ m_log.log(LogService.LOG_INFO, "Error importing artifact: " + iae.getMessage());
+ throw iae;
+ }
+ catch (IOException ioe) {
+ m_log.log(LogService.LOG_INFO, "Error storing artifact: " + ioe.getMessage());
+ throw ioe;
+ }
+ }
+
+ private ArtifactObject importArtifact(URL artifact, ArtifactRecognizer recognizer, ArtifactHelper helper, String mimetype, boolean overwrite, boolean upload) throws IOException {
+ Map<String, String> attributes = recognizer.extractMetaData(artifact);
+ Map<String, String> tags = new HashMap<String, String>();
+
+ helper.checkAttributes(attributes);
+
+ URL location;
+ if (upload) {
+ location = upload(artifact, mimetype);
+ }
+ else {
+ location = artifact;
+ }
+
+ attributes.put(ArtifactObject.KEY_URL, location.toString());
+ attributes.put(ArtifactObject.KEY_ARTIFACT_DESCRIPTION, "");
+ if (overwrite) {
+ attributes.put(ArtifactObject.KEY_MIMETYPE, mimetype);
+ }
+
+ return create(attributes, tags);
+ }
+
+ /**
+ * Helper method which checks a given URL for 'validity', that is, does this URL point
+ * to something that can be read.
+ * @param artifact A URL pointing to an artifact.
+ * @throws IllegalArgumentException when the URL does not point to a valid file.
+ */
+
+ private void checkURL(URL artifact) throws IllegalArgumentException {
+ // First, check whether we can actually reach something from this URL.
+ InputStream is = null;
+ try {
+ is = artifact.openStream();
+ }
+ catch (IOException ioe) {
+ throw new IllegalArgumentException("Artifact " + artifact.toString() + "does not point to a valid file.");
+ }
+ finally {
+ if (is != null) {
+ try {
+ is.close();
+ }
+ catch (IOException ioe) {
+ // Too bad, nothing to do.
+ }
+ }
+ }
+
+ // Then, check whether the name is legal.
+ for (byte b : artifact.toString().substring(artifact.toString().lastIndexOf('/') + 1).getBytes()) {
+ if (!(((b >= 'A') && (b <= 'Z')) || ((b >= 'a') && (b <= 'z')) || ((b >= '0') && (b <= '9')) || (b == '.') || (b == '-') || (b == '_'))) {
+ throw new IllegalArgumentException("Artifact " + artifact.toString() + "'s name contains an illegal character '" + new String(new byte[] {b}) + "'");
+ }
+ }
+
+ }
+
+ /**
+ * Uploads an artifact to the OBR.
+ * @param artifact URL pointing to the local artifact.
+ * @param mimetype The mimetype of this artifact.
+ * @return The persistent URL of this artifact.
+ * @throws IOException for any problem uploading the artifact.
+ */
+ private URL upload(URL artifact, String mimetype) throws IOException {
+ if (m_obrBase == null) {
+ throw new IOException("There is no storage available for this artifact.");
+ }
+
+ InputStream input = null;
+ OutputStream output = null;
+ URL url = null;
+ try {
+ input = artifact.openStream();
+ url = new URL(m_obrBase, new File(artifact.getFile()).getName());
+ URLConnection connection = url.openConnection();
+ connection.setDoOutput(true);
+ connection.setDoInput(true);
+ connection.setUseCaches(false);
+ connection.setRequestProperty("Content-Type", mimetype);
+ output = connection.getOutputStream();
+ byte[] buffer = new byte[4 * 1024];
+ for (int count = input.read(buffer); count != -1; count = input.read(buffer)) {
+ output.write(buffer, 0, count);
+ }
+ output.close();
+ if (connection instanceof HttpURLConnection) {
+ int responseCode = ((HttpURLConnection) connection).getResponseCode();
+ switch (responseCode) {
+ case HttpURLConnection.HTTP_OK :
+ break;
+ case HttpURLConnection.HTTP_CONFLICT:
+ throw new IOException("Artifact already exists in storage.");
+ case HttpURLConnection.HTTP_INTERNAL_ERROR:
+ throw new IOException("The storage server returned an internal server error.");
+ default:
+ throw new IOException("The storage server returned code " + responseCode + " writing to " + url.toString());
+ }
+ }
+ }
+ catch (IOException ioe) {
+ throw new IOException("Error importing artifact " + artifact.toString() + ": " + ioe.getMessage());
+ }
+ finally {
+ if (input != null) {
+ try {
+ input.close();
+ }
+ catch (Exception ex) {
+ // Not much we can do
+ }
+ }
+ if (output != null) {
+ try {
+ output.close();
+ }
+ catch (Exception ex) {
+ // Not much we can do
+ }
+ }
+ }
+
+ return url;
+ }
+
+ public void setObrBase(URL obrBase) {
+ m_obrBase = obrBase;
+ }
+
+ public String preprocessArtifact(ArtifactObject artifact, GatewayObject gateway, String gatewayID, String version) throws IOException {
+ ArtifactPreprocessor preprocessor = getHelper(artifact.getMimetype()).getPreprocessor();
+ if (preprocessor == null) {
+ return artifact.getURL();
+ }
+ else {
+ return preprocessor.preprocess(artifact.getURL(), new GatewayPropertyResolver(gateway), gatewayID, version, m_obrBase);
+ }
+ }
+
+ public boolean needsNewVersion(ArtifactObject artifact, GatewayObject gateway, String gatewayID, String fromVersion) {
+ ArtifactPreprocessor preprocessor = getHelper(artifact.getMimetype()).getPreprocessor();
+ if (preprocessor == null) {
+ return false;
+ }
+ else {
+ return preprocessor.needsNewVersion(artifact.getURL(), new GatewayPropertyResolver(gateway), gatewayID, fromVersion);
+ }
+ }
+
+ private static class GatewayPropertyResolver implements PropertyResolver {
+
+ private final GatewayObject m_go;
+
+ public GatewayPropertyResolver(GatewayObject go) {
+ m_go = go;
+ }
+
+ public String get(String key) {
+ return get(key, m_go);
+ }
+
+ private String get(String key, RepositoryObject ro) {
+ // Is it in this object?
+ String result = findKeyInObject(ro, key);
+ if (result != null) {
+ return result;
+ }
+
+ // Is it in one of the children?
+ List<RepositoryObject> children = getChildren(ro);
+ for (RepositoryObject child : children) {
+ result = findKeyInObject(child, key);
+ if (result != null) {
+ return result;
+ }
+ }
+
+ // Not found yet? then continue to the next level recursively.
+ for (RepositoryObject child : children) {
+ result = get(key, child);
+ if (result != null) {
+ return result;
+ }
+ }
+ return result;
+ }
+
+ private List getChildren(RepositoryObject ob) {
+ if (ob instanceof GatewayObject) {
+ return ((GatewayObject) ob).getLicenses();
+ }
+ else if (ob instanceof LicenseObject) {
+ return ((LicenseObject) ob).getGroups();
+ }
+ else if (ob instanceof GroupObject) {
+ return ((GroupObject) ob).getArtifacts();
+ }
+ return new ArrayList();
+ }
+
+ private String findKeyInObject(RepositoryObject ro, String key) {
+ String result;
+ if ((result = ro.getAttribute(key)) != null) {
+ return result;
+ }
+ if ((result = ro.getTag(key)) != null) {
+ return result;
+ }
+ return null;
+ }
+
+ }
+
+ public URL getObrBase() {
+ return m_obrBase;
+ }
+
+}
Added: incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/AssociationImpl.java
URL: http://svn.apache.org/viewvc/incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/AssociationImpl.java?rev=788992&view=auto
==============================================================================
--- incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/AssociationImpl.java (added)
+++ incubator/ace/trunk/server/src/net/luminis/liq/client/repository/impl/AssociationImpl.java Sat Jun 27 15:53:04 2009
@@ -0,0 +1,234 @@
+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 java.util.Properties;
+
+import net.luminis.liq.client.repository.Associatable;
+import net.luminis.liq.client.repository.Association;
+import net.luminis.liq.client.repository.RepositoryObject;
+
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.service.event.Event;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/**
+ * A basic implementation of the Association interface. Implements 'common' behavior for all associations.
+ *
+ * The association allows up to m-to-n associations. Each end of the association gets
+ * a filter to match objects, possibly a cardinality (if no cardinality is specified,
+ * 1 is assumed), and, if there can be more matches to the filter than the given cardinality,
+ * a comparator should be provided in the constructor.
+ *
+ * @param <L> The type of the RepositoryObject on the left side of this association
+ * @param <R> The type of the RepositoryObject on the right side of this association
+ * @param <T> The non-generic Association interface this object should use.
+ */
+public class AssociationImpl<L extends RepositoryObject, R extends RepositoryObject, T extends Association<L, R>> extends RepositoryObjectImpl<T> implements Association<L, R> {
+
+ /* These lists are volatile, since we use copy-on-write semantics for
+ * updating them.
+ */
+ private volatile List<L> m_left = new ArrayList<L>();
+ private volatile List<R> m_right = new ArrayList<R>();
+ private final Object m_lock = new Object();
+
+ private final Filter m_filterLeft;
+ private final Filter m_filterRight;
+
+ private final ObjectRepositoryImpl<?, L> m_leftRepository;
+ private final ObjectRepositoryImpl<?, R> m_rightRepository;
+ private final Class<L> m_leftClass;
+ private final Class<R> m_rightClass;
+
+ /**
+ * Constructor intended for deserialization. For most parameters, see below.
+ * @param reader a stream reader which contains an XML representation of this object's contents.
+ */
+ public AssociationImpl(HierarchicalStreamReader reader, ChangeNotifier notifier, Class<L> leftClass, Class<R> rightClass, Comparator<L> leftComparator, Comparator<R> rightComparator, ObjectRepositoryImpl<?, L> leftRepository, ObjectRepositoryImpl<?, R> rightRepository, String xmlNode) throws InvalidSyntaxException {
+ this(readMap(reader), notifier, leftClass, rightClass, leftRepository, rightRepository, xmlNode);
+ }
+
+ /**
+ * Basic constructor for AssociationImpl.
+ * @param attributes A map of attributes. This should at least contain <code>Association.LEFT_ENDPOINT</code> and <code>Association.RIGHT_ENDPOINT</code>,
+ * and optionally <code>Association.LEFT_CARDINALITY</code> and <code>Association.RIGHT_CARDINALITY</code>.
+ * @param notifier An instance of the event admin
+ * @param leftClass The class on the left side of this association.
+ * @param rightClass The class on the right side of this association.
+ * @param leftRepository The repository which holds object of <code>leftClass</code>.
+ * @param rightRepository The repository which holds object of <code>rightClass</code>.
+ * @param xmlNode The tag by which this object is known in the XML representation.
+ * @throws InvalidSyntaxException Thrown when the attributes contain an invalidly constructed filter string.
+ */
+ public AssociationImpl(Map<String, String> attributes, ChangeNotifier notifier, Class<L> leftClass, Class<R> rightClass, ObjectRepositoryImpl<?, L> leftRepository, ObjectRepositoryImpl<?, R> rightRepository, String xmlNode) throws InvalidSyntaxException {
+ super(attributes, notifier, xmlNode);
+
+ if ((getAttribute(LEFT_CARDINALITY) != null) && (Integer.parseInt(getAttribute(LEFT_CARDINALITY)) < 1)) {
+ throw new IllegalArgumentException("The left cardinality should be 1 or greater.");
+ }
+ if ((getAttribute(RIGHT_CARDINALITY) != null) && (Integer.parseInt(getAttribute(RIGHT_CARDINALITY)) < 1)) {
+ throw new IllegalArgumentException("The right cardinality should be 1 or greater.");
+ }
+
+ m_leftClass = leftClass;
+ m_rightClass = rightClass;
+ m_leftRepository = leftRepository;
+ m_rightRepository = rightRepository;
+
+ m_filterLeft = m_leftRepository.createFilter(getAttribute(Association.LEFT_ENDPOINT));
+ m_filterRight = m_rightRepository.createFilter(getAttribute(Association.RIGHT_ENDPOINT));
+
+ locateLeftEndpoint(false);
+ locateRightEndpoint(false);
+ }
+
+ public AssociationImpl(Map<String, String> attributes, Map<String, String> tags, ChangeNotifier notifier, Class<L> leftClass, Class<R> rightClass, ObjectRepositoryImpl<?, L> leftRepository, ObjectRepositoryImpl<?, R> rightRepository, String xmlNode) throws InvalidSyntaxException {
+ super(attributes, tags, notifier, xmlNode);
+
+ if ((getAttribute(LEFT_CARDINALITY) != null) && (Integer.parseInt(getAttribute(LEFT_CARDINALITY)) < 1)) {
+ throw new IllegalArgumentException("The left cardinality should be 1 or greater.");
+ }
+ if ((getAttribute(RIGHT_CARDINALITY) != null) && (Integer.parseInt(getAttribute(RIGHT_CARDINALITY)) < 1)) {
+ throw new IllegalArgumentException("The right cardinality should be 1 or greater.");
+ }
+
+ m_leftClass = leftClass;
+ m_rightClass = rightClass;
+ m_leftRepository = leftRepository;
+ m_rightRepository = rightRepository;
+
+ m_filterLeft = m_leftRepository.createFilter(getAttribute(Association.LEFT_ENDPOINT));
+ m_filterRight = m_rightRepository.createFilter(getAttribute(Association.RIGHT_ENDPOINT));
+
+ locateLeftEndpoint(false);
+ locateRightEndpoint(false);
+ }
+
+ public List<Associatable> getTo(Associatable from) {
+ if (m_left.contains(from)) {
+ return new ArrayList<Associatable>(m_right);
+ }
+ if (m_right.contains(from)) {
+ return new ArrayList<Associatable>(m_left);
+ }
+ return null;
+ }
+
+ public List<L> getLeft() {
+ return new ArrayList<L>(m_left);
+ }
+
+ public List<R> getRight() {
+ return new ArrayList<R>(m_right);
+ }
+
+ public void remove() {
+ for (L l : m_left) {
+ l.remove(this, m_rightClass);
+ }
+ for (R r : m_right) {
+ r.remove(this, m_leftClass);
+ }
+ }
+
+ /**
+ * Locates the most suited endpoint of one side of this association. If the corresponding filter
+ * matches multiple objects, the <code>comparator</code> will be used to find the most suited one.
+ * The association will register itself with a new endpoint, and remove itself from the old one.
+ * @param <TYPE> (only used for type matching).
+ * @param objectRepositoryImpl The repository where the endpoint should come from.
+ * @param filter A filter string, used to get candidate-endpoints from <code>objectRepositoryImpl</code>.
+ * @param endpoint The current endpoint.
+ * @param comparator A comparator, used when there are multiple potential endpoints.
+ * @param clazz The class of the 'other side' of this association.
+ * @return The most suited endpoint; this could be equal to <code>endpoint</code>.
+ */
+ @SuppressWarnings("unchecked")
+ private <TYPE extends RepositoryObject> List<TYPE> locateEndpoint(ObjectRepositoryImpl<?, TYPE> objectRepositoryImpl, Filter filter, List<TYPE> endpoints, int cardinality, Class<? extends RepositoryObject> clazz, boolean notify) {
+ List<TYPE> candidates = objectRepositoryImpl.get(filter);
+ List<TYPE> newEndpoints = new ArrayList<TYPE>();
+ List<TYPE> oldEndpoints = new ArrayList<TYPE>(endpoints);
+
+ if (candidates.size() > cardinality) {
+ Comparator<TYPE> comparator = candidates.get(0).getComparator();
+ if (comparator != null) {
+ Collections.sort(candidates, comparator);
+ }
+ else {
+ throw new NullPointerException("Filter '" + filter.toString() + "' has resulted in multiple candidates, so the RepositoryObject descendents should have provide a comparator, which they do not.");
+ }
+ }
+
+ for (int i = 0; (i < cardinality) && !candidates.isEmpty(); i++) {
+ TYPE current = candidates.remove(0);
+ newEndpoints.add(current);
+
+ if (!oldEndpoints.remove(current)) {
+ current.add(this, clazz);
+ }
+ }
+
+ for (TYPE e : oldEndpoints) {
+ e.remove(this, clazz);
+ }
+
+ if (!endpoints.equals(newEndpoints)) {
+ Properties props = new Properties();
+ props.put(EVENT_OLD, new ArrayList<TYPE>(endpoints));
+ props.put(EVENT_NEW, new ArrayList<TYPE>(newEndpoints));
+ if (notify) {
+ notifyChanged(props);
+ }
+ }
+
+ return newEndpoints;
+ }
+
+ /**
+ * Locates the left endpoint by using the generic locateEndpoint and notifies
+ * listeners of changes, if any.
+ * @param notify Indicates whether notifications should be sent out.
+ */
+ private void locateLeftEndpoint(boolean notify) {
+ synchronized (m_lock) {
+ m_left = locateEndpoint(m_leftRepository, m_filterLeft, m_left, (getAttribute(LEFT_CARDINALITY) == null ? 1 : Integer.parseInt(getAttribute(LEFT_CARDINALITY))), m_rightClass, notify);
+ }
+ }
+
+ /**
+ * Locates the right endpoint by using the generic locateEndpoint and notifies
+ * listeners of changes, if any.
+ * @param notify Indicates whether notifications should be sent out.
+ */
+ private void locateRightEndpoint(boolean notify) {
+ synchronized (m_lock) {
+ m_right = locateEndpoint(m_rightRepository, m_filterRight, m_right, (getAttribute(RIGHT_CARDINALITY) == null ? 1 : Integer.parseInt(getAttribute(RIGHT_CARDINALITY))), m_leftClass, notify);
+ }
+ }
+
+ public boolean isSatisfied() {
+ return (!m_left.isEmpty()) && (!m_right.isEmpty());
+ }
+
+ @Override
+ public void handleEvent(Event event) {
+ // We get a topic which ends in '/*', but the event contains a specialized topic.
+ // for now, we chop of the star, and check whether the topic starts with that.
+ RepositoryObject entity = (RepositoryObject) event.getProperty(RepositoryObject.EVENT_ENTITY);
+ if ((event.getTopic().endsWith("ADDED")) || event.getTopic().endsWith("REMOVED")) {
+ if (m_leftClass.isInstance(entity) && m_filterLeft.match(entity.getDictionary())) {
+ locateLeftEndpoint(true);
+ }
+ if (m_rightClass.isInstance(entity) && m_filterRight.match(entity.getDictionary())) {
+ locateRightEndpoint(true);
+ }
+ }
+ }
+
+}