You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by gn...@apache.org on 2010/04/02 11:43:00 UTC
svn commit: r930209 [1/2] - in /incubator/aries/trunk/subsystem: ./
org.osgi.service.composite/ org.osgi.service.composite/src/
org.osgi.service.composite/src/main/
org.osgi.service.composite/src/main/java/
org.osgi.service.composite/src/main/java/org/...
Author: gnodet
Date: Fri Apr 2 09:42:59 2010
New Revision: 930209
URL: http://svn.apache.org/viewvc?rev=930209&view=rev
Log:
[subsystem] check-in initial implementation
Added:
incubator/aries/trunk/subsystem/org.osgi.service.composite/
incubator/aries/trunk/subsystem/org.osgi.service.composite/pom.xml
incubator/aries/trunk/subsystem/org.osgi.service.composite/src/
incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/
incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/
incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/
incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/
incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/
incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/
incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeAdmin.java
incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeBundle.java
incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeConstants.java
incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/package.html
incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/packageinfo
incubator/aries/trunk/subsystem/subsystem-core/
incubator/aries/trunk/subsystem/subsystem-core/pom.xml
incubator/aries/trunk/subsystem/subsystem-core/src/
incubator/aries/trunk/subsystem/subsystem-core/src/main/
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceProcessor.java
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/DictionaryBuilder.java
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/FileUtils.java
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/NoOpResolver.java
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceImpl.java
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemAdminImpl.java
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemImpl.java
incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceProcessor.java
incubator/aries/trunk/subsystem/subsystem-install/
incubator/aries/trunk/subsystem/subsystem-install/pom.xml
incubator/aries/trunk/subsystem/subsystem-install/src/
incubator/aries/trunk/subsystem/subsystem-install/src/main/
incubator/aries/trunk/subsystem/subsystem-install/src/main/java/
incubator/aries/trunk/subsystem/subsystem-install/src/main/java/org/
incubator/aries/trunk/subsystem/subsystem-install/src/main/java/org/apache/
incubator/aries/trunk/subsystem/subsystem-install/src/main/java/org/apache/aries/
incubator/aries/trunk/subsystem/subsystem-install/src/main/java/org/apache/aries/subsystem/
incubator/aries/trunk/subsystem/subsystem-install/src/main/java/org/apache/aries/subsystem/install/
incubator/aries/trunk/subsystem/subsystem-install/src/main/java/org/apache/aries/subsystem/install/internal/
incubator/aries/trunk/subsystem/subsystem-install/src/main/java/org/apache/aries/subsystem/install/internal/SubsystemInstaller.java
incubator/aries/trunk/subsystem/subsystem-install/src/main/resources/
incubator/aries/trunk/subsystem/subsystem-install/src/main/resources/OSGI-INF/
incubator/aries/trunk/subsystem/subsystem-install/src/main/resources/OSGI-INF/blueprint/
incubator/aries/trunk/subsystem/subsystem-install/src/main/resources/OSGI-INF/blueprint/subsystem-install.xml
Modified:
incubator/aries/trunk/subsystem/pom.xml
Added: incubator/aries/trunk/subsystem/org.osgi.service.composite/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/org.osgi.service.composite/pom.xml?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/org.osgi.service.composite/pom.xml (added)
+++ incubator/aries/trunk/subsystem/org.osgi.service.composite/pom.xml Fri Apr 2 09:42:59 2010
@@ -0,0 +1,49 @@
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.aries.subsystem</groupId>
+ <artifactId>subsystem</artifactId>
+ <version>0.1-incubating-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.osgi.service.composite</artifactId>
+ <packaging>bundle</packaging>
+ <name>OSGi Composite API</name>
+ <description>
+ OSGi Composite API.
+ </description>
+
+ <properties>
+ <aries.osgi.export>
+ org.osgi.service.composite;version=1.0
+ </aries.osgi.export>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+</project>
Added: incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeAdmin.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeAdmin.java?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeAdmin.java (added)
+++ incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeAdmin.java Fri Apr 2 09:42:59 2010
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) OSGi Alliance (2009). All Rights Reserved.
+ *
+ * Licensed 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.osgi.service.composite;
+
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleException;
+
+/**
+ * The composite admin service is registered by a framework which supports
+ * composite bundles. The composite admin service is used to install
+ * composite bundles.
+ *
+ * @ThreadSafe
+ * @version $Revision: 8585 $
+ */
+public interface CompositeAdmin {
+ /**
+ * Installs a composite bundle into the parent framework with which this
+ * composite admin service is registered.
+ * <p>
+ * The following steps are required to install a composite:
+ * <ol>
+ * <li>The composite manifest is verified. If this fails, a {@linkplain BundleException}
+ * is thrown.</li>
+ * <li>If a bundle containing the same location identifier is already installed, if
+ * that bundle is a composite bundle the CompositeBundle object for that bundle is returned
+ * otherwise a {@link BundleException} is thrown.</li>
+ * <li>The composite's associated resources are allocated. The associated resources
+ * minimally consist of a unique identifier and a composite framework. If this
+ * step fails, a {@linkplain BundleException} is thrown.</li>
+ * <li>The composite framework is initialized and its start-level is set to 0.
+ * At this point no constituent bundles are installed in the composite framework.</li>
+ * <li>A bundle event of type {@linkplain BundleEvent#INSTALLED} is fired.</li>
+ * <li>The <code>CompositeBundle</code> object for the newly installed composite is
+ * returned</li>
+ * </ol>
+ *
+ * <b>Postconditions, no exceptions thrown </b>
+ * <ul>
+ * <li><code>getState()</code> in { <code>INSTALLED</code>,
+ * <code>RESOLVED</code> }.</li>
+ * <li>Composite has a unique ID.</li>
+ * <li>The composite framework is initialized, in the {@linkplain Bundle#STARTING}
+ * state and its start-level is set to 0.</li>
+ * </ul>
+ * <b>Postconditions, when an exception is thrown </b>
+ * <ul>
+ * <li>Composite is not installed and no trace of the composite exists.</li>
+ * </ul>
+ * @param location The location identifier of the composite to install.
+ * @param compositeManifest The meta-data describing the composite. This includes
+ * the symbolic name and version and the sharing policy.
+ * @param configuration The configuration parameters to the composite framework. See
+ * {@link CompositeConstants} for the supported configuration parameters.
+ * @return the installed composite bundle.
+ * @throws BundleException if the installation failed.
+ * @throws SecurityException If the caller does not have
+ * <code>AllPermission</code>.
+ * @throws IllegalStateException If this composite admin service is no longer valid.
+ * For example, if the framework has shutdown.
+ */
+ CompositeBundle installCompositeBundle(String location,
+ Map<String, String> compositeManifest,
+ Map<String, String> configuration)
+ throws BundleException;
+
+ /**
+ * Returns the parent composite bundle associated with the framework with which
+ * this composite admin service is registered. The composite admin service
+ * registered in the root framework must return <code>null</code>.
+ * @return The parent composite bundle or <code>null</code>.
+ */
+ CompositeBundle getParentCompositeBundle();
+}
Added: incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeBundle.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeBundle.java?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeBundle.java (added)
+++ incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeBundle.java Fri Apr 2 09:42:59 2010
@@ -0,0 +1,310 @@
+/*
+ * Copyright (c) OSGi Alliance (2009). All Rights Reserved.
+ *
+ * Licensed 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.osgi.service.composite;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.FrameworkEvent;
+
+/**
+ * A composite bundle is a bundle for which the content is composed of meta-data
+ * describing the composite and a set of bundles called constituent bundles.
+ * Constituent bundles are isolated from other bundles which are not
+ * constituents of the same composite bundle. Composites provide isolation
+ * for constituent bundles in the following ways.
+ * <ul>
+ * <li>Class space: Constraints specified by constituent bundles (e.g.
+ * Import-Package, Require-Bundle, Fragment-Host) can only be resolved
+ * against capabilities provided by other constituents within the same
+ * composite bundle (Export-Package, Bundle-SymbolicName/Bundle-Version).</li>
+ * <li>Service Registry: Constituent bundles only have access to services
+ * registered by other constituents within the same composite bundle.
+ * This includes service events and service references.</li>
+ * <li>Bundles: Constituent bundles only have access to other Bundle objects
+ * that represent constituents within the same composite bundle. This
+ * includes bundle events and core API like BundleContext.getBundles,
+ * PackageAdmin and StartLevel.</li>
+ * </ul>
+ * <p>
+ * A parent framework refers to the OSGi framework where a composite bundle
+ * is installed. A composite framework refers the framework where the
+ * constituent bundles are installed and provides the isolation for the
+ * constituent bundles. Constituent bundles are isolated
+ * but there are many cases where capabilities (packages and services) need
+ * to be shared between bundles installed in the parent framework and the
+ * constituents within a composite bundle.
+ * </p>
+ * <p>
+ * Through a sharing policy the composite is in control of what capabilities
+ * are shared across framework boundaries. The sharing policy controls what
+ * capabilities provided by bundles installed in the parent framework are
+ * imported into the composite and made available to constituent bundles.
+ * The sharing policy also controls what capabilities provided by
+ * constituent bundles are exported out of the composite and made available
+ * to bundles installed in the parent framework.
+ * </p>
+ * <p>
+ * The lifecycle of the constituent bundles are tied to the lifecycle of
+ * the composite bundle. See {@link #start(int)}, {@link #stop(int)},
+ * {@link #update(Map)} and {@link #uninstall}.
+ * </p>
+ *
+ * @ThreadSafe
+ * @version $Revision: 8585 $
+ */
+public interface CompositeBundle extends Bundle {
+ /**
+ * Returns the system bundle context for the composite framework. This
+ * method must return a valid {@link BundleContext} as long as this
+ * composite bundle is installed. Once a composite bundle is
+ * uninstalled this method must return <code>null</code>. The composite system
+ * bundle context can be used to install and manage the constituent bundles.
+ * @return the system bundle context for the composite framework
+ * @throws SecurityException If the caller does not have the
+ * appropriate <code>AdminPermission[system.bundle,CONTEXT]</code>, and
+ * the Java Runtime Environment supports permissions.
+ */
+ public BundleContext getSystemBundleContext();
+
+ /**
+ * Starts this composite with no options.
+ *
+ * <p>
+ * This method performs the same function as calling <code>start(0)</code>.
+ *
+ * @throws BundleException If this composite could not be started.
+ * @throws IllegalStateException If this composite has been uninstalled.
+ * @throws SecurityException If the caller does not have the appropriate
+ * <code>AdminPermission[this,EXECUTE]</code>, and the Java Runtime
+ * Environment supports permissions.
+ * @see #start(int)
+ */
+ public void start() throws BundleException;
+
+ /**
+ * Starts this composite according to {@link Bundle#start(int)}.
+ * When the composite bundle's state is set to {@link Bundle#STARTING} and
+ * after the {@link BundleEvent#STARTING} event has been fired for this
+ * composite bundle, the following steps are required to activate the
+ * constituents:
+ * <ol>
+ * <li>The composite framework start-level is set to the beginning start-level.</li>
+ * <li>The constituent bundles are started according to the start-level
+ * specification.
+ * <li>The {@link FrameworkEvent#STARTED} event is fired for the
+ * composite framework.</li>
+ * <li>The composite bundle state is set to {@link Bundle#ACTIVE}</li>
+ * <li>The bundle event of type {@link BundleEvent#STARTED} is fired for this
+ * composite.</li>
+ * </ol>
+ * @param options The options for starting this composite. See
+ * {@link #START_TRANSIENT} and {@link #START_ACTIVATION_POLICY}. The
+ * Framework must ignore unrecognized options.
+ * @throws BundleException If this composite could not be started.
+ * @throws IllegalStateException If this composite has been uninstalled.
+ * @throws SecurityException If the caller does not have the appropriate
+ * <code>AdminPermission[this,EXECUTE]</code>, and the Java Runtime
+ * Environment supports permissions.
+ */
+ public void start(int options) throws BundleException;
+
+ /**
+ * Stops this composite with no options.
+ *
+ * <p>
+ * This method performs the same function as calling <code>stop(0)</code>.
+ *
+ * @throws BundleException If an error occurred while stopping this composite
+ * @throws IllegalStateException If this composite has been uninstalled.
+ * @throws SecurityException If the caller does not have the appropriate
+ * <code>AdminPermission[this,EXECUTE]</code>, and the Java Runtime
+ * Environment supports permissions.
+ * @see #start(int)
+ */
+ public void stop() throws BundleException;
+
+ /**
+ * Stops this composite according to {@link Bundle#stop(int)}.
+ * When the composite bundle's state is set to {@link Bundle#STOPPING},
+ * the following steps are required to stop the constituents:
+ * <ol>
+ * <li>The composite framework start-level is set to the 0.</li>
+ * <li>The constituent bundles are stopped according to the start-level
+ * specification.</li>
+ * <li>The bundle event of type {@link BundleEvent#STARTED} is fired for the
+ * composite.</li>
+ * </ol>
+ * @param options The options for stopping this bundle. See
+ * {@link #STOP_TRANSIENT}. The Framework must ignore unrecognized
+ * options.
+ * @throws BundleException If an error occurred while stopping this composite
+ * @throws IllegalStateException If this composite has been uninstalled.
+ * @throws SecurityException If the caller does not have the appropriate
+ * <code>AdminPermission[this,EXECUTE]</code>, and the Java Runtime
+ * Environment supports permissions.
+ * @since 1.4
+ */
+ public void stop(int options) throws BundleException;
+
+ /**
+ * Uninstalls this composite according to {@link Bundle#uninstall()}.
+ * When the composite bundle is uninstalled the following steps are
+ * required:
+ * <ol>
+ * <li>After a composite's state is set to {@linkplain Bundle#INSTALLED}
+ * and before a composite's state is set to {@linkplain Bundle#UNINSTALLED},
+ * all the constituent bundles are uninstalled.</li>
+ * <li>When a composite's state is set to {@linkplain Bundle#UNINSTALLED},
+ * the composite system bundle context becomes invalid.
+ * </ol>
+ */
+ public void uninstall() throws BundleException;
+ /**
+ * This operation is not supported for composite bundles. A
+ * <code>BundleException</code> of type
+ * {@link BundleException#INVALID_OPERATION invalid operation} must be
+ * thrown.
+ */
+ public void update() throws BundleException;
+
+ /**
+ * This operation is not supported for composite bundles. A
+ * <code>BundleException</code> of type
+ * {@link BundleException#INVALID_OPERATION invalid operation} must be
+ * thrown.
+ */
+ public void update(InputStream input) throws BundleException;
+
+ /**
+ * Updates the meta-data for this composite from a <code>Map</code>.
+ *
+ * <p>
+ * The specified <code>Map</code> must not be <code>null</code>.
+ *
+ * <p>
+ * If this composite's state is <code>ACTIVE</code>, it must be stopped before
+ * the update and started after the update successfully completes.
+ *
+ * <p>
+ * If this composite has a sharing policy for packages, any packages that are
+ * imported by other bundles through the current sharing policy must remain exported
+ * for existing importers. A call <code>PackageAdmin.refreshPackages</code> method
+ * will force all constituent bundles for this composite to be refreshed, causing the
+ * new package sharing policy to be used for all constituent bundles.
+ * <p>
+ * The following steps are required to update a composite:
+ * <ol>
+ * <li>If this composite's state is <code>UNINSTALLED</code> then an
+ * <code>IllegalStateException</code> is thrown.
+ * <li>The component manifest <code>Map</code> is verified. If this fails,
+ * a {@linkplain BundleException} is thrown.
+ *
+ * <li>If this composite's state is <code>ACTIVE</code>, <code>STARTING</code>
+ * or <code>STOPPING</code>, this bundle is stopped as described in the
+ * <code>CompositeBundle.stop</code> method. If <code>CompositeBundle.stop</code>
+ * throws an exception, the exception is rethrown terminating the update.
+ *
+ * <li>The meta-data of this composite is updated from the <code>Map</code>.
+ *
+ * <li>This composite's state is set to <code>INSTALLED</code>.
+ *
+ * <li>If the updated version of this composite was successfully installed, a
+ * bundle event of type {@link BundleEvent#UPDATED} is fired.
+ *
+ * <li>If this composite's state was originally <code>ACTIVE</code>, the
+ * updated composite is started as described in the <code>CompositeBundle.start</code>
+ * method. If <code>CompositeBundle.start</code> throws an exception, a Framework
+ * event of type {@link FrameworkEvent#ERROR} is fired containing the
+ * exception.
+ * </ol>
+ *
+ * <b>Preconditions </b>
+ * <ul>
+ * <li><code>getState()</code> not in { <code>UNINSTALLED</code>
+ * }.
+ * </ul>
+ * <b>Postconditions, no exceptions thrown </b>
+ * <ul>
+ * <li><code>getState()</code> in { <code>INSTALLED</code>,
+ * <code>RESOLVED</code>, <code>ACTIVE</code> }.
+ * <li>This composite has been updated.
+ * </ul>
+ * <b>Postconditions, when an exception is thrown </b>
+ * <ul>
+ * <li><code>getState()</code> in { <code>INSTALLED</code>,
+ * <code>RESOLVED</code>, <code>ACTIVE</code> }.
+ * <li>Original composite is still used; no update occurred.
+ * </ul>
+ *
+ * @param compositeManifest The <code>Map</code> from which to read the new
+ * composite meta-data from. Must not be <code>null</code>.
+ * @throws BundleException If the the update fails.
+ * @throws IllegalStateException If this composite has been uninstalled.
+ * @throws SecurityException If the caller does not have
+ * <code>AllPermission</code>.
+ * @see #stop()
+ * @see #start()
+ */
+ public void update(Map<String, String> compositeManifest)
+ throws BundleException;
+
+ /**
+ * Composite bundles do not have class content. This method must
+ * throw a {@link ClassNotFoundException}
+ * @throws ClassNotFoundException Always thrown for composite bundles.
+ */
+ public Class< ? > loadClass(String name) throws ClassNotFoundException;
+ /**
+ * Composite bundles do not have content. This method must return
+ * <code>null</code>.
+ * @return A <code>null</code> value is always returned for composites.
+ */
+ public URL getResource(String name);
+ /**
+ * Composite bundles do not have content. This method must return
+ * <code>null</code>.
+ * @return A <code>null</code> value is always returned for composites.
+ */
+ public Enumeration<URL> getResources(String name) throws IOException;
+ /**
+ * Composite bundles do not have content. This method must return
+ * <code>null</code>.
+ * @return A <code>null</code> value is always returned for composites.
+ */
+ public URL getEntry(String path);
+ /**
+ * Composite bundles do not have content. This method must return
+ * <code>null</code>.
+ * @return A <code>null</code> value is always returned for composites.
+ */
+ public Enumeration<String> getEntryPaths(String path);
+ /**
+ * Composite bundles do not have content. This method must return
+ * <code>null</code>.
+ * @return A <code>null</code> value is always returned for composites.
+ */
+ public Enumeration<URL> findEntries(String path, String filePattern,
+ boolean recurse);
+}
Added: incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeConstants.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeConstants.java?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeConstants.java (added)
+++ incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/CompositeConstants.java Fri Apr 2 09:42:59 2010
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) OSGi Alliance (2009). All Rights Reserved.
+ *
+ * Licensed 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.osgi.service.composite;
+
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+
+
+/**
+ * Defines standard names for composite constants.
+ *
+ * @ThreadSafe
+ * @version $Revision: 8585 $
+ */
+public class CompositeConstants {
+ /**
+ * Private constructor to prevent objects of this type.
+ */
+ private CompositeConstants() {
+ // non-instantiable
+ }
+
+ /**
+ * Manifest header directive identifying whether a bundle is a composite.
+ * The default value is <code>false</code>.
+ *
+ * <p>
+ * The directive value is encoded in the Bundle-SymbolicName manifest header
+ * like:
+ *
+ * <pre>
+ * Bundle-SymbolicName: com.acme.composite.test; composite:=true
+ * </pre>
+ *
+ * <p>
+ * The attribute value may be retrieved from the <code>Dictionary</code>
+ * object returned by the <code>Bundle.getHeaders</code> method.
+ *
+ * <p>
+ * A valid manifest for a composite bundle must have this directive set
+ * to <code>true</code>. Any attempt to install a composite which does
+ * not have this directive set to <code>true</code> must result in a
+ * {@linkplain BundleException}.
+ *
+ * @see Constants#BUNDLE_SYMBOLICNAME
+ */
+ public final static String COMPOSITE_DIRECTIVE = "composite";
+
+ /**
+ * Composite manifest header (named "Composite-PackageImportPolicy")
+ * identifying a list of package constraints to import into the composite.
+ * Any exported package from a bundle installed in the parent framework which
+ * satisfies one of the specified package constraints is available to satisfy
+ * Import-Package constraints from constituent bundles.
+ * <p>
+ * This header uses the same syntax as the {@linkplain Constants#IMPORT_PACKAGE
+ * Import-Package} header.
+ */
+ public static final String COMPOSITE_PACKAGE_IMPORT_POLICY = "Composite-PackageImportPolicy";
+
+ /**
+ * Composite manifest header (named "Composite-PackageExportPolicy")
+ * identifying a list of package constraints to export out of a composite.
+ * Any exported package from a constituent bundle in the composite which
+ * satisfies one of the specified package constraints is available to satisfy
+ * Import-Package constraints from bundles installed in the parent framework.
+ * <p>
+ * This header uses the same syntax as the {@linkplain Constants#IMPORT_PACKAGE
+ * Import-Package} header.
+ */
+ public static final String COMPOSITE_PACKAGE_EXPORT_POLICY = "Composite-PackageExportPolicy";
+
+ /**
+ * Composite manifest header (named "Composite-BundleRequirePolicy")
+ * identifying a list of require bundle constraints to import into the composite.
+ * Any bundle installed in the parent framework which satisfies one of the
+ * specified require bundle constraints is available to satisfy Require-Bundle
+ * constraints from constituent bundles.
+ * <p>
+ * This header uses the same syntax as the {@linkplain Constants#REQUIRE_BUNDLE
+ * Require-Bundle} header.
+ */
+ public static final String COMPOSITE_BUNDLE_REQUIRE_POLICY = "Composite-BundleRequirePolicy";
+
+ /**
+ * Composite manifest header (named "Composite-ServiceImportPolicy")
+ * identifying a service filter that controls the services to import into the
+ * composite. See {@link Filter} for a description of the filter syntax. Any
+ * services registered by bundles installed in the parent framework that match
+ * the specified service filter is available to constituent bundles.
+ */
+ public static final String COMPOSITE_SERVICE_IMPORT_POLICY = "Composite-ServiceImportPolicy";
+
+ /**
+ * Composite manifest header (named "Composite-ServiceExportPolicy")
+ * identifying a service filter that controls the services to export out of the
+ * composite. See {@link Filter} for a description of the filter syntax. Any
+ * services registered by constituent bundles that match the specified service
+ * filter is available to bundles installed in the parent framework.
+ */
+ public static final String COMPOSITE_SERVICE_EXPORT_POLICY = "Composite-ServiceExportPolicy";
+
+ /**
+ * Manifest header directive identifying the symbolic name a sibling composite
+ * must have that allows capabilities exported from that composite to match
+ * an import sharing policy specified by {@link #COMPOSITE_PACKAGE_IMPORT_POLICY
+ * Composite-PackageImportPolicy} or {@link #COMPOSITE_SERVICE_IMPORT_POLICY
+ * Composite-ServiceImportPolicy}.
+ *
+ * <p>
+ * The directive value is encoded in the a manifest header like:
+ *
+ * <pre>
+ * Composite-PackageImportPolicy: org.example.pkg; composite-symbolic-name="org.example.composite"
+ * Composite-ServiceImportPolicy: "(attr=somevalue)"; composite-symbolic-name="org.example.composite"
+ * </pre>
+ *
+ * @see #COMPOSITE_PACKAGE_IMPORT_POLICY
+ * @see #COMPOSITE_SERVICE_IMPORT_POLICY
+ */
+ public static final String COMPOSITE_SYMBOLICNAME_DIRECTIVE = "composite-symbolic-name";
+
+ /**
+ * Manifest header directive identifying the version a sibling composite
+ * must have that allows capabilities exported from that composite to match
+ * an import sharing policy specified by {@link #COMPOSITE_PACKAGE_IMPORT_POLICY
+ * Composite-PackageImportPolicy} or {@link #COMPOSITE_SERVICE_IMPORT_POLICY
+ * Composite-ServiceImportPolicy}.
+ *
+ * <p>
+ * The directive value is encoded in the a manifest header like:
+ *
+ * <pre>
+ * Composite-PackageImportPolicy: org.example.pkg; composite-version="[1.0,1.1)"
+ * Composite-ServiceImportPolicy: "(attr=somevalue)"; composite-version="[1.0,1.1)"
+ * </pre>
+ *
+ * <p>
+ * In most cases a {@link #COMPOSITE_SYMBOLICNAME_DIRECTIVE composite-symbolic-name}
+ * directive should be specified along with the composite-version directive like:
+ *
+ * <pre>
+ * Composite-PackageImportPolicy: org.example.pkg;
+ * composite-symbolic-name="org.example.composite"; composite-version="[1.0,1.1)"
+ * Composite-ServiceImportPolicy: "(attr=somevalue)";
+ * composite-symbolic-name="org.example.composite"; composite-version="[1.0,1.1)"
+ * </pre>
+ *
+ * @see #COMPOSITE_PACKAGE_IMPORT_POLICY
+ * @see #COMPOSITE_SERVICE_IMPORT_POLICY
+ */
+ public static final String COMPOSITE_VERSION_DIRECTIVE = "composite-version";
+
+ /**
+ * A supported configuration parameter for a composite framework.
+ * @see Constants#FRAMEWORK_BEGINNING_STARTLEVEL
+ */
+ public final static String COMPOSITE_FRAMEWORK_BEGINNING_STARTLEVEL = Constants.FRAMEWORK_BEGINNING_STARTLEVEL;
+}
Added: incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/package.html
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/package.html?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/package.html (added)
+++ incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/package.html Fri Apr 2 09:42:59 2010
@@ -0,0 +1,11 @@
+<!-- $Revision: 8119 $ -->
+<BODY>
+<p>Composite Admin service Package Version 1.0.
+<p>Bundles wishing to use this package must list the package
+in the Import-Package header of the bundle's manifest.
+For example:
+<pre>
+Import-Package: org.osgi.service.composite;version="[1.0,2.0)"
+</pre>
+</BODY>
+
Added: incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/packageinfo
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/packageinfo?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/packageinfo (added)
+++ incubator/aries/trunk/subsystem/org.osgi.service.composite/src/main/java/org/osgi/service/composite/packageinfo Fri Apr 2 09:42:59 2010
@@ -0,0 +1 @@
+version 1.0
Modified: incubator/aries/trunk/subsystem/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/pom.xml?rev=930209&r1=930208&r2=930209&view=diff
==============================================================================
--- incubator/aries/trunk/subsystem/pom.xml (original)
+++ incubator/aries/trunk/subsystem/pom.xml Fri Apr 2 09:42:59 2010
@@ -46,15 +46,33 @@
<version>${version}</version>
</dependency>
<dependency>
+ <groupId>org.apache.aries.subsystem</groupId>
+ <artifactId>org.apache.aries.subsystem.core</artifactId>
+ <version>${version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.aries.subsystem</groupId>
+ <artifactId>org.osgi.service.composite</artifactId>
+ <version>${version}</version>
+ </dependency>
+ <dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
<version>4.2.0</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.utils</artifactId>
+ <version>1.0.0</version>
+ </dependency>
</dependencies>
</dependencyManagement>
<modules>
- <module>subsystem-api</module>
+ <module>subsystem-api</module>
+ <module>org.osgi.service.composite</module>
+ <module>subsystem-core</module>
+ <module>subsystem-install</module>
</modules>
</project>
Added: incubator/aries/trunk/subsystem/subsystem-core/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/subsystem-core/pom.xml?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/subsystem-core/pom.xml (added)
+++ incubator/aries/trunk/subsystem/subsystem-core/pom.xml Fri Apr 2 09:42:59 2010
@@ -0,0 +1,65 @@
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.aries.subsystem</groupId>
+ <artifactId>subsystem</artifactId>
+ <version>0.1-incubating-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.apache.aries.subsystem.core</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Aries Subsystem Core</name>
+ <description>
+ Subsystems API.
+ </description>
+
+ <properties>
+ <aries.osgi.activator>
+ org.apache.aries.subsystem.core.internal.Activator
+ </aries.osgi.activator>
+ <aries.osgi.private.pkg>
+ org.apache.aries.subsystem.core.internal,
+ org.apache.felix.utils.manifest
+ </aries.osgi.private.pkg>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.aries.subsystem</groupId>
+ <artifactId>org.apache.aries.subsystem.api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.aries.subsystem</groupId>
+ <artifactId>org.osgi.service.composite</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.utils</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
Added: incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java (added)
+++ incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java Fri Apr 2 09:42:59 2010
@@ -0,0 +1,109 @@
+/*
+ * Licensed 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.aries.subsystem.core.internal;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.aries.subsystem.SubsystemAdmin;
+import org.apache.aries.subsystem.SubsystemConstants;
+import org.apache.aries.subsystem.spi.ResourceProcessor;
+import org.apache.aries.subsystem.spi.ResourceResolver;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * The bundle activator for the this bundle.
+ * When the bundle is starting, this activator will create
+ * and register the SubsystemAdmin service.
+ */
+public class Activator implements BundleActivator {
+
+ private BundleContext context;
+ private List<ServiceRegistration> registrations = new ArrayList<ServiceRegistration>();
+
+ public void start(BundleContext context) throws Exception {
+ this.context = context;
+ register(SubsystemAdmin.class, new SubsystemAdminFactory(), null);
+ register(ResourceResolver.class,
+ new NoOpResolver(),
+ DictionaryBuilder.build(Constants.SERVICE_RANKING, Integer.MIN_VALUE));
+ register(ResourceProcessor.class,
+ new BundleResourceProcessor(),
+ DictionaryBuilder.build(SubsystemConstants.SERVICE_RESOURCE_TYPE, SubsystemConstants.RESOURCE_TYPE_BUNDLE));
+ register(ResourceProcessor.class,
+ new SubsystemResourceProcessor(),
+ DictionaryBuilder.build(SubsystemConstants.SERVICE_RESOURCE_TYPE, SubsystemConstants.RESOURCE_TYPE_SUBSYSTEM));
+ }
+
+ protected <T> void register(Class<T> clazz, T service, Dictionary props) {
+ registrations.add(context.registerService(clazz.getName(), service, props));
+ }
+
+ protected <T> void register(Class<T> clazz, ServiceFactory factory, Dictionary props) {
+ registrations.add(context.registerService(clazz.getName(), factory, props));
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ for (ServiceRegistration r : registrations) {
+ try {
+ r.unregister();
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ }
+
+
+ public static class SubsystemAdminFactory implements ServiceFactory {
+
+ private final Map<BundleContext, SubsystemAdminImpl> admins = new HashMap<BundleContext, SubsystemAdminImpl>();
+ private final Map<SubsystemAdminImpl, Long> references = new HashMap<SubsystemAdminImpl, Long>();
+
+ public synchronized Object getService(Bundle bundle, ServiceRegistration registration) {
+ BundleContext systemBundleContext = bundle.getBundleContext().getBundle(0).getBundleContext();
+ SubsystemAdminImpl admin = admins.get(systemBundleContext);
+ long ref = 0;
+ if (admin == null) {
+ admin = new SubsystemAdminImpl(systemBundleContext);
+ admins.put(systemBundleContext, admin);
+ } else {
+ ref = references.get(admin);
+ }
+ references.put(admin, ref + 1);
+ return admin;
+ }
+
+ public synchronized void ungetService(Bundle bundle, ServiceRegistration registration, Object service) {
+ SubsystemAdminImpl admin = (SubsystemAdminImpl) service;
+ long ref = references.get(admin) - 1;
+ if (ref == 0) {
+ admin.dispose();
+ admins.remove(admin.context);
+ references.remove(admin);
+ } else {
+ references.put(admin, ref);
+ }
+ }
+
+ }
+
+}
Added: incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceProcessor.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceProcessor.java?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceProcessor.java (added)
+++ incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceProcessor.java Fri Apr 2 09:42:59 2010
@@ -0,0 +1,74 @@
+/*
+ * Licensed 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.aries.subsystem.core.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.aries.subsystem.SubsystemException;
+import org.apache.aries.subsystem.spi.Resource;
+import org.apache.aries.subsystem.spi.ResourceProcessor;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+
+public class BundleResourceProcessor implements ResourceProcessor {
+
+ public Session createSession(BundleContext context) {
+ return new BundleSession(context);
+ }
+
+ public static class BundleSession implements Session {
+
+ private final BundleContext context;
+ private final List<Bundle> installed = new ArrayList<Bundle>();
+
+ public BundleSession(BundleContext context) {
+ this.context = context;
+ }
+
+ public void process(Resource resource) throws SubsystemException {
+ try {
+ Bundle bundle = context.installBundle(resource.getLocation(), resource.open());
+ installed.add(bundle);
+ } catch (SubsystemException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SubsystemException("Unable to process bundle resource", e);
+ }
+ }
+
+ public void dropped(Resource resource) throws SubsystemException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void prepare() throws SubsystemException {
+ }
+
+ public void commit() {
+ installed.clear();
+ }
+
+ public void rollback() {
+ for (Bundle bundle : installed) {
+ try {
+ bundle.uninstall();
+ } catch (Exception e) {
+ // Ignore
+ }
+ }
+ }
+ }
+
+}
Added: incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/DictionaryBuilder.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/DictionaryBuilder.java?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/DictionaryBuilder.java (added)
+++ incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/DictionaryBuilder.java Fri Apr 2 09:42:59 2010
@@ -0,0 +1,47 @@
+/*
+ * Licensed 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.aries.subsystem.core.internal;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+public class DictionaryBuilder<K,V> {
+
+ public static <K,V> Dictionary<K,V> build(K k, V v) {
+ return new DictionaryBuilder<K,V>().p(k, v).get();
+ }
+
+ public static <K,V> Dictionary<K,V> build(K k1, V v1, K k2, V v2) {
+ return new DictionaryBuilder<K,V>().p(k1, v1).p(k2, v2).get();
+ }
+
+ public static <K,V> Dictionary<K,V> build(K k1, V v1, K k2, V v2, K k3, V v3) {
+ return new DictionaryBuilder<K,V>().p(k1, v1).p(k2, v2).p(k3, v3).get();
+ }
+
+ private Dictionary<K,V> dict;
+
+ public DictionaryBuilder() {
+ dict = new Hashtable<K,V>();
+ }
+
+ DictionaryBuilder<K,V> p(K k, V v) {
+ dict.put(k, v);
+ return this;
+ }
+
+ Dictionary<K,V> get() {
+ return dict;
+ }
+}
Added: incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/FileUtils.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/FileUtils.java?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/FileUtils.java (added)
+++ incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/FileUtils.java Fri Apr 2 09:42:59 2010
@@ -0,0 +1,93 @@
+/*
+ * Licensed 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.aries.subsystem.core.internal;
+
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+public class FileUtils {
+
+ private FileUtils() {
+ }
+
+ /**
+ * Build a directory path - creating directories if necessary
+ *
+ * @param file
+ * @return true if the directory exists, or making it was successful
+ * @throws java.io.IOException
+ */
+ public static void mkdirs(File file) throws IOException {
+ if (!file.isDirectory() && !file.mkdirs()) {
+ throw new IOException("Could not create directory: " + file);
+ }
+ }
+
+ /**
+ * Unpack an archive from an input stream
+ *
+ * @param is
+ * @param targetDir
+ * @throws IOException
+ */
+ public static void unpackArchive(InputStream is, File targetDir) throws IOException {
+ mkdirs(targetDir);
+ byte[] buf = new byte[1024];
+ ZipInputStream zis = new ZipInputStream(is);
+ try {
+ ZipEntry entry = zis.getNextEntry();
+ while (entry != null) {
+ File file = new File(targetDir, entry.getName());
+ // Take the sledgehammer approach to creating directories
+ // to work around ZIP's that incorrectly miss directories
+ mkdirs(file.getParentFile());
+ if (!entry.isDirectory()) {
+ FileOutputStream fos = new FileOutputStream(file);
+ try {
+ int n;
+ while ((n = zis.read(buf, 0, 1024)) > -1) {
+ fos.write(buf, 0, n);
+ }
+ } finally {
+ closeQuietly(fos);
+ }
+ zis.closeEntry();
+ entry = zis.getNextEntry();
+ } else {
+ mkdirs(file);
+ }
+ }//while
+ } finally {
+ closeQuietly(zis, is);
+ }
+ }
+
+ public static void closeQuietly(Closeable... closeables) {
+ for (Closeable c : closeables) {
+ try {
+ if (c != null) {
+ c.close();
+ }
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ }
+
+}
Added: incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/NoOpResolver.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/NoOpResolver.java?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/NoOpResolver.java (added)
+++ incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/NoOpResolver.java Fri Apr 2 09:42:59 2010
@@ -0,0 +1,55 @@
+/*
+ * Licensed 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.aries.subsystem.core.internal;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.aries.subsystem.SubsystemConstants;
+import org.apache.aries.subsystem.SubsystemException;
+import org.apache.aries.subsystem.spi.Resource;
+import org.apache.aries.subsystem.spi.ResourceResolver;
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.manifest.Parser;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+
+public class NoOpResolver implements ResourceResolver {
+
+ public Resource find(String resource) throws SubsystemException {
+ Clause[] clauses = Parser.parseHeader(resource);
+ if (clauses.length != 1) {
+ throw new SubsystemException("Unsupported resource: " + resource);
+ }
+
+ String bsn = clauses[0].getName();
+ String ver = clauses[0].getAttribute(Constants.VERSION_ATTRIBUTE);
+ String typ = clauses[0].getAttribute(SubsystemConstants.RESOURCE_TYPE_ATTRIBUTE);
+ String loc = clauses[0].getAttribute(SubsystemConstants.RESOURCE_LOCATION_ATTRIBUTE);
+ if (loc == null) {
+ throw new SubsystemException("Mandatory location missing on resource: " + resource);
+ }
+ return new ResourceImpl(
+ bsn,
+ ver != null ? new Version(ver) : Version.emptyVersion,
+ typ != null ? typ : SubsystemConstants.RESOURCE_TYPE_BUNDLE,
+ loc
+ );
+ }
+
+ public List<Resource> resolve(List<Resource> subsystemContent, List<Resource> subsystemResources) throws SubsystemException {
+ return Collections.emptyList();
+ }
+
+}
Added: incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceImpl.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceImpl.java?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceImpl.java (added)
+++ incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceImpl.java Fri Apr 2 09:42:59 2010
@@ -0,0 +1,57 @@
+/*
+ * Licensed 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.aries.subsystem.core.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+import org.apache.aries.subsystem.spi.Resource;
+import org.osgi.framework.Version;
+
+public class ResourceImpl implements Resource {
+
+ private final String symbolicName;
+ private final Version version;
+ private final String type;
+ private final String location;
+
+ public ResourceImpl(String symbolicName, Version version, String type, String location) {
+ this.symbolicName = symbolicName;
+ this.version = version;
+ this.type = type;
+ this.location = location;
+ }
+
+ public String getSymbolicName() {
+ return symbolicName;
+ }
+
+ public Version getVersion() {
+ return version;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public String getLocation() {
+ return location;
+ }
+
+ public InputStream open() throws IOException {
+ return new URL(location).openStream();
+ }
+
+}
Added: incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemAdminImpl.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemAdminImpl.java?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemAdminImpl.java (added)
+++ incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemAdminImpl.java Fri Apr 2 09:42:59 2010
@@ -0,0 +1,204 @@
+/*
+ * Licensed 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.aries.subsystem.core.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.Semaphore;
+
+import org.apache.aries.subsystem.Subsystem;
+import org.apache.aries.subsystem.SubsystemAdmin;
+import org.apache.aries.subsystem.SubsystemConstants;
+import org.apache.aries.subsystem.SubsystemException;
+import org.apache.aries.subsystem.spi.Resource;
+import org.apache.aries.subsystem.spi.ResourceResolver;
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.manifest.Parser;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.SynchronousBundleListener;
+import org.osgi.framework.Version;
+import org.osgi.service.composite.CompositeAdmin;
+import org.osgi.service.composite.CompositeBundle;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class SubsystemAdminImpl implements SubsystemAdmin {
+
+ private static final Version SUBSYSTEM_MANIFEST_VERSION = new Version("1.0");
+
+ final Semaphore lock = new Semaphore(1);
+ final BundleContext context;
+ final Map<Long, Subsystem> subsystems = new HashMap<Long, Subsystem>();
+ final ServiceTracker compositeAdminTracker;
+ final ServiceTracker resourceResolverTracker;
+
+ public SubsystemAdminImpl(BundleContext context) {
+ this.context = context;
+ this.compositeAdminTracker = new ServiceTracker(context, CompositeAdmin.class.getName(), null);
+ this.compositeAdminTracker.open();
+ this.resourceResolverTracker = new ServiceTracker(context, ResourceResolver.class.getName(), null);
+ this.resourceResolverTracker.open();
+ // Track subsystems
+ synchronized (subsystems) {
+ this.context.addBundleListener(new SynchronousBundleListener() {
+ public void bundleChanged(BundleEvent event) {
+ SubsystemAdminImpl.this.bundleChanged(event);
+ }
+ });
+ loadSubsystems();
+ }
+ }
+
+ public void dispose() {
+ compositeAdminTracker.close();
+ resourceResolverTracker.close();
+ }
+
+ public void bundleChanged(BundleEvent event) {
+ synchronized (subsystems) {
+ if (event.getType() == BundleEvent.UPDATED || event.getType() == BundleEvent.UNINSTALLED) {
+ subsystems.remove(event.getBundle().getBundleId());
+ }
+ if (event.getType() == BundleEvent.INSTALLED || event.getType() == BundleEvent.UPDATED) {
+ Subsystem s = isSubsystem(event.getBundle());
+ if (s != null) {
+ subsystems.put(s.getSubsystemId(), s);
+ }
+ }
+ }
+ }
+
+ protected void loadSubsystems() {
+ synchronized (subsystems) {
+ subsystems.clear();
+ for (Bundle bundle : context.getBundles()) {
+ Subsystem s = isSubsystem(bundle);
+ if (s != null) {
+ subsystems.put(s.getSubsystemId(), s);
+ }
+ }
+ }
+ }
+
+ protected Subsystem isSubsystem(Bundle bundle) {
+ if (bundle instanceof CompositeBundle) {
+ String bsn = (String) bundle.getHeaders().get(Constants.BUNDLE_SYMBOLICNAME);
+ Clause[] bsnClauses = Parser.parseHeader(bsn);
+ if ("true".equals(bsnClauses[0].getDirective(SubsystemConstants.SUBSYSTEM_DIRECTIVE))) {
+ return new SubsystemImpl(this, (CompositeBundle) bundle);
+ }
+ }
+ return null;
+ }
+
+ public Subsystem getSubsystem(String scope) {
+ synchronized (subsystems) {
+ for (Subsystem s : subsystems.values()) {
+ if (s.getScope().equals(scope)) {
+ return s;
+ }
+ }
+ return null;
+ }
+ }
+
+ public Map<Long, Subsystem> getSubsystems() {
+ synchronized (subsystems) {
+ return Collections.unmodifiableMap(subsystems);
+ }
+ }
+
+ public Subsystem install(String url) {
+ return install(url, null);
+ }
+
+ public synchronized Subsystem install(String url, final InputStream is) throws SubsystemException {
+ Resource subsystemResource = new ResourceImpl(null, null, SubsystemConstants.RESOURCE_TYPE_SUBSYSTEM, url) {
+ @Override
+ public InputStream open() throws IOException {
+ if (is != null) {
+ return is;
+ }
+ return super.open();
+ }
+ };
+ SubsystemResourceProcessor processor = new SubsystemResourceProcessor();
+ SubsystemResourceProcessor.SubsystemSession session = processor.createSession(context);
+ boolean success = false;
+ try {
+ session.process(subsystemResource);
+ session.prepare();
+ session.commit();
+ success = true;
+ } finally {
+ if (!success) {
+ session.rollback();
+ }
+ }
+ for (Subsystem ss : getSubsystems().values()) {
+ if (url.equals(ss.getLocation())) {
+ return ss;
+ }
+ }
+ throw new IllegalStateException();
+ }
+
+ public void update(Subsystem subsystem) {
+ update(subsystem, null);
+ }
+
+ public synchronized void update(Subsystem subsystem, InputStream content) {
+ // TODO: update
+ }
+
+ public synchronized void uninstall(Subsystem ss) {
+ if (!(ss instanceof SubsystemImpl)) {
+ throw new IllegalArgumentException("The given subsystem is not managed by the SubsystemAdmin instance");
+ }
+ SubsystemImpl subsystem = (SubsystemImpl) ss;
+ try {
+ subsystem.composite.uninstall();
+ this.subsystems.remove(subsystem.id);
+ } catch (BundleException e) {
+ // TODO: Rollback
+ throw new SubsystemException("Error while uninstalling the subsystem", e);
+ }
+ }
+
+ public void uninstallForced(Subsystem ss) {
+ if (!(ss instanceof SubsystemImpl)) {
+ throw new IllegalArgumentException("The given subsystem is not managed by the SubsystemAdmin instance");
+ }
+ SubsystemImpl subsystem = (SubsystemImpl) ss;
+ try {
+ subsystem.composite.uninstall();
+ } catch (BundleException e) {
+ // Ignore
+ } finally {
+ this.subsystems.remove(subsystem.id);
+ }
+ }
+
+ public boolean cancel() {
+ // TODO
+ return false;
+ }
+
+}
Added: incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemImpl.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemImpl.java?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemImpl.java (added)
+++ incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemImpl.java Fri Apr 2 09:42:59 2010
@@ -0,0 +1,114 @@
+/*
+ * Licensed 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.aries.subsystem.core.internal;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.aries.subsystem.Subsystem;
+import org.apache.aries.subsystem.SubsystemException;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Version;
+import org.osgi.service.composite.CompositeBundle;
+
+public class SubsystemImpl implements Subsystem {
+
+ final long id;
+ final SubsystemAdminImpl admin;
+ final CompositeBundle composite;
+
+ public SubsystemImpl(SubsystemAdminImpl admin, CompositeBundle composite) {
+ this.admin = admin;
+ this.composite = composite;
+ this.id = composite.getBundleId();
+ }
+
+ public State getState() {
+ switch (composite.getState())
+ {
+ case Bundle.UNINSTALLED:
+ return State.UNINSTALLED;
+ case Bundle.INSTALLED:
+ return State.INSTALLED;
+ case Bundle.RESOLVED:
+ return State.RESOLVED;
+ case Bundle.STARTING:
+ return State.STARTING;
+ case Bundle.ACTIVE:
+ return State.ACTIVE;
+ case Bundle.STOPPING:
+ return State.STOPPING;
+ }
+ throw new SubsystemException("Unable to retrieve subsystem state");
+ }
+
+ public void start() throws SubsystemException {
+ try {
+ composite.start();
+ } catch (BundleException e) {
+ throw new SubsystemException("Unable to start subsystem", e);
+ }
+ }
+
+ public void stop() throws SubsystemException {
+ try {
+ composite.stop();
+ } catch (BundleException e) {
+ throw new SubsystemException("Unable to stop subsystem", e);
+ }
+ }
+
+ public long getSubsystemId() {
+ return composite.getBundleId();
+ }
+
+ public String getLocation() {
+ return composite.getLocation();
+ }
+
+ public String getSymbolicName() {
+ return composite.getSymbolicName();
+ }
+
+ public Version getVersion() {
+ return composite.getVersion();
+ }
+
+ public String getScope() {
+ return getSymbolicName() + "_" + getVersion().toString();
+ }
+
+ public Map<String, String> getHeaders() {
+ return getHeaders(null);
+ }
+
+ public Map<String, String> getHeaders(String locale) {
+ // TODO: retrieve headers
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public Collection<Bundle> getConstituents() {
+ List<Bundle> list = new ArrayList<Bundle>();
+ Bundle[] bundles = composite.getSystemBundleContext().getBundles();
+ for (Bundle bundle : bundles) {
+ if (bundle.getBundleId() != 0) {
+ list.add(bundle);
+ }
+ }
+ return list;
+ }
+}
\ No newline at end of file
Added: incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceProcessor.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceProcessor.java?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceProcessor.java (added)
+++ incubator/aries/trunk/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceProcessor.java Fri Apr 2 09:42:59 2010
@@ -0,0 +1,289 @@
+/*
+ * Licensed 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.aries.subsystem.core.internal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+import org.apache.aries.subsystem.Subsystem;
+import org.apache.aries.subsystem.SubsystemAdmin;
+import org.apache.aries.subsystem.SubsystemConstants;
+import org.apache.aries.subsystem.SubsystemException;
+import org.apache.aries.subsystem.spi.Resource;
+import org.apache.aries.subsystem.spi.ResourceProcessor;
+import org.apache.aries.subsystem.spi.ResourceResolver;
+import org.apache.felix.utils.manifest.Clause;
+import org.apache.felix.utils.manifest.Parser;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.Version;
+import org.osgi.service.composite.CompositeAdmin;
+import org.osgi.service.composite.CompositeBundle;
+import org.osgi.util.tracker.ServiceTracker;
+
+import static org.apache.aries.subsystem.core.internal.FileUtils.closeQuietly;
+
+import static org.osgi.framework.Constants.*;
+import static org.osgi.service.composite.CompositeConstants.*;
+import static org.apache.aries.subsystem.SubsystemConstants.*;
+
+public class SubsystemResourceProcessor implements ResourceProcessor {
+
+ private static final Version SUBSYSTEM_MANIFEST_VERSION = new Version("1.0");
+
+ public SubsystemSession createSession(BundleContext context) {
+ return new SubsystemSession(context);
+ }
+
+ public static class SubsystemSession implements Session {
+
+ private static final long TIMEOUT = 30000;
+
+ private final BundleContext context;
+ private final Map<Resource, CompositeBundle> installed = new HashMap<Resource, CompositeBundle>();
+ private final Map<Resource, CompositeBundle> removed = new HashMap<Resource, CompositeBundle>();
+ private final Map<String, ServiceTracker> trackers = new HashMap<String, ServiceTracker>();
+ private final Map<BundleContext, Map<String, Session>> sessions = new HashMap<BundleContext, Map<String, Session>>();
+
+
+ public SubsystemSession(BundleContext context) {
+ this.context = context;
+ }
+
+ public void process(Resource res) throws SubsystemException {
+ CompositeBundle composite = null;
+ boolean success = false;
+ try {
+
+ CompositeAdmin admin = getService(CompositeAdmin.class);
+ ResourceResolver resolver = getService(ResourceResolver.class);
+
+ // Unpack the subsystem archive into a temporary directory
+ File dir = File.createTempFile("subsystem", "", null);
+ if (dir == null || !dir.delete() || !dir.mkdir()) {
+ throw new Exception("Unable to create temporary dir");
+ }
+ FileUtils.unpackArchive(res.open(), dir);
+
+ Manifest manifest = new Manifest();
+ InputStream mis = new FileInputStream(new File(dir, JarFile.MANIFEST_NAME));
+ try {
+ manifest.read(mis);
+ } finally {
+ closeQuietly(mis);
+ }
+
+ List<Resource> resource = new ArrayList<Resource>();
+ String resourceHeader = manifest.getMainAttributes().getValue(SUBSYSTEM_RESOURCES);
+ Clause[] resourceClauses = Parser.parseHeader(resourceHeader);
+ for (Clause c : resourceClauses) {
+ Resource r = resolver.find(c.toString());
+ resource.add(r);
+ }
+
+ List<Resource> content = new ArrayList<Resource>();
+ String contentHeader = manifest.getMainAttributes().getValue(SUBSYSTEM_CONTENT);
+ Clause[] contentClauses = Parser.parseHeader(contentHeader);
+ for (Clause c : contentClauses) {
+ Resource r = resolver.find(c.toString());
+ content.add(r);
+ }
+
+ // TODO: convert resources before calling the resolver?
+
+ List<Resource> additional = resolver.resolve(content, resource);
+
+ // Check subsystem manifest required headers
+ String mfv = manifest.getMainAttributes().getValue(SUBSYSTEM_MANIFESTVERSION);
+ if (mfv == null || mfv.length() == 0) {
+ throw new SubsystemException("Invalid subsystem manifest version: " + mfv);
+ }
+ try {
+ Version v = Version.parseVersion(mfv);
+ if (!SUBSYSTEM_MANIFEST_VERSION.equals(v)) {
+ throw new SubsystemException("Unsupported subsystem manifest version: " + mfv);
+ }
+ } catch (IllegalArgumentException e) {
+ throw new SubsystemException("Invalid subsystem manifest version: " + mfv, e);
+ }
+ String ssn = manifest.getMainAttributes().getValue(SUBSYSTEM_SYMBOLICNAME);
+ if (ssn == null || ssn.length() == 0) {
+ throw new SubsystemException("Invalid subsystem symbolic name: " + ssn);
+ }
+ // TODO: check attributes / directives on the subsystem symbolic name ?
+ String sv = manifest.getMainAttributes().getValue(SUBSYSTEM_VERSION);
+ if (sv == null || sv.length() == 0) {
+ throw new SubsystemException("Invalid subsystem version: " + sv);
+ }
+ try {
+ new Version(sv);
+ } catch (IllegalArgumentException e) {
+ throw new SubsystemException("Invalid subsystem version: " + sv, e);
+ }
+ // Grab all headers
+ Map<String, String> headers = new HashMap<String, String>();
+ Iterator it = manifest.getMainAttributes().entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry e = (Map.Entry) it.next();
+ String name = e.getKey().toString();
+ String value = e.getValue().toString();
+ headers.put(name, value);
+ }
+ // Create the required composite headers
+ headers.put(BUNDLE_SYMBOLICNAME, ssn + ";" + COMPOSITE_DIRECTIVE + ":=true;" + SUBSYSTEM_DIRECTIVE + ":=true");
+ headers.put(BUNDLE_VERSION, sv);
+ // TODO: compute other composite manifest entries
+ // TODO: compute list of bundles
+
+ composite = admin.installCompositeBundle(
+ res.getLocation(),
+ headers,
+ Collections.<String, String>emptyMap());
+ installed.put(res, composite);
+ composite.getSystemBundleContext().registerService(SubsystemAdmin.class.getName(), new Activator.SubsystemAdminFactory(), null);
+
+ for (Resource r : additional) {
+ getSession(context, r.getType()).process(r);
+ }
+ for (Resource r : content) {
+ getSession(composite.getSystemBundleContext(), r.getType()).process(r);
+ }
+
+ success = true;
+
+ } catch (SubsystemException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SubsystemException("Unable to install subsystem", e);
+ } finally {
+ if (!success && composite != null) {
+ try {
+ composite.uninstall();
+ } catch (Exception e) {
+ // TODO: log error
+ }
+ }
+ }
+ }
+
+ public void dropped(Resource resource) throws SubsystemException {
+ // TODO: find corresponding subsystem
+ }
+
+ protected Subsystem findSubsystem(Resource resource) {
+ // TODO
+ return null;
+ }
+
+ public void prepare() throws SubsystemException {
+ for (Map<String, Session> sm : sessions.values()) {
+ for (Session s : sm.values()) {
+ s.prepare();
+ }
+ }
+ }
+
+ public void commit() {
+ for (Map<String, Session> sm : sessions.values()) {
+ for (Session s : sm.values()) {
+ s.commit();
+ }
+ }
+ installed.clear();
+ closeTrackers();
+ }
+
+ public void rollback() {
+ for (Map<String, Session> sm : sessions.values()) {
+ for (Session s : sm.values()) {
+ s.rollback();
+ }
+ }
+ for (CompositeBundle c : installed.values()) {
+ try {
+ c.uninstall();
+ } catch (BundleException e) {
+ // Ignore
+ }
+ }
+ closeTrackers();
+ }
+
+ protected Session getSession(BundleContext context, String type) throws InvalidSyntaxException, InterruptedException {
+ Map<String, Session> sm = this.sessions.get(context);
+ if (sm == null) {
+ sm = new HashMap<String, Session>();
+ this.sessions.put(context, sm);
+ }
+ Session session = sm.get(type);
+ if (session == null) {
+ session = getProcessor(type).createSession(context);
+ sm.put(type, session);
+ }
+ return session;
+ }
+
+ protected ResourceProcessor getProcessor(String type) throws InvalidSyntaxException, InterruptedException {
+ return getService(ResourceProcessor.class, SubsystemConstants.SERVICE_RESOURCE_TYPE + "=" + type);
+ }
+
+ protected <T> T getService(Class<T> clazz) throws InvalidSyntaxException, InterruptedException {
+ return getService(clazz, null);
+ }
+
+ protected <T> T getService(Class<T> clazz, String filter) throws InvalidSyntaxException, InterruptedException {
+ Filter flt;
+ if (filter != null) {
+ if (!filter.startsWith("(")) {
+ flt = context.createFilter("(&(" + Constants.OBJECTCLASS + "=" + clazz.getName() + ")(" + filter + "))");
+ } else {
+ flt = context.createFilter("(&(" + Constants.OBJECTCLASS + "=" + clazz.getName() + ")" + filter + ")");
+ }
+ } else {
+ flt = context.createFilter("(" + Constants.OBJECTCLASS + "=" + clazz.getName() + ")");
+ }
+ ServiceTracker tracker = trackers.get(flt.toString());
+ if (tracker == null) {
+ tracker = new ServiceTracker(context, flt, null);
+ tracker.open();
+ trackers.put(flt.toString(), tracker);
+ }
+ T t = (T) tracker.waitForService(TIMEOUT);
+ if (t == null) {
+ throw new SubsystemException("No service available: " + flt);
+ }
+ return t;
+ }
+
+ private void closeTrackers() {
+ for (ServiceTracker t : trackers.values()) {
+ t.close();
+ }
+ trackers.clear();
+ }
+ }
+
+}
\ No newline at end of file
Added: incubator/aries/trunk/subsystem/subsystem-install/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/subsystem/subsystem-install/pom.xml?rev=930209&view=auto
==============================================================================
--- incubator/aries/trunk/subsystem/subsystem-install/pom.xml (added)
+++ incubator/aries/trunk/subsystem/subsystem-install/pom.xml Fri Apr 2 09:42:59 2010
@@ -0,0 +1,62 @@
+<!--
+ 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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.aries.subsystem</groupId>
+ <artifactId>subsystem</artifactId>
+ <version>0.1-incubating-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>org.apache.aries.subsystem.install</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Aries Subsystem Installer</name>
+ <description>
+ Subsystems Installer.
+ </description>
+
+ <properties>
+ <aries.osgi.private.pkg>
+ org.apache.aries.subsystem.install.internal
+ </aries.osgi.private.pkg>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.aries.subsystem</groupId>
+ <artifactId>org.apache.aries.subsystem.api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.aries.subsystem</groupId>
+ <artifactId>org.osgi.service.composite</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.fileinstall</artifactId>
+ <version>2.0.8</version>
+ </dependency>
+ </dependencies>
+
+</project>