You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by ma...@apache.org on 2013/04/02 16:53:35 UTC
svn commit: r1463576 [2/8] - in /ace/trunk:
org.apache.ace.client.repository.api/
org.apache.ace.client.repository.helper.base/
org.apache.ace.client.repository.helper.bundle/
org.apache.ace.client.repository.helper.configuration/
org.apache.ace.client...
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/base/ArtifactPreprocessorBase.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,304 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.base;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+
+import org.apache.ace.client.repository.helper.ArtifactPreprocessor;
+import org.apache.ace.connectionfactory.ConnectionFactory;
+
+/**
+ * This class can be used as a base class for artifact preprocessors. It comes with its own upload() method, which will
+ * be used by all artifact preprocessors anyway.
+ */
+public abstract class ArtifactPreprocessorBase implements ArtifactPreprocessor {
+
+ /** 64k buffers should be enough for everybody... */
+ protected static final int BUFFER_SIZE = 64 * 1024;
+
+ protected final ConnectionFactory m_connectionFactory;
+ private final ExecutorService m_executor;
+
+ /**
+ * Creates a new {@link ArtifactPreprocessorBase} instance.
+ *
+ * @param connectionFactory
+ * the connection factory to use, cannot be <code>null</code>.
+ */
+ protected ArtifactPreprocessorBase(ConnectionFactory connectionFactory) {
+ m_connectionFactory = connectionFactory;
+ m_executor = Executors.newCachedThreadPool();
+ }
+
+ /**
+ * Creates a new URL for given (file) name and OBR base URL.
+ *
+ * @param name
+ * the name of the file to create the URL for;
+ * @param obrBase
+ * the OBR base URL to use.
+ * @return a new URL for the file, never <code>null</code>.
+ * @throws MalformedURLException
+ * in case of invalid characters in the given name.
+ */
+ protected URL determineNewUrl(String name, URL obrBase) throws MalformedURLException {
+ return new URL(obrBase, name);
+ }
+
+ /**
+ * Silently closes the given {@link Closeable} instance.
+ *
+ * @param closable
+ * the closeable to close, may be <code>null</code>.
+ */
+ protected final void silentlyClose(Closeable closable) {
+ if (closable != null) {
+ try {
+ closable.close();
+ }
+ catch (IOException e) {
+ // Ignore; nothing we can/will do about here...
+ }
+ }
+ }
+
+ /**
+ * Gets a stream to write an artifact to, which will be uploaded asynchronously to the OBR.
+ *
+ * @param name
+ * The name of the artifact.
+ * @param obrBase
+ * The base URL of the obr to which this artifact should be written.
+ * @param inputStream
+ * the input stream with data to upload.
+ */
+ protected final Future<URL> uploadAsynchronously(final String name, final URL obrBase, final InputStream inputStream) {
+ return m_executor.submit(new Callable<URL>() {
+ public URL call() throws IOException {
+ return upload(inputStream, name, obrBase);
+ }
+ });
+ }
+
+ /**
+ * Converts a given URL to a {@link File} object.
+ *
+ * @param url
+ * the URL to convert, cannot be <code>null</code>.
+ * @return a {@link File} object, never <code>null</code>.
+ */
+ protected final File urlToFile(URL url) {
+ File file;
+ try {
+ file = new File(url.toURI());
+ }
+ catch (URISyntaxException e) {
+ file = new File(url.getPath());
+ }
+ return file;
+ }
+
+ /**
+ * Uploads an artifact synchronously to an OBR.
+ *
+ * @param input
+ * A inputstream from which the artifact can be read.
+ * @param name
+ * The name of the artifact. If the name is not unique, an IOException will be thrown.
+ * @param obrBase
+ * The base URL of the obr to which this artifact should be written.
+ * @return A URL to the uploaded artifact; this is identical to calling <code>determineNewUrl(name, obrBase)</code>
+ * @throws IOException
+ * If there was an error reading from <code>input</code>, or if there was a problem communicating with
+ * the OBR.
+ */
+ private URL upload(InputStream input, String name, URL obrBase) throws IOException {
+ if (obrBase == null) {
+ throw new IOException("There is no storage available for this artifact.");
+ }
+ if ((name == null) || (input == null)) {
+ throw new IllegalArgumentException("None of the parameters can be null.");
+ }
+
+ URL url = null;
+ try {
+ url = determineNewUrl(name, obrBase);
+
+ if (!urlPointsToExistingFile(url)) {
+ if ("file".equals(url.getProtocol())) {
+ uploadToFile(input, url);
+ }
+ else {
+ uploadToRemote(input, url);
+ }
+ }
+ }
+ catch (IOException ioe) {
+ throw new IOException("Error uploading " + name + ": " + ioe.getMessage());
+ }
+ finally {
+ silentlyClose(input);
+ }
+
+ return url;
+ }
+
+ /**
+ * Uploads an artifact to a local file location.
+ *
+ * @param input
+ * the input stream of the (local) artifact to upload.
+ * @param url
+ * the URL of the (file) artifact to upload to.
+ * @throws IOException
+ * in case of I/O problems.
+ */
+ private void uploadToFile(InputStream input, URL url) throws IOException {
+ File file = urlToFile(url);
+
+ OutputStream output = null;
+
+ try {
+ output = new FileOutputStream(file);
+
+ byte[] buffer = new byte[BUFFER_SIZE];
+ for (int count = input.read(buffer); count != -1; count = input.read(buffer)) {
+ output.write(buffer, 0, count);
+ }
+ }
+ finally {
+ silentlyClose(output);
+ }
+ }
+
+ /**
+ * Uploads an artifact to a remote location.
+ *
+ * @param input
+ * the input stream of the (local) artifact to upload.
+ * @param url
+ * the URL of the (remote) artifact to upload to.
+ * @throws IOException
+ * in case of I/O problems, or when the upload was refused by the remote.
+ */
+ private void uploadToRemote(InputStream input, URL url) throws IOException {
+ OutputStream output = null;
+
+ try {
+ URLConnection connection = m_connectionFactory.createConnection(url);
+ if (connection instanceof HttpURLConnection) {
+ // ACE-294: enable streaming mode causing only small amounts of memory to be
+ // used for this commit. Otherwise, the entire input stream is cached into
+ // memory prior to sending it to the server...
+ ((HttpURLConnection) connection).setChunkedStreamingMode(8192);
+ }
+ connection.setDoOutput(true);
+
+ output = connection.getOutputStream();
+
+ byte[] buffer = new byte[BUFFER_SIZE];
+ 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());
+ }
+ }
+ }
+ finally {
+ silentlyClose(output);
+ }
+ }
+
+ /**
+ * Determines whether the given URL points to an existing file.
+ *
+ * @param url
+ * the URL to test, cannot be <code>null</code>.
+ * @return <code>true</code> if the given URL points to an existing file, <code>false</code> otherwise.
+ */
+ private boolean urlPointsToExistingFile(URL url) {
+ boolean result = false;
+
+ if ("file".equals(url.getProtocol())) {
+ result = urlToFile(url).exists();
+ }
+ else {
+ try {
+ URLConnection connection = m_connectionFactory.createConnection(url);
+
+ if (connection instanceof HttpURLConnection) {
+ HttpURLConnection hc = (HttpURLConnection) connection;
+
+ // Perform a HEAD on the file, to see whether it exists...
+ hc.setRequestMethod("HEAD");
+ try {
+ int responseCode = hc.getResponseCode();
+ result = (responseCode == HttpURLConnection.HTTP_OK);
+ }
+ finally {
+ hc.disconnect();
+ }
+ }
+ else {
+ // In all other scenario's: try to read a single byte from the input
+ // stream, if this succeeds, we can assume the file exists...
+ InputStream is = connection.getInputStream();
+ try {
+ is.read();
+ }
+ finally {
+ silentlyClose(is);
+ }
+ }
+ }
+ catch (IOException e) {
+ // Ignore; assume file does not exist...
+ }
+ }
+
+ return result;
+ }
+}
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/base/VelocityArtifactPreprocessor.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,318 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.base;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.lang.ref.Reference;
+import java.lang.ref.WeakReference;
+import java.net.URL;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.ace.client.repository.helper.PropertyResolver;
+import org.apache.ace.connectionfactory.ConnectionFactory;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+
+/**
+ * This class can be used as a 'default' artifact preprocessor, using the Velocity template engine to preprocess
+ * the artifact.
+ */
+public class VelocityArtifactPreprocessor extends ArtifactPreprocessorBase {
+
+ private static Object m_initLock = new Object();
+ private static boolean m_velocityInitialized = false;
+
+ private final Map<String, Reference<byte[]>> m_cachedArtifacts;
+ private final Map<String, Reference<String>> m_cachedHashes;
+ private final MessageDigest m_md5;
+
+ /**
+ * Creates a new {@link VelocityArtifactPreprocessor} instance.
+ * @param connectionFactory
+ */
+ public VelocityArtifactPreprocessor(ConnectionFactory connectionFactory) {
+ super(connectionFactory);
+
+ try {
+ m_md5 = MessageDigest.getInstance("MD5");
+ }
+ catch (NoSuchAlgorithmException e) {
+ throw new RuntimeException("Failed to create VelocityArtifactPreprocessor instance!", e);
+ }
+
+ m_cachedArtifacts = new ConcurrentHashMap<String, Reference<byte[]>>();
+ m_cachedHashes = new ConcurrentHashMap<String, Reference<String>>();
+ }
+
+ @Override
+ public boolean needsNewVersion(String url, PropertyResolver props, String targetID, String fromVersion) {
+ // get the template
+ byte[] input = null;
+ byte[] result = null;
+
+ try {
+ init();
+
+ input = getArtifactAsBytes(url);
+ result = process(input, props);
+ }
+ catch (IOException ioe) {
+ // problem initializing velocity, or we cannot retrieve the
+ // original artifact, or process it; we can't say anything now.
+ return true;
+ }
+
+ // process the template
+ // first check: did we need any processing at all?
+ if (Arrays.equals(result, input)) {
+ return false;
+ }
+
+ // hash the processed template
+ String newHash = hash(result);
+
+ // find the hash for the previous version
+ String oldHash = getHashForVersion(url, targetID, fromVersion);
+
+ // Note: we do not cache any previously created processed templates, since the call that asks us to approve a new version
+ // may cross a pending needsNewVersion call.
+ return !newHash.equals(oldHash);
+ }
+
+ @Override
+ public String preprocess(String url, PropertyResolver props, String targetID, String version, URL obrBase) throws IOException {
+ init();
+
+ // first, get the original data.
+ byte[] input = getArtifactAsBytes(url);
+ // process the template
+ byte[] result = process(input, props);
+
+ // first check: did we need any processing at all?
+ if (Arrays.equals(result, input)) {
+ // template isn't modified; use direct URL instead...
+ return url;
+ }
+
+ setHashForVersion(url, targetID, version, hash(result));
+
+ String name = getFilename(url, targetID, version);
+
+ uploadAsynchronously(name, obrBase, new ByteArrayInputStream(result));
+
+ return determineNewUrl(name, obrBase).toString();
+ }
+
+ /**
+ * Initializes this preprocessor by making sure {@link Velocity#init()} is called.
+ * <p>This method may be called multiple times.</p>
+ *
+ * @throws IOException in case of problems initializing Velocity.
+ */
+ private void init() throws IOException {
+ if (m_velocityInitialized) {
+ return;
+ }
+ else {
+ synchronized (m_initLock) {
+ if (!m_velocityInitialized) {
+ try {
+ Velocity.init();
+ m_velocityInitialized = true;
+ }
+ catch (Exception e) {
+ // Something went seriously bad initializing velocity.
+ throw new IOException("Error initializing Velocity: " + e.getMessage());
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * @param url
+ * @param targetID
+ * @param version
+ * @return
+ */
+ private String getFilename(String url, String targetID, String version) {
+ int indexOfLastSlash = url.lastIndexOf('/');
+ if (indexOfLastSlash != -1) {
+ url = url.substring(indexOfLastSlash + 1);
+ }
+ return url + "-" + targetID + "-" + version;
+ }
+
+ /**
+ * @param url
+ * @param targetID
+ * @param version
+ * @return
+ */
+ private String getFullUrl(String url, String targetID, String version) {
+ return url + "-" + targetID + "-" + version;
+ }
+
+ /**
+ * @param url
+ * @param target
+ * @param version
+ * @return
+ */
+ private String getHashForVersion(String url, String target, String version) {
+ String key = createHashKey(url, target, version);
+
+ Reference<String> ref = m_cachedHashes.get(key);
+ String hash = (ref != null) ? ref.get() : null;
+ if (hash == null) {
+ try {
+ hash = hash(getBytesFromUrl(getFullUrl(url, target, version)));
+
+ m_cachedHashes.put(key, new WeakReference<String>(hash));
+ }
+ catch (IOException e) {
+ // we cannot retrieve the artifact, so we cannot say anything about it.
+ }
+ }
+
+ return hash;
+ }
+
+ /**
+ * @param url
+ * @param target
+ * @param version
+ * @param hash
+ */
+ private void setHashForVersion(String url, String target, String version, String hash) {
+ String key = createHashKey(url, target, version);
+
+ m_cachedHashes.put(key, new WeakReference<String>(hash));
+ }
+
+ /**
+ * Applies the template processor to the given byte array.
+ *
+ * @param input the template (as byte array) to process;
+ * @param props the {@link PropertyResolver} to use.
+ * @return the processed template, never <code>null</code>.
+ * @throws IOException in case of I/O problems.
+ */
+ private byte[] process(byte[] input, PropertyResolver props) throws IOException {
+ VelocityContext context = new VelocityContext();
+ context.put("context", props);
+
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ Writer writer = new OutputStreamWriter(baos);
+ Velocity.evaluate(context, writer, "", new InputStreamReader(new ByteArrayInputStream(input)));
+ writer.flush();
+ return baos.toByteArray();
+ }
+ catch (IOException ioe) {
+ throw new IOException("Error processing the artifact: " + ioe.getMessage());
+ }
+ }
+
+ /**
+ * Reads all information from a given URL, and returns that as a byte array. The byte array is not to be changed, and could be potentially come from a cache.
+ *
+ * @param url the URL to read the artifact from, cannot be <code>null</code>.
+ * @return the read (or cached) bytes, can be <code>null</code>.
+ * @throws IOException in case of I/O problems.
+ */
+ private byte[] getArtifactAsBytes(String url) throws IOException {
+ byte[] result = null;
+
+ Reference<byte[]> ref = m_cachedArtifacts.get(url);
+ if (ref == null || ((result = ref.get()) == null)) {
+ result = getBytesFromUrl(url);
+ }
+ return result;
+ }
+
+ /**
+ * Reads all bytes from the given URL and caches its result.
+ *
+ * @param url the URL to read the bytes for, cannot be <code>null</code>.
+ * @return the read bytes from the given URL, can be <code>null</code> if the reading failed.
+ * @throws IOException in case of I/O problems.
+ */
+ private byte[] getBytesFromUrl(String url) throws IOException {
+ byte[] result = null;
+
+ // ACE-267
+ InputStream in = m_connectionFactory.createConnection(new URL(url)).getInputStream();
+ try {
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ byte[] buf = new byte[BUFFER_SIZE];
+ for (int count = in.read(buf); count != -1; count = in.read(buf)) {
+ baos.write(buf, 0, count);
+ }
+
+ result = baos.toByteArray();
+
+ m_cachedArtifacts.put(url, new WeakReference<byte[]>(result));
+ }
+ finally {
+ silentlyClose(in);
+ }
+
+ return result;
+ }
+
+ /**
+ * Creates a key for storing/retrieving a hash.
+ *
+ * @param url
+ * @param target
+ * @param version
+ * @return a hash key, never <code>null</code>.
+ */
+ private String createHashKey(String url, String target, String version) {
+ return new StringBuilder().append('[')
+ .append(url)
+ .append("][")
+ .append(target)
+ .append("][")
+ .append(version)
+ .append(']').toString();
+ }
+
+ /**
+ * Computes a hash for a given byte array.
+ *
+ * @param input the byte array to compute the hash for.
+ * @return a hash for the given byte array, never <code>null</code>.
+ */
+ private String hash(byte[] input) {
+ return new String(m_md5.digest(input));
+ }
+}
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/base/packageinfo
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/base/packageinfo?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/base/packageinfo (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/base/packageinfo Tue Apr 2 14:53:33 2013
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/BundleHelper.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/BundleHelper.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/BundleHelper.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/BundleHelper.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.bundle;
+
+import org.apache.ace.client.repository.helper.ArtifactHelper;
+import org.apache.ace.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);
+}
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/impl/Activator.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/impl/Activator.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/impl/Activator.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/impl/Activator.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.bundle.impl;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.ace.client.repository.helper.ArtifactHelper;
+import org.apache.ace.client.repository.helper.ArtifactRecognizer;
+import org.apache.ace.client.repository.helper.bundle.BundleHelper;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.felix.dm.DependencyActivatorBase;
+import org.apache.felix.dm.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(createComponent()
+ .setInterface(ArtifactHelper.class.getName(), props)
+ .setImplementation(helperImpl));
+ manager.add(createComponent()
+ .setInterface(ArtifactRecognizer.class.getName(), null)
+ .setImplementation(helperImpl));
+ manager.add(createComponent()
+ .setInterface(BundleHelper.class.getName(), null)
+ .setImplementation(helperImpl));
+ }
+
+ @Override
+ public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ // Nothing to do
+ }
+}
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/impl/BundleHelperImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/impl/BundleHelperImpl.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/impl/BundleHelperImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/impl/BundleHelperImpl.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,285 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.bundle.impl;
+
+import java.io.IOException;
+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 org.apache.ace.client.repository.RepositoryUtil;
+import org.apache.ace.client.repository.helper.ArtifactHelper;
+import org.apache.ace.client.repository.helper.ArtifactPreprocessor;
+import org.apache.ace.client.repository.helper.ArtifactRecognizer;
+import org.apache.ace.client.repository.helper.ArtifactResource;
+import org.apache.ace.client.repository.helper.bundle.BundleHelper;
+import org.apache.ace.client.repository.object.ArtifactObject;
+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(ArtifactResource 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 {
+ if (jis != null) {
+ jis.close();
+ }
+ }
+ catch (IOException e) {
+ // Too bad.
+ }
+ }
+ }
+
+ public String recognize(ArtifactResource 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 {
+ if (jis != null) {
+ jis.close();
+ }
+ }
+ catch (Exception e) {
+ // Too bad.
+ }
+ }
+ return null;
+ }
+
+ public ArtifactPreprocessor getPreprocessor() {
+ return null;
+ }
+
+ public String getExtension(ArtifactResource artifact) {
+ return ".jar";
+ }
+}
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/impl/VersionRange.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/impl/VersionRange.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/impl/VersionRange.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/impl/VersionRange.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.bundle.impl;
+
+import org.osgi.framework.Version;
+
+class VersionRange
+{
+ private Version m_low = null;
+ private boolean m_isLowInclusive = false;
+ private Version m_high = null;
+ private boolean m_isHighInclusive = false;
+ private String m_toString = null;
+
+ public static final VersionRange infiniteRange = new VersionRange(
+ Version.emptyVersion, true, null, true);
+
+ public VersionRange(Version low, boolean isLowInclusive, Version high, boolean isHighInclusive) {
+ m_low = low;
+ m_isLowInclusive = isLowInclusive;
+ m_high = high;
+ m_isHighInclusive = isHighInclusive;
+ }
+
+ public Version getLow() {
+ return m_low;
+ }
+
+ public boolean isLowInclusive() {
+ return m_isLowInclusive;
+ }
+
+ public Version getHigh() {
+ return m_high;
+ }
+
+ public boolean isHighInclusive() {
+ return m_isHighInclusive;
+ }
+
+ public boolean isInRange(Version version) {
+ // We might not have an upper end to the range.
+ if (m_high == null) {
+ return (version.compareTo(m_low) >= 0);
+ }
+ else if (isLowInclusive() && isHighInclusive()) {
+ return (version.compareTo(m_low) >= 0) &&
+ (version.compareTo(m_high) <= 0);
+ }
+ else if (isHighInclusive()) {
+ return (version.compareTo(m_low) > 0) &&
+ (version.compareTo(m_high) <= 0);
+ }
+ else if (isLowInclusive()) {
+ return (version.compareTo(m_low) >= 0) &&
+ (version.compareTo(m_high) < 0);
+ }
+ return (version.compareTo(m_low) > 0) &&
+ (version.compareTo(m_high) < 0);
+ }
+
+ public static VersionRange parse(String range) {
+ // Check if the version is an interval.
+ if (range.indexOf(',') >= 0) {
+ String s = range.substring(1, range.length() - 1);
+ String vlo = s.substring(0, s.indexOf(',')).trim();
+ String vhi = s.substring(s.indexOf(',') + 1, s.length()).trim();
+ return new VersionRange(new Version(vlo), (range.charAt(0) == '['),
+ new Version(vhi), (range.charAt(range.length() - 1) == ']'));
+ }
+ else {
+ return new VersionRange(new Version(range), true, null, false);
+ }
+ }
+
+ public String toString() {
+ if (m_toString == null) {
+ if (m_high != null) {
+ StringBuffer sb = new StringBuffer();
+ sb.append(m_isLowInclusive ? '[' : '(');
+ sb.append(m_low.toString());
+ sb.append(',');
+ sb.append(m_high.toString());
+ sb.append(m_isHighInclusive ? ']' : ')');
+ m_toString = sb.toString();
+ }
+ else {
+ m_toString = m_low.toString();
+ }
+ }
+ return m_toString;
+ }
+}
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/packageinfo
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/packageinfo?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/packageinfo (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/bundle/packageinfo Tue Apr 2 14:53:33 2013
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/ConfigurationHelper.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/ConfigurationHelper.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/ConfigurationHelper.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/ConfigurationHelper.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.configuration;
+
+import org.apache.ace.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";
+}
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/Activator.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/Activator.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/Activator.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/Activator.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.configuration.impl;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.ace.client.repository.helper.ArtifactHelper;
+import org.apache.ace.client.repository.helper.ArtifactRecognizer;
+import org.apache.ace.client.repository.helper.configuration.ConfigurationHelper;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.ace.connectionfactory.ConnectionFactory;
+import org.apache.felix.dm.DependencyActivatorBase;
+import org.apache.felix.dm.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(createComponent()
+ .setInterface(new String[] { ArtifactHelper.class.getName(), ArtifactRecognizer.class.getName() }, props)
+ .setImplementation(helperImpl)
+ .add(createServiceDependency()
+ .setService(ConnectionFactory.class)
+ .setRequired(true))
+ );
+ }
+
+ @Override
+ public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ // Nothing to do
+ }
+}
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/impl/ConfigurationHelperImpl.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.configuration.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.apache.ace.client.repository.helper.ArtifactPreprocessor;
+import org.apache.ace.client.repository.helper.ArtifactRecognizer;
+import org.apache.ace.client.repository.helper.ArtifactResource;
+import org.apache.ace.client.repository.helper.base.VelocityArtifactPreprocessor;
+import org.apache.ace.client.repository.helper.configuration.ConfigurationHelper;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.ace.connectionfactory.ConnectionFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public class ConfigurationHelperImpl implements ArtifactRecognizer, ConfigurationHelper {
+
+ // known valid metatype namespaces
+ private static final String NAMESPACE_1_0 = "http://www.osgi.org/xmlns/metatype/v1.0.0";
+ private static final String NAMESPACE_1_1 = "http://www.osgi.org/xmlns/metatype/v1.1.0";
+ private static final String NAMESPACE_1_2 = "http://www.osgi.org/xmlns/metatype/v1.2.0";
+
+ private final SAXParserFactory m_saxParserFactory;
+
+ // Injected by Dependency Manager
+ private volatile ConnectionFactory m_connectionFactory;
+ // Created in #start()
+ private volatile VelocityArtifactPreprocessor m_artifactPreprocessor;
+
+ public ConfigurationHelperImpl() {
+ m_saxParserFactory = SAXParserFactory.newInstance();
+ m_saxParserFactory.setNamespaceAware(false);
+ m_saxParserFactory.setValidating(false);
+ }
+
+ public boolean canHandle(String mimetype) {
+ return MIMETYPE.equals(mimetype);
+ }
+
+ public Map<String, String> extractMetaData(ArtifactResource artifact) throws IllegalArgumentException {
+ Map<String, String> result = new HashMap<String, String>();
+ result.put(ArtifactObject.KEY_PROCESSOR_PID, PROCESSOR);
+ result.put(ArtifactObject.KEY_MIMETYPE, MIMETYPE);
+ String name = new File(artifact.getURL().getFile()).getName();
+ String key = KEY_FILENAME + "-";
+ int idx = name.indexOf(key);
+ if (idx > -1) {
+ int endIdx = name.indexOf("-", idx + key.length());
+ name = name.substring(idx + key.length(), (endIdx > -1) ? endIdx : (name.length() - getExtension(artifact).length()));
+ }
+ result.put(ArtifactObject.KEY_ARTIFACT_NAME, name);
+ result.put(KEY_FILENAME, name);
+ return result;
+ }
+
+ public String recognize(ArtifactResource artifact) {
+ MetaDataNamespaceCollector handler = new MetaDataNamespaceCollector();
+ InputStream input = null;
+ try {
+ input = artifact.openStream();
+ SAXParser parser = m_saxParserFactory.newSAXParser();
+ parser.parse(input, handler);
+ }
+ catch (Exception e) {
+ String namespace = handler.getMetaDataNamespace();
+ if (namespace != null
+ && (namespace.equals(NAMESPACE_1_0)
+ || namespace.equals(NAMESPACE_1_1)
+ || namespace.equals(NAMESPACE_1_2))) {
+ return MIMETYPE;
+ }
+ }
+ finally {
+ if (input != null) {
+ try {
+ input.close();
+ }
+ catch (IOException e) {}
+ }
+ }
+ 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};
+ }
+
+ public ArtifactPreprocessor getPreprocessor() {
+ return m_artifactPreprocessor;
+ }
+
+ public String getExtension(ArtifactResource artifact) {
+ return ".xml";
+ }
+
+ /**
+ * Called by dependency manager upon start of this component.
+ */
+ protected void start() {
+ m_artifactPreprocessor = new VelocityArtifactPreprocessor(m_connectionFactory);
+ }
+
+ /**
+ * Called by dependency manager upon stopping of this component.
+ */
+ protected void stop() {
+ m_artifactPreprocessor = null;
+
+ }
+
+ static class MetaDataNamespaceCollector extends DefaultHandler {
+
+ private String m_metaDataNameSpace = "";
+
+ public String getMetaDataNamespace() {
+ return m_metaDataNameSpace;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes)
+ throws SAXException {
+ if (qName.equals("MetaData") || qName.endsWith(":MetaData")) {
+ String nsAttributeQName = "xmlns";
+ if (qName.endsWith(":MetaData")) {
+ nsAttributeQName = "xmlns" + ":" + qName.split(":")[0];
+ }
+ for (int i = 0; i < attributes.getLength(); i++) {
+ if (attributes.getQName(i).equals(nsAttributeQName)) {
+ m_metaDataNameSpace = attributes.getValue(i);
+ }
+ }
+ }
+ // first element is expected to have been the MetaData
+ // root so we can now terminate processing.
+ throw new SAXException("Done");
+ }
+ }
+}
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/packageinfo
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/packageinfo?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/packageinfo (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/configuration/packageinfo Tue Apr 2 14:53:33 2013
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/packageinfo
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/packageinfo?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/packageinfo (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/packageinfo Tue Apr 2 14:53:33 2013
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/UserAdminHelper.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/UserAdminHelper.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/UserAdminHelper.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/UserAdminHelper.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.user;
+
+import org.apache.ace.client.repository.helper.ArtifactHelper;
+
+/**
+ * Definitions for the UserAdminHelper artifact helper.
+ */
+public interface UserAdminHelper extends ArtifactHelper {
+ public static final String MIMETYPE = "application/vnd.apache.ace.useradmin";
+ public static final String PROCESSOR = "org.apache.ace.resourceprocessor.useradmin";
+}
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/Activator.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/Activator.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/Activator.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/Activator.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.user.impl;
+
+import java.util.Properties;
+
+import org.apache.ace.client.repository.helper.ArtifactHelper;
+import org.apache.ace.client.repository.helper.ArtifactRecognizer;
+import org.apache.ace.client.repository.helper.user.UserAdminHelper;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.ace.connectionfactory.ConnectionFactory;
+import org.apache.felix.dm.DependencyActivatorBase;
+import org.apache.felix.dm.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(Constants.SERVICE_RANKING, 10);
+ props.put(ArtifactObject.KEY_MIMETYPE, UserAdminHelper.MIMETYPE);
+
+ UserHelperImpl helperImpl = new UserHelperImpl();
+ manager.add(createComponent()
+ .setInterface(new String[]{ ArtifactHelper.class.getName(), ArtifactRecognizer.class.getName() }, props)
+ .setImplementation(helperImpl)
+ .add(createServiceDependency()
+ .setService(ConnectionFactory.class)
+ .setRequired(true))
+ );
+ }
+
+ @Override
+ public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ // Nothing to do
+ }
+}
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/UserHelperImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/UserHelperImpl.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/UserHelperImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/impl/UserHelperImpl.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.helper.user.impl;
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.apache.ace.client.repository.helper.ArtifactPreprocessor;
+import org.apache.ace.client.repository.helper.ArtifactRecognizer;
+import org.apache.ace.client.repository.helper.ArtifactResource;
+import org.apache.ace.client.repository.helper.base.VelocityArtifactPreprocessor;
+import org.apache.ace.client.repository.helper.user.UserAdminHelper;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.ace.connectionfactory.ConnectionFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+public class UserHelperImpl implements ArtifactRecognizer, UserAdminHelper {
+
+ // Injected by Dependency Manager
+ private volatile ConnectionFactory m_connectionFactory;
+ // Created in #start()
+ private volatile VelocityArtifactPreprocessor m_artifactPreprocessor;
+
+ public boolean canHandle(String mimetype) {
+ return MIMETYPE.equals(mimetype);
+ }
+
+ public Map<String, String> extractMetaData(ArtifactResource artifact) throws IllegalArgumentException {
+ Map<String, String> result = new HashMap<String, String>();
+ result.put(ArtifactObject.KEY_PROCESSOR_PID, PROCESSOR);
+ result.put(ArtifactObject.KEY_MIMETYPE, MIMETYPE);
+ String name = new File(artifact.getURL().getFile()).getName();
+ String key = ArtifactObject.KEY_ARTIFACT_NAME + "-";
+ int idx = name.indexOf(key);
+ if (idx > -1) {
+ int endIdx = name.indexOf("-", idx + key.length());
+ name = name.substring(idx + key.length(), (endIdx > -1) ? endIdx : (name.length() - getExtension(artifact).length()));
+ }
+ result.put(ArtifactObject.KEY_ARTIFACT_NAME, name);
+ return result;
+ }
+
+ public String recognize(ArtifactResource 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};
+ }
+
+ public ArtifactPreprocessor getPreprocessor() {
+ return m_artifactPreprocessor;
+ }
+
+ public String getExtension(ArtifactResource artifact) {
+ return ".xml";
+ }
+
+ /**
+ * Called by dependency manager upon start of this component.
+ */
+ protected void start() {
+ m_artifactPreprocessor = new VelocityArtifactPreprocessor(m_connectionFactory);
+ }
+
+ /**
+ * Called by dependency manager upon stopping of this component.
+ */
+ protected void stop() {
+ m_artifactPreprocessor = null;
+
+ }
+}
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/packageinfo
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/packageinfo?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/packageinfo (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/helper/user/packageinfo Tue Apr 2 14:53:33 2013
@@ -0,0 +1 @@
+version 1.0
\ No newline at end of file
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Activator.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Activator.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Activator.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Activator.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.impl;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import org.apache.ace.client.repository.RepositoryAdmin;
+import org.apache.ace.client.repository.SessionFactory;
+import org.apache.ace.client.repository.helper.bundle.BundleHelper;
+import org.apache.ace.client.repository.object.Artifact2FeatureAssociation;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.ace.client.repository.object.DeploymentVersionObject;
+import org.apache.ace.client.repository.object.Distribution2TargetAssociation;
+import org.apache.ace.client.repository.object.DistributionObject;
+import org.apache.ace.client.repository.object.Feature2DistributionAssociation;
+import org.apache.ace.client.repository.object.FeatureObject;
+import org.apache.ace.client.repository.object.TargetObject;
+import org.apache.ace.client.repository.repository.ArtifactRepository;
+import org.apache.ace.client.repository.repository.DeploymentVersionRepository;
+import org.apache.ace.client.repository.repository.TargetRepository;
+import org.apache.ace.client.repository.stateful.StatefulTargetRepository;
+import org.apache.ace.client.repository.stateful.impl.StatefulTargetRepositoryImpl;
+import org.apache.ace.server.log.store.LogStore;
+import org.apache.felix.dm.Component;
+import org.apache.felix.dm.DependencyActivatorBase;
+import org.apache.felix.dm.DependencyManager;
+import org.apache.felix.service.command.CommandProcessor;
+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;
+import org.osgi.service.prefs.PreferencesService;
+
+/**
+ * Activator for the RepositoryAdmin bundle. Creates the repository admin, which internally
+ * creates all required repositories.
+ */
+public class Activator extends DependencyActivatorBase implements SessionFactory {
+
+ private final Map<String, SessionData> m_sessions = new HashMap<String, SessionData>();
+
+ private volatile DependencyManager m_dependencyManager;
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void init(BundleContext context, DependencyManager manager) throws Exception {
+ m_dependencyManager = manager;
+
+ Properties props = new Properties();
+ props.put(CommandProcessor.COMMAND_SCOPE, "clientrepo");
+ props.put(CommandProcessor.COMMAND_FUNCTION, new String[] { "sessions" });
+
+ manager.add(createComponent()
+ .setInterface(SessionFactory.class.getName(), props)
+ .setImplementation(this)
+ );
+ }
+
+ /** Shell command to show the active sessions. */
+ public void sessions() {
+ synchronized (m_sessions) {
+ if (m_sessions.isEmpty()) {
+ System.out.println("No sessions.");
+ }
+ else {
+ System.out.println("Sessions:");
+ for (Entry<String, SessionData> session : m_sessions.entrySet()) {
+ System.out.println(" * " + session.getKey());
+ }
+ }
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public synchronized void destroy(BundleContext context, DependencyManager manager) throws Exception {
+ // Nop
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void createSession(String sessionID) {
+ SessionData sessionData = null;
+ synchronized (m_sessions) {
+ if (!m_sessions.containsKey(sessionID)) {
+ sessionData = new SessionData();
+ m_sessions.put(sessionID, sessionData);
+ }
+ }
+
+ // Allow session to be created outside the lock; to avoid potential deadlocks...
+ if (sessionData != null) {
+ createSessionServices(sessionData, sessionID);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void destroySession(String sessionID) {
+ SessionData sessionData = null;
+ synchronized (m_sessions) {
+ sessionData = m_sessions.remove(sessionID);
+ }
+
+ // Allow session to be destroyed outside the lock; to avoid potential deadlocks...
+ if ((sessionData != null) && !sessionData.isEmpty()) {
+ destroySessionServices(sessionData, sessionID);
+ }
+ }
+
+ /**
+ * Creates all necessary session-related service for the given session.
+ *
+ * @param sd the session data to keep the session-related services;
+ * @param sessionID the session ID to use.
+ */
+ @SuppressWarnings("unchecked")
+ private void createSessionServices(SessionData sd, String sessionID) {
+ RepositoryAdminImpl rai = new RepositoryAdminImpl(sessionID);
+ Component comp1 = createComponent()
+ .setInterface(RepositoryAdmin.class.getName(), rai.getSessionProps())
+ .setImplementation(rai)
+ .setComposition("getInstances")
+ .add(createServiceDependency().setService(PreferencesService.class).setRequired(true))
+ .add(createServiceDependency().setService(EventAdmin.class).setRequired(true))
+ .add(createServiceDependency().setService(LogService.class).setRequired(false));
+
+ String sessionFilter = "(" + SessionFactory.SERVICE_SID + "=" + sessionID + ")";
+ String auditLogFilter = "(&(" + Constants.OBJECTCLASS + "=" + LogStore.class.getName() + ")(name=auditlog))";
+
+ Dictionary topic = new Hashtable();
+ topic.put(SessionFactory.SERVICE_SID, sessionID);
+ topic.put(EventConstants.EVENT_FILTER, sessionFilter);
+ topic.put(EventConstants.EVENT_TOPIC, new String[] {
+ ArtifactObject.TOPIC_ALL,
+ Artifact2FeatureAssociation.TOPIC_ALL,
+ FeatureObject.TOPIC_ALL,
+ Feature2DistributionAssociation.TOPIC_ALL,
+ DistributionObject.TOPIC_ALL,
+ Distribution2TargetAssociation.TOPIC_ALL,
+ TargetObject.TOPIC_ALL,
+ DeploymentVersionObject.TOPIC_ALL,
+ RepositoryAdmin.TOPIC_REFRESH,
+ RepositoryAdmin.TOPIC_LOGIN
+ });
+
+ StatefulTargetRepositoryImpl statefulTargetRepositoryImpl = new StatefulTargetRepositoryImpl(sessionID);
+ Component comp2 = createComponent()
+ .setInterface(new String[] { StatefulTargetRepository.class.getName(), EventHandler.class.getName() }, topic)
+ .setImplementation(statefulTargetRepositoryImpl)
+ .add(createServiceDependency().setService(ArtifactRepository.class, sessionFilter).setRequired(true))
+ .add(createServiceDependency().setService(TargetRepository.class, sessionFilter).setRequired(true))
+ .add(createServiceDependency().setService(DeploymentVersionRepository.class, sessionFilter).setRequired(true))
+ .add(createServiceDependency().setService(LogStore.class, auditLogFilter).setRequired(false))
+ .add(createServiceDependency().setService(BundleHelper.class).setRequired(true))
+ .add(createServiceDependency().setService(EventAdmin.class).setRequired(true))
+ .add(createServiceDependency().setService(LogService.class).setRequired(false));
+
+ // Publish our components to our session data for later use...
+ sd.addComponents(m_dependencyManager, comp1, comp2);
+ }
+
+ /**
+ * Removes the session-related services from the session.
+ *
+ * @param sd the session data that keeps the session-related services;
+ * @param sessionID the session ID to use.
+ */
+ private void destroySessionServices(SessionData sd, String sessionID) {
+ sd.removeAllComponents(m_dependencyManager);
+ }
+
+ /**
+ * Small container that keeps the session-related services for us.
+ */
+ private static final class SessionData {
+ private final List<Component> m_services = new ArrayList<Component>();
+
+ final void addComponents(DependencyManager manager, Component... comps) {
+ synchronized (m_services) {
+ for (Component c : comps) {
+ m_services.add(c);
+ }
+ }
+
+ for (Component c : comps) {
+ manager.add(c);
+ }
+ }
+
+ final void removeAllComponents(DependencyManager manager) {
+ Component[] comps;
+ synchronized (m_services) {
+ comps = m_services.toArray(new Component[m_services.size()]);
+ m_services.clear();
+ }
+
+ for (Component c : comps) {
+ manager.remove(c);
+ }
+ }
+
+ final boolean isEmpty() {
+ synchronized (m_services) {
+ return m_services.isEmpty();
+ }
+ }
+ }
+}
Added: ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Artifact2FeatureAssociationImpl.java
URL: http://svn.apache.org/viewvc/ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Artifact2FeatureAssociationImpl.java?rev=1463576&view=auto
==============================================================================
--- ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Artifact2FeatureAssociationImpl.java (added)
+++ ace/trunk/org.apache.ace.client.repository/src/org/apache/ace/client/repository/impl/Artifact2FeatureAssociationImpl.java Tue Apr 2 14:53:33 2013
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.ace.client.repository.impl;
+
+import java.util.Map;
+
+import org.apache.ace.client.repository.object.Artifact2FeatureAssociation;
+import org.apache.ace.client.repository.object.ArtifactObject;
+import org.apache.ace.client.repository.object.FeatureObject;
+import org.osgi.framework.InvalidSyntaxException;
+
+import com.thoughtworks.xstream.io.HierarchicalStreamReader;
+
+/**
+ * Implementation class for the Artifact2FeatureAssociation. For 'what it does', see Artifact2FeatureAssociation,
+ * for 'how it works', see AssociationImpl.
+ */
+public class Artifact2FeatureAssociationImpl extends AssociationImpl<ArtifactObject, FeatureObject, Artifact2FeatureAssociation> implements Artifact2FeatureAssociation {
+ private final static String XML_NODE = "artifact2feature";
+
+ public Artifact2FeatureAssociationImpl(Map<String, String> attributes, ChangeNotifier notifier, ArtifactRepositoryImpl artifactRepository, FeatureRepositoryImpl featureRepository) throws InvalidSyntaxException {
+ super(attributes, notifier, ArtifactObject.class, FeatureObject.class, artifactRepository, featureRepository, XML_NODE);
+ }
+
+ public Artifact2FeatureAssociationImpl(Map<String, String> attributes, Map<String, String> tags, ChangeNotifier notifier, ArtifactRepositoryImpl artifactRepository, FeatureRepositoryImpl featureRepository) throws InvalidSyntaxException {
+ super(attributes, tags, notifier, ArtifactObject.class, FeatureObject.class, artifactRepository, featureRepository, XML_NODE);
+ }
+
+ public Artifact2FeatureAssociationImpl(HierarchicalStreamReader reader, ChangeNotifier notifier, ArtifactRepositoryImpl artifactRepository, FeatureRepositoryImpl featureRepository) throws InvalidSyntaxException {
+ super(reader, notifier, ArtifactObject.class, FeatureObject.class, null, null, artifactRepository, featureRepository, XML_NODE);
+ }
+}