You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@aries.apache.org by Lin Sun <li...@gmail.com> on 2010/04/06 04:22:01 UTC

Re: 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/jav

Hi Guillaume,

You are so fast! :)

I have some initial Comments/Questions-
1. ArtifactInstaller... what is the purpose of SubsystemInstaller?  Is
it intended to work only with felix?

2. for BundleResourceProcessor.rollback() or
SubsystemResourceProcessor.rollback(), should we clear the installed
list at the end?

3. SubsystemAdminImpl.bundleChanged... for BundleEvent.UPDATED, does
this refer to the case where a bundle was a composite without
subsystem directive but later got updated to be a composite with
subsystem directive?

Thanks

Lin
On Fri, Apr 2, 2010 at 5:43 AM,  <gn...@apache.org> wrote:
> 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 &#x007B; <code>INSTALLED</code>,
> +        * <code>RESOLVED</code> &#x007D;.</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 &#x007B; <code>UNINSTALLED</code>
> +        * &#x007D;.
> +        * </ul>
> +        * <b>Postconditions, no exceptions thrown </b>
> +        * <ul>
> +        * <li><code>getState()</code> in &#x007B; <code>INSTALLED</code>,
> +        * <code>RESOLVED</code>, <code>ACTIVE</code> &#x007D;.
> +        * <li>This composite has been updated.
> +        * </ul>
> +        * <b>Postconditions, when an exception is thrown </b>
> +        * <ul>
> +        * <li><code>getState()</code> in &#x007B; <code>INSTALLED</code>,
> +        * <code>RESOLVED</code>, <code>ACTIVE</code> &#x007D;.
> +        * <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 &quot;Composite-PackageImportPolicy&quot;)
> +        * 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 &quot;Composite-PackageExportPolicy&quot;)
> +        * 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 &quot;Composite-BundleRequirePolicy&quot;)
> +        * 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 &quot;Composite-ServiceImportPolicy&quot;)
> +        * 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 &quot;Composite-ServiceExportPolicy&quot;)
> +        * 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=&quot;org.example.composite&quot;
> +        *     Composite-ServiceImportPolicy: &quot;(attr=somevalue)&quot;; composite-symbolic-name=&quot;org.example.composite&quot;
> +        * </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=&quot;[1.0,1.1)&quot;
> +        *     Composite-ServiceImportPolicy: &quot;(attr=somevalue)&quot;; composite-version=&quot;[1.0,1.1)&quot;
> +        * </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=&quot;org.example.composite&quot;; composite-version=&quot;[1.0,1.1)&quot;
> +        *     Composite-ServiceImportPolicy: &quot;(attr=somevalue)&quot;;
> +        *      composite-symbolic-name=&quot;org.example.composite&quot;; composite-version=&quot;[1.0,1.1)&quot;
> +        * </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=&quot;[1.0,2.0)&quot;
> +</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>
>
>
>

Re: 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/jav

Posted by Guillaume Nodet <gn...@gmail.com>.
On Tue, Apr 6, 2010 at 15:30, Lin Sun <li...@gmail.com> wrote:

> Please see replies in line.
>
>
> On Tue, Apr 6, 2010 at 2:47 AM, Guillaume Nodet <gn...@gmail.com> wrote:
> >> Yeah, it's the same as the application installer.  It works with Felix
> > Fileinstall
> > which is used in Karaf (and Geronimo) to support file based deployments.
> > This is the way i've done very basic testing (by using Karaf and creating
> a
> > exploded
> > subsystem archive in the deploy folder).
>
> Ah I see.  I have been wondering how we can itest this stuff as I
> don't see the prototype equinox that contains the impl of the RFC 138
> available in maven central.
>
> > Yes, I think so.  Feel free to go ahead.  As I said, I only committed
> that
> > code so
> > that you can have a look and start working on it if you want.
>
> Ok great. I'll start making changes and if you don't like them, let me know
> :)
>
>
Sounds good.


> >
> > Not only.  The coupling between the admin and its internal subsystems is
> > quite loose.
> > Actually, subsystems are not put into the internal map when installed,
> but
> > only through those
> > processed bundle notifications.  I'm not sure it's actually a good idea,
> > because this means
> > that a subsystem which is being installed will be made available for
> > management before
> > it is fully installed.   So this certainly need to be reworked in the
> future
> > I think.
>
>
> Yes I think the code is a bit confusing as when we detect bundle event
> change we add the subsystem to the map or remove the subsystem off the
> map.   We don't deal with the map for the install() method, but for
> the uninstall() method, we remove the subsystem off the map.
>
> I think we don't necessarily need the sync bundle listener.   We can
> just process all the initial bundles then use install/uninstall/update
> to manage the map, assuming we only care about the subsystems that are
> installed via subsystemAdmin.  If you like that, I can try make the
> change.
>

Yeah, though I was not really keen on persisting the data for subsystems.
That's why I used a subsystem:=true directive on the symbolic name of the
underlying composite.  I think we still need the bundle listener in case the
user
uninstall a composite himself, or even in the case where a composite
installation
will install another peer composite in order to satisfy some dependencies.
So that's why I had chosen to just rely on those events, but the downside is
that
the subsystems appear before they are fully installed :-(


>
> > Once again, I don't consider any of this code as really working or final.
> >  The only think which is working
> > is the fact that you can install a subsystem and a composite will be
> created
> > with the jars listed
> > in the manifest.  It's a bit dumb and the NoOpResolver means that the
> only
> > way to install a subsystem is
> > by giving the location in the manifest:
> >
> > Manifest-Version: 1.0
> > Subsystem-ManifestVersion: 1.0
> > Subsystem-SymbolicName: woodstox
> > Subsystem-Version: 4.0.7
> > Subsystem-Content:
> >
> stax-api;location=mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.stax-api-1.0/1.4.0,
> >  stax2-api;location=mvn:org.codehaus.woodstox/stax2-api/3.0.1,
> >
>  woodstox-core-asl;location=mvn:org.codehaus.woodstox/woodstox-core-asl/4.0.7
> >
> > It certainly don't imply that this is what should be used by end users.
>  I
> > agree using urls inside the manifest defeats the purpose of
> > the resolver, but currently we have none, so I found that quite handy.
> > So the current code will be able to deploy those bundles, that's all.
>
> Yep we need to add other ResourceResolvers going forward.   So which
> framework impl jar is providing the CompositeAdmin service and
> creating the composite bundle in the test?  Is your test case checked
> in?
>

I don't really wrote any test case yet, those were just manual testing using
the
equinox prototype.  I've actually uploaded it to the servicemix private repo
for the
time being:

http://svn.apache.org/repos/asf/servicemix/m2-repo/org/eclipse/osgi/v43prototype-3.6.0.201003231329/
It would be nice if we can set up pax-exam to use that one, but I haven't
tried yet.



>
> Thanks
>
> Lin
>



-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://fusesource.com

Re: 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/jav

Posted by Lin Sun <li...@gmail.com>.
Please see replies in line.


On Tue, Apr 6, 2010 at 2:47 AM, Guillaume Nodet <gn...@gmail.com> wrote:
>> Yeah, it's the same as the application installer.  It works with Felix
> Fileinstall
> which is used in Karaf (and Geronimo) to support file based deployments.
> This is the way i've done very basic testing (by using Karaf and creating a
> exploded
> subsystem archive in the deploy folder).

Ah I see.  I have been wondering how we can itest this stuff as I
don't see the prototype equinox that contains the impl of the RFC 138
available in maven central.

> Yes, I think so.  Feel free to go ahead.  As I said, I only committed that
> code so
> that you can have a look and start working on it if you want.

Ok great. I'll start making changes and if you don't like them, let me know :)

>
> Not only.  The coupling between the admin and its internal subsystems is
> quite loose.
> Actually, subsystems are not put into the internal map when installed, but
> only through those
> processed bundle notifications.  I'm not sure it's actually a good idea,
> because this means
> that a subsystem which is being installed will be made available for
> management before
> it is fully installed.   So this certainly need to be reworked in the future
> I think.


Yes I think the code is a bit confusing as when we detect bundle event
change we add the subsystem to the map or remove the subsystem off the
map.   We don't deal with the map for the install() method, but for
the uninstall() method, we remove the subsystem off the map.

I think we don't necessarily need the sync bundle listener.   We can
just process all the initial bundles then use install/uninstall/update
to manage the map, assuming we only care about the subsystems that are
installed via subsystemAdmin.  If you like that, I can try make the
change.

> Once again, I don't consider any of this code as really working or final.
>  The only think which is working
> is the fact that you can install a subsystem and a composite will be created
> with the jars listed
> in the manifest.  It's a bit dumb and the NoOpResolver means that the only
> way to install a subsystem is
> by giving the location in the manifest:
>
> Manifest-Version: 1.0
> Subsystem-ManifestVersion: 1.0
> Subsystem-SymbolicName: woodstox
> Subsystem-Version: 4.0.7
> Subsystem-Content:
> stax-api;location=mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.stax-api-1.0/1.4.0,
>  stax2-api;location=mvn:org.codehaus.woodstox/stax2-api/3.0.1,
>  woodstox-core-asl;location=mvn:org.codehaus.woodstox/woodstox-core-asl/4.0.7
>
> It certainly don't imply that this is what should be used by end users.  I
> agree using urls inside the manifest defeats the purpose of
> the resolver, but currently we have none, so I found that quite handy.
> So the current code will be able to deploy those bundles, that's all.

Yep we need to add other ResourceResolvers going forward.   So which
framework impl jar is providing the CompositeAdmin service and
creating the composite bundle in the test?  Is your test case checked
in?

Thanks

Lin

Re: 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/jav

Posted by Guillaume Nodet <gn...@gmail.com>.
On Tue, Apr 6, 2010 at 04:22, Lin Sun <li...@gmail.com> wrote:

> Hi Guillaume,
>
> You are so fast! :)
>

There isn't much yet, really ...

>
> I have some initial Comments/Questions-
> 1. ArtifactInstaller... what is the purpose of SubsystemInstaller?  Is
> it intended to work only with felix?
>
> Yeah, it's the same as the application installer.  It works with Felix
Fileinstall
which is used in Karaf (and Geronimo) to support file based deployments.
This is the way i've done very basic testing (by using Karaf and creating a
exploded
subsystem archive in the deploy folder).


> 2. for BundleResourceProcessor.rollback() or
> SubsystemResourceProcessor.rollback(), should we clear the installed
> list at the end?
>

Yes, I think so.  Feel free to go ahead.  As I said, I only committed that
code so
that you can have a look and start working on it if you want.


>
> 3. SubsystemAdminImpl.bundleChanged... for BundleEvent.UPDATED, does
> this refer to the case where a bundle was a composite without
> subsystem directive but later got updated to be a composite with
> subsystem directive?
>

Not only.  The coupling between the admin and its internal subsystems is
quite loose.
Actually, subsystems are not put into the internal map when installed, but
only through those
processed bundle notifications.  I'm not sure it's actually a good idea,
because this means
that a subsystem which is being installed will be made available for
management before
it is fully installed.   So this certainly need to be reworked in the future
I think.

Once again, I don't consider any of this code as really working or final.
 The only think which is working
is the fact that you can install a subsystem and a composite will be created
with the jars listed
in the manifest.  It's a bit dumb and the NoOpResolver means that the only
way to install a subsystem is
by giving the location in the manifest:

Manifest-Version: 1.0
Subsystem-ManifestVersion: 1.0
Subsystem-SymbolicName: woodstox
Subsystem-Version: 4.0.7
Subsystem-Content:
stax-api;location=mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.stax-api-1.0/1.4.0,
 stax2-api;location=mvn:org.codehaus.woodstox/stax2-api/3.0.1,
 woodstox-core-asl;location=mvn:org.codehaus.woodstox/woodstox-core-asl/4.0.7

It certainly don't imply that this is what should be used by end users.  I
agree using urls inside the manifest defeats the purpose of
the resolver, but currently we have none, so I found that quite handy.
So the current code will be able to deploy those bundles, that's all.


> Thanks
>
> Lin
> On Fri, Apr 2, 2010 at 5:43 AM,  <gn...@apache.org> wrote:
> > 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 &#x007B;
> <code>INSTALLED</code>,
> > +        * <code>RESOLVED</code> &#x007D;.</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 &#x007B;
> <code>UNINSTALLED</code>
> > +        * &#x007D;.
> > +        * </ul>
> > +        * <b>Postconditions, no exceptions thrown </b>
> > +        * <ul>
> > +        * <li><code>getState()</code> in &#x007B;
> <code>INSTALLED</code>,
> > +        * <code>RESOLVED</code>, <code>ACTIVE</code> &#x007D;.
> > +        * <li>This composite has been updated.
> > +        * </ul>
> > +        * <b>Postconditions, when an exception is thrown </b>
> > +        * <ul>
> > +        * <li><code>getState()</code> in &#x007B;
> <code>INSTALLED</code>,
> > +        * <code>RESOLVED</code>, <code>ACTIVE</code> &#x007D;.
> > +        * <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
> &quot;Composite-PackageImportPolicy&quot;)
> > +        * 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
> &quot;Composite-PackageExportPolicy&quot;)
> > +        * 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
> &quot;Composite-BundleRequirePolicy&quot;)
> > +        * 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
> &quot;Composite-ServiceImportPolicy&quot;)
> > +        * 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
> &quot;Composite-ServiceExportPolicy&quot;)
> > +        * 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=&quot;org.example.composite&quot;
> > +        *     Composite-ServiceImportPolicy:
> &quot;(attr=somevalue)&quot;;
> composite-symbolic-name=&quot;org.example.composite&quot;
> > +        * </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=&quot;[1.0,1.1)&quot;
> > +        *     Composite-ServiceImportPolicy:
> &quot;(attr=somevalue)&quot;; composite-version=&quot;[1.0,1.1)&quot;
> > +        * </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=&quot;org.example.composite&quot;;
> composite-version=&quot;[1.0,1.1)&quot;
> > +        *     Composite-ServiceImportPolicy:
> &quot;(attr=somevalue)&quot;;
> > +        *
>  composite-symbolic-name=&quot;org.example.composite&quot;;
> composite-version=&quot;[1.0,1.1)&quot;
> > +        * </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=&quot;[1.0,2.0)&quot;
> > +</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>
> >
> >
> >
>



-- 
Cheers,
Guillaume Nodet
------------------------
Blog: http://gnodet.blogspot.com/
------------------------
Open Source SOA
http://fusesource.com