Merged latest trunk into subsystemsR6
git-svn-id: https://svn.apache.org/repos/asf/aries/branches/subsystemsR6@1684451 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/subsystem/subsystem-api/pom.xml b/subsystem/subsystem-api/pom.xml
index 0d4a90f..cfb7018 100644
--- a/subsystem/subsystem-api/pom.xml
+++ b/subsystem/subsystem-api/pom.xml
@@ -32,7 +32,7 @@
<artifactId>org.apache.aries.subsystem.api</artifactId>
<packaging>bundle</packaging>
<name>Apache Aries Subsystem API</name>
- <version>1.1.1-SNAPSHOT</version>
+ <version>1.2.0-SNAPSHOT</version>
<description>Subsystems API.</description>
<scm>
@@ -49,11 +49,10 @@
org.osgi.service.subsystem
</aries.osgi.export.pkg>
<aries.osgi.import>
- org.osgi.service.repository;version="[1.0,2)",
- org.osgi.service.subsystem;version="[1.0,2)",
- *
- </aries.osgi.import>
- <lastReleaseVersion>1.0.0</lastReleaseVersion>
+ org.osgi.service.repository;version="[1.0,1.1)",
+ org.osgi.service.subsystem;version="[1.1,1.2)",
+ *
+ </aries.osgi.import>
</properties>
<dependencies>
@@ -65,11 +64,16 @@
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
- <version>5.0.0</version>
+ <version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
+ <artifactId>org.osgi.annotation</artifactId>
+ <version>6.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
<artifactId>org.osgi.enterprise</artifactId>
<version>5.0.0</version>
<scope>provided</scope>
diff --git a/subsystem/subsystem-api/src/main/java/org/apache/aries/subsystem/AriesSubsystem.java b/subsystem/subsystem-api/src/main/java/org/apache/aries/subsystem/AriesSubsystem.java
index 2a11435..3387eb5 100644
--- a/subsystem/subsystem-api/src/main/java/org/apache/aries/subsystem/AriesSubsystem.java
+++ b/subsystem/subsystem-api/src/main/java/org/apache/aries/subsystem/AriesSubsystem.java
@@ -46,12 +46,15 @@
@Override
AriesSubsystem install(String location, InputStream content);
+ @Override
+ AriesSubsystem install(String location, InputStream content, InputStream deploymentManifest);
+
/**
* Installs a subsystem from the specified location identifier and content.
* <p>
* This method performs the same function as calling
- * {@link #install(String, InputStream)} except the content is retrieved
- * from the specified {@link IDirectory} instead.
+ * {@link #install(String, IDirectory, InputStream)} with a null deployment
+ * manifest.
*
* @param location The location identifier of the subsystem to install.
* @param content The directory from which this subsystem will be read or
@@ -66,7 +69,35 @@
* @throws SecurityException If the caller does not have the appropriate
* {@link SubsystemPermission}[installed subsystem,LIFECYCLE], and
* the runtime supports permissions.
- * @see #install(String, InputStream)
+ * @see #install(String, IDirectory, InputStream)
*/
AriesSubsystem install(String location, IDirectory content);
+
+ /**
+ * Installs a subsystem from the specified location identifier and content
+ * but uses the provided deployment manifest, if any, rather than the
+ * computed one or the one provided as part of the content.
+ * <p>
+ * This method performs the same function as calling
+ * {@link #install(String, InputStream, InputStream)} except the content is
+ * retrieved from the specified {@link IDirectory} instead.
+ *
+ * @param location The location identifier of the subsystem to install.
+ * @param content The directory from which this subsystem will be read or
+ * {@code null} to indicate the directory must be created from the
+ * specified location identifier.
+ * @param deploymentManifest The deployment manifest to use in lieu of any
+ * others.
+ * @return The installed subsystem.
+ * @throws IllegalStateException If this subsystem's state is in
+ * {@link State#INSTALLING INSTALLING}, {@link State#INSTALL_FAILED
+ * INSTALL_FAILED}, {@link State#UNINSTALLING UNINSTALLING},
+ * {@link State#UNINSTALLED UNINSTALLED}.
+ * @throws SubsystemException If the installation failed.
+ * @throws SecurityException If the caller does not have the appropriate
+ * {@link SubsystemPermission}[installed subsystem,LIFECYCLE], and
+ * the runtime supports permissions.
+ * @see #install(String, InputStream, InputStream)
+ */
+ AriesSubsystem install(String location, IDirectory content, InputStream deploymentManifest);
}
diff --git a/subsystem/subsystem-api/src/main/java/org/apache/aries/subsystem/packageinfo b/subsystem/subsystem-api/src/main/java/org/apache/aries/subsystem/packageinfo
index 1da3be9..3f71fe3 100644
--- a/subsystem/subsystem-api/src/main/java/org/apache/aries/subsystem/packageinfo
+++ b/subsystem/subsystem-api/src/main/java/org/apache/aries/subsystem/packageinfo
@@ -16,4 +16,4 @@
# specific language governing permissions and limitations
# under the License.
#
-version 1.1.0
+version 1.2.0
diff --git a/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/Subsystem.java b/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/Subsystem.java
index 13087fb..7cf39bf 100644
--- a/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/Subsystem.java
+++ b/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/Subsystem.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2012, 2013). 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.
@@ -20,6 +20,7 @@
import java.util.Collection;
import java.util.Locale;
import java.util.Map;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.IdentityNamespace;
@@ -72,7 +73,7 @@
* framework.</li>
* <li>{@link #getSubsystemId() ID} - An identifier generated by the
* implementation as part of installation. It is guaranteed to be unique within
- * the same framework.
+ * the same framework.</li>
* <li>{@link #getSymbolicName() Symbolic Name}/{@link #getVersion() Version} -
* The combination of symbolic name and version is guaranteed to be unique
* within the same region. Although {@link #getType() type} is not formally part
@@ -157,9 +158,9 @@
* </ul>
*
* @ThreadSafe
- * @noimplement
- * @version $Id: 73028a6997272cbac7e90ae00eb0f28afd14c8ee $
+ * @author $Id: 46dbc3d05b6c0fcd6962ffe433b62cbd284c3d0d $
*/
+@ProviderType
public interface Subsystem {
/**
* An enumeration of the possible states of a subsystem.
@@ -375,6 +376,28 @@
public Collection<Resource> getConstituents();
/**
+ * Returns the headers for this subsystem's deployment manifest.
+ * <p>
+ * Each key in the map is a header name and the value of the key is the
+ * corresponding header value. Because header names are case-insensitive,
+ * the methods of the map must treat the keys in a case-insensitive manner.
+ * If the header name is not found, {@code null} is returned. Both original
+ * and derived headers will be included in the map.
+ * <p>
+ * This method must continue to return the headers while this subsystem is
+ * in the {@link State#INSTALL_FAILED INSTALL_FAILED} or
+ * {@link State#UNINSTALLED UNINSTALLED} states.
+ *
+ * @return The headers for this subsystem's deployment manifest. The
+ * returned map is unmodifiable.
+ * @throws SecurityException If the caller does not have the appropriate
+ * {@link SubsystemPermission}[this,METADATA], and the runtime
+ * supports permissions.
+ * @since 1.1
+ */
+ public Map<String, String> getDeploymentHeaders();
+
+ /**
* Returns the current state of this subsystem.
* <p>
* This method must continue to return this subsystem's state while this
@@ -514,16 +537,18 @@
* reading the content, an installation failure results.</li>
* <li>If an installed subsystem with the same symbolic name and version
* already exists within this subsystem's region, complete the installation
- * with one of the following.<br/>
- * - If the installing and installed subsystems' types are not equal, an
- * installation failure results.<br/>
- * - If the installing and installed subsystems' types are equal, and the
+ * with one of the following.
+ * <ul>
+ * <li>If the installing and installed subsystems' types are not equal, an
+ * installation failure results.</li>
+ * <li>If the installing and installed subsystems' types are equal, and the
* installed subsystem is already a child of this subsystem, return the
- * installed subsystem.<br/>
- * - If the installing and installed subsystems' types are equal, and the
+ * installed subsystem.</li>
+ * <li>If the installing and installed subsystems' types are equal, and the
* installed subsystem is not already a child of this subsystem, add the
* installed subsystem as a child of this subsystem, increment the installed
- * subsystem's reference count by one, and return the installed subsystem.
+ * subsystem's reference count by one, and return the installed subsystem.</li>
+ * </ul>
* <li>Create a new subsystem based on the specified location and content.</li>
* <li>If the subsystem is scoped, install and start a new region context
* bundle.</li>
@@ -557,7 +582,7 @@
* <li>Change the state to {@link State#INSTALL_FAILED INSTALL_FAILED}.</li>
* <li>Change the state to {@link State#UNINSTALLING UNINSTALLING}.</li>
* <li>All content and dependencies which may have been installed by the
- * installing process must be uninstalled.
+ * installing process must be uninstalled.</li>
* <li>Change the state to {@link State#UNINSTALLED UNINSTALLED}.</li>
* <li>Unregister the subsystem service.</li>
* <li>If the subsystem is a scoped subsystem then, uninstall the region
@@ -584,6 +609,39 @@
public Subsystem install(String location, InputStream content);
/**
+ * Installs a subsystem from the specified content according to the
+ * specified deployment manifest.
+ * <p>
+ * This method installs a subsystem using the provided deployment manifest
+ * instead of the one in the archive, if any, or a computed one. If the
+ * deployment manifest is {@code null}, the behavior is exactly the same as
+ * in the {@link #install(String, InputStream)} method. Implementations must
+ * support deployment manifest input streams in the format described by
+ * section 134.2 of the Subsystem Service Specification. If the deployment
+ * manifest does not conform to the subsystem manifest (see 134.15.2), the
+ * installation fails.
+ *
+ * @param location The location identifier of the subsystem to be installed.
+ * @param content The input stream from which this subsystem will be read or
+ * {@code null} to indicate the input stream must be created from the
+ * specified location identifier. The input stream will always be
+ * closed when this method completes, even if an exception is thrown.
+ * @param deploymentManifest The deployment manifest to use in lieu of the
+ * one in the archive, if any, or a computed one.
+ * @return The installed subsystem.
+ * @throws IllegalStateException If this subsystem's state is in
+ * {@link State#INSTALLING INSTALLING}, {@link State#INSTALL_FAILED
+ * INSTALL_FAILED}, {@link State#UNINSTALLING UNINSTALLING},
+ * {@link State#UNINSTALLED UNINSTALLED}.
+ * @throws SubsystemException If the installation failed.
+ * @throws SecurityException If the caller does not have the appropriate
+ * {@link SubsystemPermission}[installed subsystem,LIFECYCLE], and
+ * the runtime supports permissions.
+ * @since 1.1
+ */
+ public Subsystem install(String location, InputStream content, InputStream deploymentManifest);
+
+ /**
* Starts this subsystem.
* <p>
* The following table shows which actions are associated with each state.
@@ -606,8 +664,7 @@
* </tr>
* <tr>
* <td>{@link State#INSTALLED INSTALLED}</td>
- * <td>{@code Resolve}<br/>
- * {@code Start}</td>
+ * <td>{@code Resolve}, {@code Start}</td>
* </tr>
* <tr>
* <td>{@link State#INSTALL_FAILED INSTALL_FAILED}</td>
@@ -845,8 +902,7 @@
* </tr>
* <tr>
* <td>{@link State#ACTIVE ACTIVE}</td>
- * <td>{@code Stop}<br/>
- * {@code Uninstall}</td>
+ * <td>{@code Stop}, {@code Uninstall}</td>
* </tr>
* <tr>
* <td>{@link State#STOPPING STOPPING}</td>
diff --git a/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/SubsystemConstants.java b/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/SubsystemConstants.java
index baa5456..26be06b 100644
--- a/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/SubsystemConstants.java
+++ b/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/SubsystemConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2011, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2011, 2013). 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.
@@ -25,7 +25,7 @@
* otherwise indicated.
*
* @Immutable
- * @version $Id: 53f0bd1ccdd14681f09adc3c9dde8e0b95154b71 $
+ * @author $Id: 36e2190a16d3bd0e4ed0e34799286284c0986974 $
*/
public class SubsystemConstants {
private SubsystemConstants() {
@@ -91,22 +91,60 @@
public static final String START_ORDER_DIRECTIVE = "start-order";
/**
+ * Manifest header identifying the categories of a subsystem as a
+ * comma-delimited list.
+ *
+ * @since 1.1
+ */
+ public static final String SUBSYSTEM_CATEGORY = "Subsystem-Category";
+
+ /**
+ * Manifest header identifying the contact address where problems with a
+ * subsystem may be reported; for example, an email address.
+ *
+ * @since 1.1
+ */
+ public static final String SUBSYSTEM_CONTACTADDRESS = "Subsystem-ContactAddress";
+
+ /**
* Manifest header identifying the list of subsystem contents identified by
* a symbolic name and version.
*/
public static final String SUBSYSTEM_CONTENT = "Subsystem-Content";
/**
+ * Manifest header identifying a subsystem's copyright information.
+ *
+ * @since 1.1
+ */
+ public static final String SUBSYSTEM_COPYRIGHT = "Subsystem-Copyright";
+
+ /**
* Manifest header identifying the human readable description.
*/
public static final String SUBSYSTEM_DESCRIPTION = "Subsystem-Description";
/**
+ * Manifest header identifying a subsystem's documentation URL, from which
+ * further information about the subsystem may be obtained.
+ *
+ * @since 1.1
+ */
+ public static final String SUBSYSTEM_DOCURL = "Subsystem-DocURL";
+
+ /**
* Manifest header identifying services offered for export.
*/
public static final String SUBSYSTEM_EXPORTSERVICE = "Subsystem-ExportService";
/**
+ * Manifest header identifying the icon URL for the subsystem.
+ *
+ * @since 1.1
+ */
+ public static final String SUBSYSTEM_ICON = "Subsystem-Icon";
+
+ /**
* The name of the service property for the
* {@link Subsystem#getSubsystemId() subsystem ID}. The value of this
* property must be of type {@code Long}.
@@ -119,6 +157,29 @@
public static final String SUBSYSTEM_IMPORTSERVICE = "Subsystem-ImportService";
/**
+ * Manifest header identifying a subsystem's license.
+ *
+ * @since 1.1
+ */
+ public static final String SUBSYSTEM_LICENSE = "Subsystem-License";
+
+ /**
+ * Manifest header identifying the base name of a subsystem's localization
+ * entries.
+ *
+ * @since 1.1
+ */
+ public static final String SUBSYSTEM_LOCALIZATION = "Subsystem-Localization";
+
+ /**
+ * Default value for the {@link #SUBSYSTEM_LOCALIZATION
+ * Subsystem-Localization} manifest header.
+ *
+ * @since 1.1
+ */
+ public static final String SUBSYSTEM_LOCALIZATION_DEFAULT_BASENAME = "OSGI-INF/l10n/subsystem";
+
+ /**
* Manifest header identifying the subsystem manifest version. If not
* present, the default value is {@code 1}.
*/
@@ -203,6 +264,13 @@
public static final String SUBSYSTEM_TYPE_FEATURE = "osgi.subsystem.feature";
/**
+ * Manifest header identifying a subsystem's vendor.
+ *
+ * @since 1.1
+ */
+ public static final String SUBSYSTEM_VENDOR = "Subsystem-Vendor";
+
+ /**
* Manifest header value identifying the version of the subsystem. If not
* present, the default value is {@code 0.0.0}.
*/
diff --git a/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/SubsystemException.java b/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/SubsystemException.java
index 35e6091..9812bfe 100644
--- a/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/SubsystemException.java
+++ b/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/SubsystemException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2011, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2011, 2013). 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.
@@ -19,7 +19,7 @@
/**
* A Subsystem exception used to indicate a problem.
*
- * @version $Id: 06542037c2bdaa7d328a368223b4f71b7a1c3dea $
+ * @author $Id: ad56ae269d24c698380e80d2f91c76d61ee121ff $
*/
public class SubsystemException extends RuntimeException {
private static final long serialVersionUID = 1L;
diff --git a/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/SubsystemPermission.java b/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/SubsystemPermission.java
index 518613d..c907f6f 100644
--- a/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/SubsystemPermission.java
+++ b/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/SubsystemPermission.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2000, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2013). 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.
@@ -49,7 +49,7 @@
* Subsystem.stop
* lifecycle Subsystem.install
* Subsystem.uninstall
- * metadata Subsystem.getHeaders
+ * metadata Subsystem.getSubsystemHeaders
* Subsystem.getLocation
* </pre>
*
@@ -64,7 +64,7 @@
* Filter attribute names are processed in a case sensitive manner.
*
* @ThreadSafe
- * @version $Id: 6674ee12cbc60cedd5392edc39793df91aac4a1e $
+ * @author $Id: 5c71d73cc6a3e8b2c2a7a3f188ebcf79b5ef7888 $
*/
public final class SubsystemPermission extends BasicPermission {
@@ -373,6 +373,7 @@
* @return {@code true} if the specified permission is implied by this
* object; {@code false} otherwise.
*/
+ @Override
public boolean implies(Permission p) {
if (!(p instanceof SubsystemPermission)) {
return false;
@@ -442,6 +443,7 @@
* @return Canonical string representation of the
* {@code SubsystemPermission} actions.
*/
+ @Override
public String getActions() {
String result = actions;
if (result == null) {
@@ -485,6 +487,7 @@
*
* @return A new {@code PermissionCollection} object.
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new SubsystemPermissionCollection();
}
@@ -496,6 +499,7 @@
* @return {@code true} if {@code obj} is equivalent to this
* {@code SubsystemPermission}; {@code false} otherwise.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -516,6 +520,7 @@
*
* @return Hash code value for this object.
*/
+ @Override
public int hashCode() {
int h = 31 * 17 + getName().hashCode();
h = 31 * h + getActions().hashCode();
@@ -579,8 +584,8 @@
recurse.set(subsystem);
try {
final Map<String, Object> map = new HashMap<String, Object>(4);
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
map.put("id", new Long(subsystem.getSubsystemId()));
map.put("location", subsystem.getLocation());
map.put("name", subsystem.getSymbolicName());
@@ -632,6 +637,7 @@
* @throws SecurityException If this {@code SubsystemPermissionCollection}
* object has been marked read-only.
*/
+ @Override
public void add(Permission permission) {
if (!(permission instanceof SubsystemPermission)) {
throw new IllegalArgumentException("invalid permission: " + permission);
@@ -675,6 +681,7 @@
* {@code SubsystemPermission} in this collection, {@code false}
* otherwise.
*/
+ @Override
public boolean implies(Permission permission) {
if (!(permission instanceof SubsystemPermission)) {
return false;
@@ -718,6 +725,7 @@
*
* @return Enumeration of all {@code SubsystemPermission} objects.
*/
+ @Override
public synchronized Enumeration<Permission> elements() {
List<Permission> all = new ArrayList<Permission>(permissions.values());
return Collections.enumeration(all);
@@ -735,6 +743,7 @@
private synchronized void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gfields = in.readFields();
+ @SuppressWarnings("unchecked")
HashMap<String, SubsystemPermission> p = (HashMap<String, SubsystemPermission>) gfields.get("permissions", null);
permissions = p;
all_allowed = gfields.get("all_allowed", false);
diff --git a/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/package-info.java b/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/package-info.java
index 3b6206d..d4f66a0 100644
--- a/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/package-info.java
+++ b/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2010, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2010, 2013). 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.
@@ -15,7 +15,7 @@
*/
/**
- * Subsystem Service Package Version 1.0.
+ * Subsystem Service Package Version 1.1.
*
* <p>
* Bundles wishing to use this package must list the package in the
@@ -26,14 +26,17 @@
* <p>
* Example import for consumers using the API in this package:
* <p>
- * {@code Import-Package: org.osgi.service.subsystem; version="[1.0,2.0)"}
+ * {@code Import-Package: org.osgi.service.subsystem; version="[1.1,2.0)"}
* <p>
* Example import for providers implementing the API in this package:
* <p>
- * {@code Import-Package: org.osgi.service.subsystem; version="[1.0,1.1)"}
+ * {@code Import-Package: org.osgi.service.subsystem; version="[1.1,1.2)"}
*
- * @version $Id: 3d0a1cfa6351c5c269c23358cfe3cc21403ba453 $
+ * @author $Id: ef9042c42a3fbb135031bf4446e4e0fa0a579d22 $
*/
+@Version("1.1")
package org.osgi.service.subsystem;
+import org.osgi.annotation.versioning.Version;
+
diff --git a/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/packageinfo b/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/packageinfo
index 4aa729c..1d2576a 100644
--- a/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/packageinfo
+++ b/subsystem/subsystem-api/src/main/java/org/osgi/service/subsystem/packageinfo
@@ -16,4 +16,4 @@
# specific language governing permissions and limitations
# under the License.
#
-version 1.0
+version 1.1
diff --git a/subsystem/subsystem-bundle/pom.xml b/subsystem/subsystem-bundle/pom.xml
index 3260e06..7058c40 100644
--- a/subsystem/subsystem-bundle/pom.xml
+++ b/subsystem/subsystem-bundle/pom.xml
@@ -45,16 +45,16 @@
<aries.osgi.activator>
org.apache.aries.subsystem.core.internal.Activator
</aries.osgi.activator>
- <aries.osgi.import>
- org.osgi.service.repository;version="[1.0,2)",
- org.osgi.service.subsystem;version="[1.0,2)",
+ <aries.osgi.import>
+ org.osgi.service.repository;version="[1.0,1.1)",
+ org.osgi.service.subsystem;version="[1.1,1.2)",
org.apache.aries.application.*;resolution:=optional,
*
</aries.osgi.import>
<aries.osgi.export.pkg>
org.apache.aries.subsystem;version="1.1",
org.osgi.service.repository;version="1.0",
- org.osgi.service.subsystem;version="1.0"
+ org.osgi.service.subsystem;version="1.1"
</aries.osgi.export.pkg>
<aries.osgi.private.pkg>
org.apache.aries.subsystem.*
@@ -66,12 +66,12 @@
<dependency>
<groupId>org.apache.aries.subsystem</groupId>
<artifactId>org.apache.aries.subsystem.api</artifactId>
- <version>1.1.1-SNAPSHOT</version>
+ <version>1.2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.aries.subsystem</groupId>
<artifactId>org.apache.aries.subsystem.core</artifactId>
- <version>1.2.1-SNAPSHOT</version>
+ <version>1.3.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.aries</groupId>
@@ -119,9 +119,9 @@
<version>1.1.0.v20120522-1841</version>
</dependency>
<dependency>
- <groupId>org.eclipse</groupId>
+ <groupId>org.eclipse.tycho</groupId>
<artifactId>org.eclipse.osgi</artifactId>
- <version>3.8.0.v20120529-1548</version>
+ <version>3.10.0.v20140606-1445</version>
</dependency>
</dependencies>
diff --git a/subsystem/subsystem-core/pom.xml b/subsystem/subsystem-core/pom.xml
index 14ea641..b954940 100644
--- a/subsystem/subsystem-core/pom.xml
+++ b/subsystem/subsystem-core/pom.xml
@@ -32,7 +32,7 @@
<artifactId>org.apache.aries.subsystem.core</artifactId>
<packaging>bundle</packaging>
<name>Apache Aries Subsystem Core</name>
- <version>1.2.1-SNAPSHOT</version>
+ <version>1.3.0-SNAPSHOT</version>
<description>Subsystems Core.</description>
<scm>
@@ -45,10 +45,9 @@
<aries.osgi.activator>
org.apache.aries.subsystem.core.internal.Activator
</aries.osgi.activator>
- <aries.osgi.import>
- org.osgi.service.repository;version="[1.0,2)",
- org.osgi.service.subsystem;version="[1.0,2)",
- org.apache.aries.subsystem;version="[1.1,2)",
+ <aries.osgi.import>
+ org.osgi.service.subsystem;version="[1.1,1.2)",
+ org.apache.aries.subsystem;version="[1.2,1.3)",
org.apache.aries.application.*;resolution:=optional,
*
</aries.osgi.import>
@@ -63,7 +62,7 @@
<dependency>
<groupId>org.apache.aries.subsystem</groupId>
<artifactId>org.apache.aries.subsystem.api</artifactId>
- <version>1.1.1-SNAPSHOT</version>
+ <version>1.2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.aries</groupId>
@@ -83,7 +82,7 @@
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
- <version>5.0.0</version>
+ <version>6.0.0</version>
<scope>provided</scope>
</dependency>
<dependency>
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DynamicImportPackageHeader.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DynamicImportPackageHeader.java
new file mode 100755
index 0000000..43911ee
--- /dev/null
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DynamicImportPackageHeader.java
@@ -0,0 +1,210 @@
+/*
+ * 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.archive;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.osgi.framework.Constants;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.resource.Resource;
+
+public class DynamicImportPackageHeader implements RequirementHeader<DynamicImportPackageHeader.Clause> {
+ public static class Clause implements org.apache.aries.subsystem.core.archive.Clause {
+ private static final String REGEX1 = '(' + Grammar.WILDCARD_NAMES + ")(?=;|\\z)";
+ private static final String REGEX2 = '(' + Grammar.PARAMETER + ")(?=;|\\z)";
+ private static final Pattern PATTERN1 = Pattern.compile(REGEX1);
+ private static final Pattern PATTERN2 = Pattern.compile(REGEX2);
+
+ private static void fillInDefaults(Map<String, Parameter> parameters) {
+ Parameter parameter = parameters.get(Constants.VERSION_ATTRIBUTE);
+ if (parameter == null)
+ parameters.put(Constants.VERSION_ATTRIBUTE, new VersionRangeAttribute());
+ }
+
+ private final Map<String, Parameter> myParameters = new HashMap<String, Parameter>();
+ private final String myPath;
+
+ public Clause(String clause) {
+ Matcher matcher = PATTERN1.matcher(clause);
+ if (matcher.find())
+ myPath = matcher.group().replaceAll("\\s", "");
+ else
+ throw new IllegalArgumentException("Invalid " + Constants.IMPORT_PACKAGE + " header clause: " + clause);
+ matcher.usePattern(PATTERN2);
+ while (matcher.find()) {
+ Parameter parameter = ParameterFactory.create(matcher.group());
+ // TODO Revisit the following fix.
+ // All version attributes on an ImportPackage header are ranges. The ParameterFactory will return
+ // a VersionAttribute when the value is a single version (e.g., version=1.0.0). This causes a
+ // ClassCastException in getVersionRangeAttribute().
+ if (parameter instanceof VersionAttribute)
+ parameter = new VersionRangeAttribute(String.valueOf(parameter.getValue()));
+ myParameters.put(parameter.getName(), parameter);
+ }
+ fillInDefaults(myParameters);
+ }
+
+ @Override
+ public Attribute getAttribute(String name) {
+ Parameter result = myParameters.get(name);
+ if (result instanceof Attribute) {
+ return (Attribute)result;
+ }
+ return null;
+ }
+
+ @Override
+ public Collection<Attribute> getAttributes() {
+ ArrayList<Attribute> attributes = new ArrayList<Attribute>(myParameters.size());
+ for (Parameter parameter : myParameters.values()) {
+ if (parameter instanceof Attribute) {
+ attributes.add((Attribute)parameter);
+ }
+ }
+ attributes.trimToSize();
+ return attributes;
+ }
+
+ @Override
+ public Directive getDirective(String name) {
+ Parameter result = myParameters.get(name);
+ if (result instanceof Directive) {
+ return (Directive)result;
+ }
+ return null;
+ }
+
+ @Override
+ public Collection<Directive> getDirectives() {
+ ArrayList<Directive> directives = new ArrayList<Directive>(myParameters.size());
+ for (Parameter parameter : myParameters.values()) {
+ if (parameter instanceof Directive) {
+ directives.add((Directive)parameter);
+ }
+ }
+ directives.trimToSize();
+ return directives;
+ }
+
+ public Collection<String> getPackageNames() {
+ return Arrays.asList(myPath.split(";"));
+ }
+
+ @Override
+ public Parameter getParameter(String name) {
+ return myParameters.get(name);
+ }
+
+ @Override
+ public Collection<Parameter> getParameters() {
+ return Collections.unmodifiableCollection(myParameters.values());
+ }
+
+ @Override
+ public String getPath() {
+ return myPath;
+ }
+
+ public VersionRangeAttribute getVersionRangeAttribute() {
+ return (VersionRangeAttribute)myParameters.get(Constants.VERSION_ATTRIBUTE);
+ }
+
+ public List<DynamicImportPackageRequirement> toRequirements(Resource resource) {
+ Collection<String> pkgs = getPackageNames();
+ List<DynamicImportPackageRequirement> result = new ArrayList<DynamicImportPackageRequirement>(pkgs.size());
+ for (String pkg : pkgs) {
+ result.add(new DynamicImportPackageRequirement(pkg, this, resource));
+ }
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder()
+ .append(getPath());
+ for (Parameter parameter : getParameters()) {
+ builder.append(';').append(parameter);
+ }
+ return builder.toString();
+ }
+ }
+
+ public static final String ATTRIBUTE_BUNDLE_SYMBOLICNAME = PackageNamespace.CAPABILITY_BUNDLE_SYMBOLICNAME_ATTRIBUTE;
+ public static final String ATTRIBUTE_BUNDLE_VERSION = PackageNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE;
+ public static final String ATTRIBUTE_VERSION = PackageNamespace.CAPABILITY_VERSION_ATTRIBUTE;
+ public static final String NAME = Constants.DYNAMICIMPORT_PACKAGE;
+
+ private static Collection<Clause> processHeader(String header) {
+ Set<Clause> clauses = new HashSet<Clause>();
+ for (String clause : new ClauseTokenizer(header).getClauses())
+ clauses.add(new Clause(clause));
+ return clauses;
+ }
+
+ private final Set<Clause> clauses;
+
+ public DynamicImportPackageHeader(Collection<Clause> clauses) {
+ if (clauses.isEmpty())
+ throw new IllegalArgumentException("A DynamicImport-Package header must have at least one clause");
+ this.clauses = new HashSet<Clause>(clauses);
+ }
+
+ public DynamicImportPackageHeader(String header) {
+ this(processHeader(header));
+ }
+
+ public Collection<DynamicImportPackageHeader.Clause> getClauses() {
+ return Collections.unmodifiableSet(clauses);
+ }
+
+ public String getName() {
+ return Constants.IMPORT_PACKAGE;
+ }
+
+ @Override
+ public String getValue() {
+ return toString();
+ }
+
+ @Override
+ public List<DynamicImportPackageRequirement> toRequirements(Resource resource) {
+ Collection<Clause> clauses = getClauses();
+ List<DynamicImportPackageRequirement> result = new ArrayList<DynamicImportPackageRequirement>(clauses.size());
+ for (Clause clause : clauses) {
+ result.addAll(clause.toRequirements(resource));
+ }
+ return result;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ for (Clause clause : getClauses()) {
+ builder.append(clause).append(',');
+ }
+ // Remove the trailing comma. Note at least one clause is guaranteed to exist.
+ builder.deleteCharAt(builder.length() - 1);
+ return builder.toString();
+ }
+}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DynamicImportPackageRequirement.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DynamicImportPackageRequirement.java
new file mode 100755
index 0000000..1e75b4c
--- /dev/null
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/DynamicImportPackageRequirement.java
@@ -0,0 +1,72 @@
+/*
+ * 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.archive;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.aries.subsystem.core.internal.AbstractRequirement;
+import org.osgi.framework.namespace.PackageNamespace;
+import org.osgi.resource.Resource;
+
+public class DynamicImportPackageRequirement extends AbstractRequirement {
+ public static final String DIRECTIVE_FILTER = PackageNamespace.REQUIREMENT_FILTER_DIRECTIVE;
+ public static final String NAMESPACE = PackageNamespace.PACKAGE_NAMESPACE;
+
+ private final Map<String, String> directives;
+ private final String packageName;
+ private final Resource resource;
+
+ public DynamicImportPackageRequirement(String pkg, DynamicImportPackageHeader.Clause clause, Resource resource) {
+ packageName = pkg;
+ Collection<Directive> clauseDirectives = clause.getDirectives();
+ directives = new HashMap<String, String>(clauseDirectives.size() + 1);
+ for (Directive directive : clauseDirectives)
+ directives.put(directive.getName(), directive.getValue());
+ StringBuilder filter = new StringBuilder("(&(").append(NAMESPACE)
+ .append('=').append(pkg).append(')');
+ VersionRangeAttribute versionRange = clause.getVersionRangeAttribute();
+ if (versionRange != null) {
+ versionRange.appendToFilter(filter);
+ }
+ directives.put(DIRECTIVE_FILTER, filter.append(')').toString());
+ this.resource = resource;
+ }
+
+ @Override
+ public Map<String, Object> getAttributes() {
+ return Collections.emptyMap();
+ }
+
+ @Override
+ public Map<String, String> getDirectives() {
+ return Collections.unmodifiableMap(directives);
+ }
+
+ @Override
+ public String getNamespace() {
+ return NAMESPACE;
+ }
+
+ public String getPackageName() {
+ return packageName;
+ }
+
+ @Override
+ public Resource getResource() {
+ return resource;
+ }
+}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Grammar.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Grammar.java
index f251f7e..fc049bf 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Grammar.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/Grammar.java
@@ -163,4 +163,9 @@
public static final String CEILING = VERSION;
public static final String INTERVAL = "[\\[\\(]" + FLOOR + ',' + CEILING + "[\\[\\)]";
public static final String VERSIONRANGE = INTERVAL + '|' + ATLEAST;
+
+ public static final String WILDCARD_NAME = PACKAGENAME + '|' + PACKAGENAME + "\\.\\*" + "|\\*";
+ public static final String WILDCARD_NAMES = WILDCARD_NAME + "\\s*(?:\\;\\s*" + WILDCARD_NAME + ")*";
+ public static final String DYNAMIC_DESCRIPTION = WILDCARD_NAMES + "(?:;\\s*(?:" + PARAMETER + "))*";
+ public static final String DYNAMICIMPORT_PACKAGE = DYNAMIC_DESCRIPTION + "(?:\\,\\s*" + DYNAMIC_DESCRIPTION + ")*";
}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java
index edfcc63..40c7980 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/HeaderFactory.java
@@ -115,6 +115,8 @@
return new AriesSubsystemParentsHeader(value);
if (BundleRequiredExecutionEnvironmentHeader.NAME.equals(name))
return new BundleRequiredExecutionEnvironmentHeader(value);
+ if (SubsystemLocalizationHeader.NAME.equals(name))
+ return new SubsystemLocalizationHeader(value);
return new GenericHeader(name, value);
}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemExportServiceCapability.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemExportServiceCapability.java
index c5b808f..367a95d 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemExportServiceCapability.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemExportServiceCapability.java
@@ -19,13 +19,13 @@
import org.apache.aries.subsystem.core.internal.AbstractCapability;
import org.osgi.framework.Constants;
+import org.osgi.namespace.service.ServiceNamespace;
import org.osgi.resource.Namespace;
import org.osgi.resource.Resource;
public class SubsystemExportServiceCapability extends AbstractCapability {
public static final String DIRECTIVE_FILTER = Namespace.REQUIREMENT_FILTER_DIRECTIVE;
- // TODO Replace value with ServiceNamspace.SERVICE_NAMESPACE constant when available.
- public static final String NAMESPACE = "osgi.service";
+ public static final String NAMESPACE = ServiceNamespace.SERVICE_NAMESPACE;
private final Map<String, Object> attributes = new HashMap<String, Object>();
private final Map<String, String> directives = new HashMap<String, String>();
@@ -36,7 +36,7 @@
.append(Constants.OBJECTCLASS).append('=')
.append(clause.getObjectClass()).append(')');
Directive filter = clause
- .getDirective(SubsystemImportServiceHeader.Clause.DIRECTIVE_FILTER);
+ .getDirective(SubsystemExportServiceHeader.Clause.DIRECTIVE_FILTER);
if (filter != null)
builder.append(filter.getValue());
directives.put(DIRECTIVE_FILTER, builder.append(')').toString());
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemImportServiceRequirement.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemImportServiceRequirement.java
index dfd7765..9ed80d2 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemImportServiceRequirement.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemImportServiceRequirement.java
@@ -18,23 +18,36 @@
import java.util.Map;
import org.apache.aries.subsystem.core.internal.AbstractRequirement;
+import org.osgi.framework.Constants;
+import org.osgi.namespace.service.ServiceNamespace;
import org.osgi.resource.Namespace;
import org.osgi.resource.Resource;
public class SubsystemImportServiceRequirement extends AbstractRequirement {
public static final String DIRECTIVE_FILTER = Namespace.REQUIREMENT_FILTER_DIRECTIVE;
- // TODO Replace value with ServiceNamspace.SERVICE_NAMESPACE constant when available.
- public static final String NAMESPACE = "osgi.service";
+ public static final String NAMESPACE = ServiceNamespace.SERVICE_NAMESPACE;
private final Map<String, String> directives = new HashMap<String, String>(1);
private final Resource resource;
public SubsystemImportServiceRequirement(
SubsystemImportServiceHeader.Clause clause, Resource resource) {
- Directive filter = clause
- .getDirective(SubsystemImportServiceHeader.Clause.DIRECTIVE_FILTER);
- if (filter != null)
- directives.put(DIRECTIVE_FILTER, filter.getValue());
+ boolean appendObjectClass = !ServiceNamespace.SERVICE_NAMESPACE.equals(clause.getPath());
+ StringBuilder builder = new StringBuilder();
+ if (appendObjectClass) {
+ builder.append("(&(").append(Constants.OBJECTCLASS).append('=').append(clause.getPath()).append(')');
+ }
+ Directive filter = clause.getDirective(SubsystemExportServiceHeader.Clause.DIRECTIVE_FILTER);
+ if (filter != null) {
+ builder.append(filter.getValue());
+ }
+ if (appendObjectClass) {
+ builder.append(')');
+ }
+ String filterStr = builder.toString();
+ if (!filterStr.isEmpty()) {
+ directives.put(DIRECTIVE_FILTER, filterStr);
+ }
this.resource = resource;
}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemLocalizationHeader.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemLocalizationHeader.java
new file mode 100755
index 0000000..8b32c25
--- /dev/null
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemLocalizationHeader.java
@@ -0,0 +1,45 @@
+/*
+ * 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.archive;
+
+import org.osgi.service.subsystem.SubsystemConstants;
+
+public class SubsystemLocalizationHeader extends AbstractHeader {
+ public static final String DEFAULT_VALUE = "OSGI-INF/l10n/subsystem";
+ public static final String NAME = SubsystemConstants.SUBSYSTEM_LOCALIZATION;
+
+ public static final SubsystemLocalizationHeader DEFAULT = new SubsystemLocalizationHeader();
+
+ private final String baseFileName;
+ private final String directoryName;
+
+ public SubsystemLocalizationHeader() {
+ this(DEFAULT_VALUE);
+ }
+
+ public SubsystemLocalizationHeader(String value) {
+ super(NAME, value);
+ int index = value.lastIndexOf('/');
+ baseFileName = index == -1 ? value : value.substring(index + 1);
+ directoryName = index == -1 ? null : value.substring(0, index + 1);
+ }
+
+ public String getBaseFileName() {
+ return baseFileName;
+ }
+
+ public String getDirectoryName() {
+ return directoryName;
+ }
+}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemManifest.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemManifest.java
index e23bb06..5811e07 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemManifest.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/archive/SubsystemManifest.java
@@ -109,6 +109,7 @@
public static final String SUBSYSTEM_DESCRIPTION = SubsystemConstants.SUBSYSTEM_DESCRIPTION;
public static final String SUBSYSTEM_EXPORTSERVICE = SubsystemConstants.SUBSYSTEM_EXPORTSERVICE;
public static final String SUBSYSTEM_IMPORTSERVICE = SubsystemConstants.SUBSYSTEM_IMPORTSERVICE;
+ public static final String SUBSYTEM_LOCALIZATION = SubsystemConstants.SUBSYSTEM_LOCALIZATION;
public static final String SUBSYSTEM_MANIFESTVERSION = SubsystemConstants.SUBSYSTEM_MANIFESTVERSION;
public static final String SUBSYSTEM_NAME = SubsystemConstants.SUBSYSTEM_NAME;
public static final String SUBSYSTEM_SYMBOLICNAME = SubsystemConstants.SUBSYSTEM_SYMBOLICNAME;
@@ -132,6 +133,9 @@
header = headers.get(SUBSYSTEM_TYPE);
if (header == null)
headers.put(SUBSYSTEM_TYPE, SubsystemTypeHeader.DEFAULT);
+ header = headers.get(SUBSYTEM_LOCALIZATION);
+ if (header == null)
+ headers.put(SUBSYTEM_LOCALIZATION, SubsystemLocalizationHeader.DEFAULT);
}
private final Map<String, Header<?>> headers;
@@ -229,6 +233,10 @@
return (SubsystemImportServiceHeader)getHeaders().get(SUBSYSTEM_IMPORTSERVICE);
}
+ public SubsystemLocalizationHeader getSubsystemLocalizationHeader() {
+ return (SubsystemLocalizationHeader)getHeaders().get(SUBSYTEM_LOCALIZATION);
+ }
+
public SubsystemSymbolicNameHeader getSubsystemSymbolicNameHeader() {
return (SubsystemSymbolicNameHeader)getHeaders().get(SUBSYSTEM_SYMBOLICNAME);
}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java
index 3e5589b..7e42517 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/Activator.java
@@ -33,7 +33,6 @@
import org.osgi.framework.hooks.bundle.EventHook;
import org.osgi.framework.hooks.resolver.ResolverHookFactory;
import org.osgi.service.coordinator.Coordinator;
-import org.osgi.service.repository.Repository;
import org.osgi.service.resolver.Resolver;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
@@ -82,7 +81,6 @@
private volatile Subsystems subsystems;
private final Collection<ServiceRegistration<?>> registrations = new HashSet<ServiceRegistration<?>>();
- private final Collection<Repository> repositories = Collections.synchronizedSet(new HashSet<Repository>());
private final Collection<IDirectoryFinder> finders = Collections.synchronizedSet(new HashSet<IDirectoryFinder>());
public BundleContext getBundleContext() {
@@ -101,10 +99,6 @@
return regionDigraph;
}
- public Collection<Repository> getRepositories() {
- return Collections.unmodifiableCollection(repositories);
- }
-
public Collection<IDirectoryFinder> getIDirectoryFinders() {
return Collections.unmodifiableCollection(finders);
}
@@ -124,7 +118,7 @@
return result;
}
- public Repository getSystemRepository() {
+ public org.apache.aries.subsystem.core.repository.Repository getSystemRepository() {
return new SystemRepository(getSubsystems().getRootSubsystem());
}
@@ -163,6 +157,7 @@
BasicSubsystem root = subsystems.getRootSubsystem();
bundleEventHook.activate();
root.start();
+ registerWovenClassListener();
}
private void deactivate() {
@@ -208,7 +203,7 @@
.append(org.osgi.framework.Constants.OBJECTCLASS).append('=')
.append(Resolver.class.getName()).append(")(")
.append(org.osgi.framework.Constants.OBJECTCLASS).append('=')
- .append(Repository.class.getName()).append(")(")
+ .append("org.osgi.service.repository.Repository").append(")(")
.append(org.osgi.framework.Constants.OBJECTCLASS).append('=')
.append(MODELLED_RESOURCE_MANAGER).append(")(")
.append(org.osgi.framework.Constants.OBJECTCLASS).append('=')
@@ -234,6 +229,14 @@
registrations.add(bundleContext.registerService(EventHook.class, bundleEventHook, properties));
}
+ private void registerWovenClassListener() {
+ registrations.add(
+ bundleContext.registerService(
+ org.osgi.framework.hooks.weaving.WovenClassListener.class,
+ new WovenClassListener(bundleContext, subsystems),
+ null));
+ }
+
/* Begin ServiceTrackerCustomizer methods */
@Override
@@ -242,8 +245,6 @@
// Use all of each type of the following services.
if (service instanceof IDirectoryFinder)
finders.add((IDirectoryFinder) service);
- else if (service instanceof Repository)
- repositories.add((Repository) service);
// Use only one of each type of the following services.
else if (service instanceof Coordinator && coordinator == null)
coordinator = (Coordinator) service;
@@ -252,18 +253,20 @@
else if (service instanceof Resolver && resolver == null)
resolver = (Resolver) service;
else {
- try {
- Class clazz = getClass().getClassLoader().loadClass(MODELLED_RESOURCE_MANAGER);
- if (clazz.isInstance(service) && serviceModeller == null) {
- modelledResourceManager = service;
- serviceModeller = new ApplicationServiceModeller(service);
- }
- } catch (ClassNotFoundException e) {
- // ignore
- } catch (NoClassDefFoundError e) {
- // ignore
- }
- }
+ try {
+ Class clazz = getClass().getClassLoader().loadClass(MODELLED_RESOURCE_MANAGER);
+ if (clazz.isInstance(service) && serviceModeller == null) {
+ modelledResourceManager = service;
+ serviceModeller = new ApplicationServiceModeller(service);
+ } else {
+ service = null;
+ }
+ } catch (ClassNotFoundException e) {
+ service = null;
+ } catch (NoClassDefFoundError e) {
+ service = null;
+ }
+ }
// Activation is harmless if already active or all required services
// have not yet been found.
activate();
@@ -304,8 +307,6 @@
}
else if (service instanceof IDirectoryFinder)
finders.remove(service);
- else if (service instanceof Repository)
- repositories.remove(service);
else {
if (service.equals(modelledResourceManager)) {
try {
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java
index f99beb8..57c1b03 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BasicSubsystem.java
@@ -77,6 +77,10 @@
private final IDirectory directory;
public BasicSubsystem(SubsystemResource resource) throws URISyntaxException, IOException, BundleException, InvalidSyntaxException {
+ this(resource, null);
+ }
+
+ public BasicSubsystem(SubsystemResource resource, InputStream deploymentManifest) throws URISyntaxException, IOException, BundleException, InvalidSyntaxException {
this.resource = resource;
final File file = new File(Activator.getInstance().getBundleContext().getDataFile(""), Long.toString(resource.getId()));
file.mkdirs();
@@ -99,7 +103,7 @@
SubsystemManifestValidator.validate(this, getSubsystemManifest());
setDeploymentManifest(new DeploymentManifest.Builder()
.manifest(resource.getSubsystemManifest())
- .manifest(resource.getDeploymentManifest())
+ .manifest(deploymentManifest == null ? resource.getDeploymentManifest() : new DeploymentManifest(deploymentManifest))
.location(resource.getLocation())
.autostart(false)
.id(resource.getId())
@@ -107,6 +111,7 @@
.region(resource.getRegion().getName())
.state(State.INSTALLING)
.build());
+ setTranslations();
}
public BasicSubsystem(File file) throws IOException, URISyntaxException, ResolutionException {
@@ -194,7 +199,7 @@
@Override
public Map<String, String> getSubsystemHeaders(Locale locale) {
SecurityManager.checkMetadataPermission(this);
- return AccessController.doPrivileged(new GetSubsystemHeadersAction(this));
+ return AccessController.doPrivileged(new GetSubsystemHeadersAction(this, locale));
}
@Override
@@ -254,20 +259,8 @@
}
@Override
- public AriesSubsystem install(String location, final InputStream content) {
- try {
- return install(location, content == null ? null :
- AccessController.doPrivileged(new PrivilegedAction<IDirectory>() {
- @Override
- public IDirectory run() {
- return FileSystem.getFSRoot(content);
- }
- }));
- }
- finally {
- // This method must guarantee the content input stream was closed.
- IOUtils.close(content);
- }
+ public AriesSubsystem install(String location, InputStream content) {
+ return install(location, content, null);
}
@Override
@@ -618,7 +611,17 @@
@Override
public AriesSubsystem install(String location, IDirectory content) {
- return AccessController.doPrivileged(new InstallAction(location, content, this, AccessController.getContext()));
+ return install(location, content, null);
+ }
+
+ @Override
+ public AriesSubsystem install(String location, IDirectory content, InputStream deploymentManifest) {
+ try {
+ return AccessController.doPrivileged(new InstallAction(location, content, this, AccessController.getContext(), deploymentManifest));
+ }
+ finally {
+ IOUtils.close(deploymentManifest);
+ }
}
private static class SaveManifestParticipant implements Participant {
@@ -648,4 +651,38 @@
}
}
+
+ @Override
+ public Map<String, String> getDeploymentHeaders() {
+ SecurityManager.checkMetadataPermission(this);
+ return AccessController.doPrivileged(new GetDeploymentHeadersAction(this));
+ }
+
+ @Override
+ public AriesSubsystem install(String location, final InputStream content, InputStream deploymentManifest) {
+ try {
+ return install(location, content == null ? null :
+ AccessController.doPrivileged(new PrivilegedAction<IDirectory>() {
+ @Override
+ public IDirectory run() {
+ return FileSystem.getFSRoot(content);
+ }
+ }),
+ deploymentManifest);
+ }
+ finally {
+ // This method must guarantee the content input stream was closed.
+ IOUtils.close(content);
+ }
+ }
+
+ private void setTranslations() throws IOException {
+ String directoryName = getSubsystemManifest().getSubsystemLocalizationHeader().getDirectoryName();
+ File file = directoryName == null ? getDirectory() : new File(getDirectory(), directoryName);
+ if (!file.exists())
+ file.mkdirs();
+ for (TranslationFile translation : getResource().getTranslations()) {
+ translation.write(file);
+ }
+ }
}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResource.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResource.java
index e16209a..63d099a 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResource.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResource.java
@@ -41,13 +41,13 @@
import org.apache.aries.util.filesystem.IDirectory;
import org.apache.aries.util.filesystem.IFile;
import org.apache.aries.util.io.IOUtils;
+import org.osgi.namespace.service.ServiceNamespace;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
-import org.osgi.service.repository.RepositoryContent;
import org.osgi.service.subsystem.SubsystemException;
-public class BundleResource implements Resource, RepositoryContent {
+public class BundleResource implements Resource, org.apache.aries.subsystem.core.repository.RepositoryContent {
private static BundleManifest computeManifest(IDirectory directory) {
return new BundleManifest(org.apache.aries.util.manifest.BundleManifest
.fromBundle(directory)
@@ -187,14 +187,25 @@
// to services.
computeRequirementsOtherThanService();
computeCapabilitiesOtherThanService();
+ // OSGi RFC 201 for R6: The presence of any Require/Provide-Capability
+ // clauses in the osgi.service namespace overrides any service related
+ // requirements or capabilities that might have been found by other
+ // means.
+ boolean computeServiceRequirements = getRequirements(ServiceNamespace.SERVICE_NAMESPACE).isEmpty();
+ boolean computeServiceCapabilities = getCapabilities(ServiceNamespace.SERVICE_NAMESPACE).isEmpty();
+ if (!(computeServiceCapabilities || computeServiceRequirements))
+ return;
// Compute service requirements and capabilities if the optional
// ModelledResourceManager service is present.
ServiceModeller modeller = getServiceModeller();
if (modeller == null)
return;
- ServiceModeller.ServiceModel model = modeller.computeRequirementsAndCapabilities(this, directory);
- capabilities.addAll(model.getServiceCapabilities());
- requirements.addAll(model.getServiceRequirements());
+
+ ServiceModeller.ServiceModel model = modeller.computeRequirementsAndCapabilities(this, directory);
+ if (computeServiceCapabilities)
+ capabilities.addAll(model.getServiceCapabilities());
+ if (computeServiceRequirements)
+ requirements.addAll(model.getServiceRequirements());
}
private void computeRequirementsOtherThanService() {
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceInstaller.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceInstaller.java
index f5f5a46..e1a9e23 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceInstaller.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleResourceInstaller.java
@@ -33,7 +33,6 @@
import org.osgi.resource.Resource;
import org.osgi.service.coordinator.Coordination;
import org.osgi.service.coordinator.Participant;
-import org.osgi.service.repository.RepositoryContent;
import org.osgi.service.subsystem.SubsystemException;
public class BundleResourceInstaller extends ResourceInstaller {
@@ -175,16 +174,21 @@
revision = (BundleRevision)resource;
else {
ThreadLocalSubsystem.set(provisionTo);
- revision = installBundle();
+ try {
+ revision = installBundle();
+ }
+ catch (Exception e) {
+ throw new SubsystemException(e);
+ }
}
addReference(revision);
addConstituent(new BundleConstituent(resource, revision));
return revision;
}
- private BundleRevision installBundle() {
+ private BundleRevision installBundle() throws Exception {
final Bundle bundle;
- InputStream is = ((RepositoryContent)resource).getContent();
+ InputStream is = (InputStream)resource.getClass().getMethod("getContent").invoke(resource);
try {
bundle = provisionTo.getRegion().installBundleAtLocation(getLocation(), is);
}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleRevisionResource.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleRevisionResource.java
index 206734b..e5a70d9 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleRevisionResource.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/BundleRevisionResource.java
@@ -42,9 +42,13 @@
result.addAll(sCaps);
return Collections.unmodifiableList(result);
}
- if (ServiceNamespace.SERVICE_NAMESPACE.equals(namespace))
- return Collections.unmodifiableList(computeServiceCapabilities());
- return revision.getCapabilities(namespace);
+ List<Capability> result = revision.getCapabilities(namespace);
+ // OSGi RFC 201 for R6: The presence of any Provide-Capability clauses
+ // in the osgi.service namespace overrides any service related
+ // capabilities that might have been found by other means.
+ if (result.isEmpty() && ServiceNamespace.SERVICE_NAMESPACE.equals(namespace))
+ result = Collections.unmodifiableList(computeServiceCapabilities());
+ return result;
}
@Override
@@ -57,9 +61,13 @@
result.addAll(sReqs);
return Collections.unmodifiableList(result);
}
- if (ServiceNamespace.SERVICE_NAMESPACE.equals(namespace))
- return Collections.unmodifiableList(computeServiceRequirements());
- return revision.getRequirements(namespace);
+ // OSGi RFC 201 for R6: The presence of any Require-Capability clauses
+ // in the osgi.service namespace overrides any service related
+ // requirements that might have been found by other means.
+ List<Requirement> result = revision.getRequirements(namespace);
+ if (result.isEmpty() && ServiceNamespace.SERVICE_NAMESPACE.equals(namespace))
+ result = Collections.unmodifiableList(computeServiceRequirements());
+ return result;
}
private List<Capability> computeServiceCapabilities() {
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/CompositeRepository.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/CompositeRepository.java
index a7ab1cb..b9d2711 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/CompositeRepository.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/CompositeRepository.java
@@ -23,22 +23,21 @@
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
-import org.osgi.service.repository.Repository;
-public class CompositeRepository implements Repository {
- private final Collection<Repository> repositories;
+public class CompositeRepository implements org.apache.aries.subsystem.core.repository.Repository {
+ private final Collection<org.apache.aries.subsystem.core.repository.Repository> repositories;
- public CompositeRepository(Repository...repositories) {
+ public CompositeRepository(org.apache.aries.subsystem.core.repository.Repository...repositories) {
this(Arrays.asList(repositories));
}
- public CompositeRepository(Collection<Repository> repositories) {
+ public CompositeRepository(Collection<org.apache.aries.subsystem.core.repository.Repository> repositories) {
this.repositories = repositories;
}
public Collection<Capability> findProviders(Requirement requirement) {
Set<Capability> result = new HashSet<Capability>();
- for (Repository repository : repositories) {
+ for (org.apache.aries.subsystem.core.repository.Repository repository : repositories) {
Map<Requirement, Collection<Capability>> map = repository.findProviders(Collections.singleton(requirement));
Collection<Capability> capabilities = map.get(requirement);
if (capabilities == null)
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ContentRepository.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ContentRepository.java
index 55cadb4..24a4d17 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ContentRepository.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ContentRepository.java
@@ -23,9 +23,8 @@
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
-import org.osgi.service.repository.Repository;
-public class ContentRepository implements Repository {
+public class ContentRepository implements org.apache.aries.subsystem.core.repository.Repository {
private static void findContent(Requirement requirement, Collection<Capability> capabilities, Collection<Resource> resources) {
for (Resource resource : resources)
for (Capability capability : resource.getCapabilities(requirement.getNamespace()))
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/DependencyCalculator.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/DependencyCalculator.java
index 6063708..d74806e 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/DependencyCalculator.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/DependencyCalculator.java
@@ -25,6 +25,7 @@
import org.osgi.framework.Constants;
import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.namespace.NativeNamespace;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
@@ -35,8 +36,6 @@
import org.osgi.service.resolver.Resolver;
public class DependencyCalculator {
- // TODO replace with NativeNamespace constant in R6.
- static final String NATIVE_NAMESPACE = "osgi.native";
private static class ResolveContext extends
org.osgi.service.resolver.ResolveContext {
private final Collection<Resource> resources;
@@ -50,7 +49,7 @@
ArrayList<Capability> capabilities = new ArrayList<Capability>();
// never check local resources for osgi.ee or osgi.native capabilities
if (!(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE.equals(requirement.getNamespace())
- || NATIVE_NAMESPACE.equals(requirement.getNamespace()))) {
+ || NativeNamespace.NATIVE_NAMESPACE.equals(requirement.getNamespace()))) {
for (Resource resource : resources)
for (Capability capability : resource
.getCapabilities(requirement.getNamespace()))
@@ -86,7 +85,7 @@
}
}
- private static class MissingCapability extends AbstractCapability {
+ static class MissingCapability extends AbstractCapability {
private static class Resource implements org.osgi.resource.Resource {
public static final Resource INSTANCE = new Resource();
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetDeploymentHeadersAction.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetDeploymentHeadersAction.java
new file mode 100755
index 0000000..5e3a116
--- /dev/null
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetDeploymentHeadersAction.java
@@ -0,0 +1,40 @@
+/*
+ * 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.security.PrivilegedAction;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.apache.aries.subsystem.core.archive.Header;
+
+public class GetDeploymentHeadersAction implements PrivilegedAction<Map<String, String>> {
+ private final BasicSubsystem subsystem;
+
+ public GetDeploymentHeadersAction(BasicSubsystem subsystem) {
+ this.subsystem = subsystem;
+ }
+
+ @Override
+ public Map<String, String> run() {
+ Map<String, Header<?>> headers = subsystem.getDeploymentManifest().getHeaders();
+ Map<String, String> result = new HashMap<String, String>(headers.size());
+ for (Entry<String, Header<?>> entry: headers.entrySet()) {
+ Header<?> value = entry.getValue();
+ result.put(entry.getKey(), value.getValue());
+ }
+ return result;
+ }
+}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetSubsystemHeadersAction.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetSubsystemHeadersAction.java
index 7152460..7395d92 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetSubsystemHeadersAction.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/GetSubsystemHeadersAction.java
@@ -13,18 +13,28 @@
*/
package org.apache.aries.subsystem.core.internal;
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLClassLoader;
import java.security.PrivilegedAction;
import java.util.HashMap;
+import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.ResourceBundle;
import org.apache.aries.subsystem.core.archive.Header;
public class GetSubsystemHeadersAction implements PrivilegedAction<Map<String, String>> {
+ private final Locale locale;
private final BasicSubsystem subsystem;
- public GetSubsystemHeadersAction(BasicSubsystem subsystem) {
+ public GetSubsystemHeadersAction(BasicSubsystem subsystem, Locale locale) {
this.subsystem = subsystem;
+ this.locale = locale;
}
@Override
@@ -33,9 +43,50 @@
Map<String, String> result = new HashMap<String, String>(headers.size());
for (Entry<String, Header<?>> entry: headers.entrySet()) {
Header<?> value = entry.getValue();
- result.put(entry.getKey(), value.getValue());
+ result.put(entry.getKey(), translate(value.getValue()));
}
return result;
}
+ private String translate(String value) {
+ if (locale == null || value == null || !value.startsWith("%"))
+ return value;
+ String localizationStr = subsystem.getSubsystemManifest().getSubsystemLocalizationHeader().getValue();
+ File rootDir;
+ File localizationFile;
+ try {
+ rootDir = subsystem.getDirectory().getCanonicalFile();
+ localizationFile = new File(rootDir, localizationStr).getCanonicalFile();
+ }
+ catch (IOException e) {
+ // TODO Log this. Particularly a problem if rootDir throws an
+ // exception as corruption has occurred. May want to let that
+ // propagate as a runtime exception.
+ return value;
+ }
+ URI rootUri = rootDir.toURI();
+ // The last segment of the Subsystem-Localization header value is the
+ // base file name. The directory is its parent.
+ URI localizationUri = localizationFile.getParentFile().toURI();
+ if (rootUri.relativize(localizationUri).equals(localizationUri))
+ // TODO Log this. The value of the Subsystem-Localization header
+ // is not relative to the subsystem root directory.
+ return value;
+ URL localizationUrl;
+ try {
+ localizationUrl = localizationUri.toURL();
+ }
+ catch (MalformedURLException e) {
+ // TODO Should never happen but log it anyway.
+ return value;
+ }
+ URLClassLoader classLoader = new URLClassLoader(new URL[]{localizationUrl});
+ try {
+ ResourceBundle rb = ResourceBundle.getBundle(localizationFile.getName(), locale, classLoader);
+ return rb.getString(value.substring(1));
+ }
+ catch (Exception e) {
+ return value;
+ }
+ }
}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/InstallAction.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/InstallAction.java
index e0ac215..544d16e 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/InstallAction.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/InstallAction.java
@@ -13,19 +13,16 @@
*/
package org.apache.aries.subsystem.core.internal;
+import java.io.InputStream;
import java.io.IOException;
-import java.net.URISyntaxException;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.PrivilegedAction;
import org.apache.aries.util.filesystem.ICloseableDirectory;
import org.apache.aries.util.filesystem.IDirectory;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.InvalidSyntaxException;
import org.osgi.service.coordinator.Coordination;
import org.osgi.service.coordinator.CoordinationException;
-import org.osgi.service.resolver.ResolutionException;
import org.osgi.service.subsystem.SubsystemException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -33,15 +30,17 @@
public class InstallAction implements PrivilegedAction<BasicSubsystem> {
private final IDirectory content;
private final AccessControlContext context;
+ private final InputStream deploymentManifest;
private final String location;
private final BasicSubsystem parent;
private static final Logger logger = LoggerFactory.getLogger(InstallAction.class);
- public InstallAction(String location, IDirectory content, BasicSubsystem parent, AccessControlContext context) {
+ public InstallAction(String location, IDirectory content, BasicSubsystem parent, AccessControlContext context, InputStream deploymentManifest) {
this.location = location;
this.content = content;
this.parent = parent;
this.context = context;
+ this.deploymentManifest = deploymentManifest;
}
@Override
@@ -52,7 +51,7 @@
BasicSubsystem result = null;
try {
TargetRegion region = new TargetRegion(parent);
- SubsystemResource ssr = createSubsystemResource(location, content, parent);
+ SubsystemResource ssr = new SubsystemResource(location, content, parent);
result = Activator.getInstance().getSubsystems().getSubsystemByLocation(location);
if (result != null) {
checkLifecyclePermission(result);
@@ -73,7 +72,7 @@
throw new SubsystemException("Subsystem already exists in target region but has a different type: " + location);
return (BasicSubsystem)ResourceInstaller.newInstance(coordination, result, parent).install();
}
- result = createSubsystem(ssr);
+ result = new BasicSubsystem(ssr, deploymentManifest);
checkLifecyclePermission(result);
return (BasicSubsystem)ResourceInstaller.newInstance(coordination, result, parent).install();
}
@@ -96,7 +95,6 @@
closeContentIfIClosable();
}
}
- closeContentIfIClosable();
return result;
}
@@ -123,15 +121,4 @@
},
context);
}
-
- private BasicSubsystem createSubsystem(SubsystemResource resource) throws URISyntaxException, IOException, BundleException, InvalidSyntaxException {
- final BasicSubsystem result = new BasicSubsystem(resource);
- return result;
-
- }
-
- private SubsystemResource createSubsystemResource(String location, IDirectory content, BasicSubsystem parent) throws URISyntaxException, IOException, ResolutionException, BundleException, InvalidSyntaxException {
- final SubsystemResource result = new SubsystemResource(location, content, parent);
- return result;
- }
}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/LocalRepository.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/LocalRepository.java
index e17558f..801a8a8 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/LocalRepository.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/LocalRepository.java
@@ -21,9 +21,8 @@
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
-import org.osgi.service.repository.Repository;
-public class LocalRepository implements Repository {
+public class LocalRepository implements org.apache.aries.subsystem.core.repository.Repository {
private final Collection<Resource> resources;
public LocalRepository(Collection<Resource> resources) {
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/PreferredProviderRepository.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/PreferredProviderRepository.java
index 39f4a10..dd71a73 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/PreferredProviderRepository.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/PreferredProviderRepository.java
@@ -25,29 +25,28 @@
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
-import org.osgi.service.repository.Repository;
-public class PreferredProviderRepository implements Repository {
+public class PreferredProviderRepository implements org.apache.aries.subsystem.core.repository.Repository {
// @GuardedBy("this")
private boolean initialized;
- private final Repository localRepository;
- private final Repository repositoryServiceRepository = new RepositoryServiceRepository();
+ private final org.apache.aries.subsystem.core.repository.Repository repositoryServiceRepository = new RepositoryServiceRepository();
private final SubsystemResource resource;
private final Collection<Resource> resources = new HashSet<Resource>();
- private final Repository systemRepository = Activator.getInstance().getSystemRepository();
+ private final org.apache.aries.subsystem.core.repository.Repository systemRepository = Activator.getInstance().getSystemRepository();
public PreferredProviderRepository(SubsystemResource resource) {
this.resource = resource;
- localRepository = resource.getLocalRepository();
}
@Override
public Map<Requirement, Collection<Capability>> findProviders(
Collection<? extends Requirement> requirements) {
synchronized (this) {
- if (!initialized)
+ if (!initialized) {
initialize();
+ initialized = true;
+ }
}
Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
for (Requirement requirement : requirements)
@@ -56,10 +55,10 @@
}
private boolean addLocalRepositoryProviders(Requirement requirement) {
- return addProviders(requirement, localRepository, false);
+ return addProviders(requirement, resource.getLocalRepository(), false);
}
- private boolean addProviders(Requirement requirement, Repository repository, boolean checkValid) {
+ private boolean addProviders(Requirement requirement, org.apache.aries.subsystem.core.repository.Repository repository, boolean checkValid) {
Map<Requirement, Collection<Capability>> map = repository.findProviders(Collections.singleton(requirement));
Collection<Capability> capabilities = map.get(requirement);
if (capabilities == null || capabilities.isEmpty())
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RawSubsystemResource.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RawSubsystemResource.java
index 117de15..67791e5 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RawSubsystemResource.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RawSubsystemResource.java
@@ -15,6 +15,7 @@
import java.io.File;
import java.io.IOException;
+import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.ArrayList;
@@ -25,6 +26,7 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Properties;
import java.util.jar.Manifest;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -39,6 +41,7 @@
import org.apache.aries.subsystem.core.archive.SubsystemContentHeader;
import org.apache.aries.subsystem.core.archive.SubsystemContentHeader.Clause;
import org.apache.aries.subsystem.core.archive.SubsystemImportServiceHeader;
+import org.apache.aries.subsystem.core.archive.SubsystemLocalizationHeader;
import org.apache.aries.subsystem.core.archive.SubsystemManifest;
import org.apache.aries.subsystem.core.archive.SubsystemSymbolicNameHeader;
import org.apache.aries.subsystem.core.archive.SubsystemTypeHeader;
@@ -58,7 +61,6 @@
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
-import org.osgi.service.repository.Repository;
import org.osgi.service.resolver.ResolutionException;
import org.osgi.service.subsystem.Subsystem.State;
import org.osgi.service.subsystem.SubsystemConstants;
@@ -108,13 +110,14 @@
private final List<Capability> capabilities;
private final DeploymentManifest deploymentManifest;
private final long id;
- private final Repository localRepository;
+ private final org.apache.aries.subsystem.core.repository.Repository localRepository;
private final Location location;
private final BasicSubsystem parentSubsystem;
private final List<Requirement> requirements;
private final Collection<Resource> resources;
private final Resource fakeImportServiceResource;
private final SubsystemManifest subsystemManifest;
+ private final Collection<TranslationFile> translations;
public RawSubsystemResource(String location, IDirectory content, BasicSubsystem parent) throws URISyntaxException, IOException, ResolutionException {
id = SubsystemIdentifier.getNextId();
@@ -132,6 +135,7 @@
subsystemManifest = computeSubsystemManifestAfterRequirements(manifest);
capabilities = computeCapabilities();
deploymentManifest = computeDeploymentManifest(content);
+ translations = computeTranslations(content);
}
finally {
IOUtils.close(content.toCloseable());
@@ -153,6 +157,7 @@
id = Long.parseLong(deploymentManifest.getHeaders().get(DeploymentManifest.ARIESSUBSYSTEM_ID).getValue());
location = new Location(deploymentManifest.getHeaders().get(DeploymentManifest.ARIESSUBSYSTEM_LOCATION).getValue());
parentSubsystem = parent;
+ translations = Collections.emptyList();
}
private static Resource createFakeResource(SubsystemManifest manifest) {
@@ -232,7 +237,7 @@
return id;
}
- public Repository getLocalRepository() {
+ public org.apache.aries.subsystem.core.repository.Repository getLocalRepository() {
return localRepository;
}
@@ -252,14 +257,14 @@
return Collections.unmodifiableList(result);
}
- public Collection<Resource> getResources() {
- return Collections.unmodifiableCollection(resources);
- }
-
public SubsystemManifest getSubsystemManifest() {
return subsystemManifest;
}
+ public Collection<TranslationFile> getTranslations() {
+ return translations;
+ }
+
@Override
public int hashCode() {
int result = 17;
@@ -331,7 +336,7 @@
return new ImportPackageHeader(clauses);
}
- private Repository computeLocalRepository() {
+ private org.apache.aries.subsystem.core.repository.Repository computeLocalRepository() {
if (fakeImportServiceResource != null) {
Collection<Resource> temp = new ArrayList<Resource>(resources);
temp.add(fakeImportServiceResource);
@@ -374,23 +379,34 @@
}
private List<Requirement> computeRequirements(SubsystemManifest manifest) throws ResolutionException {
- if (isComposite(manifest))
+ if (isComposite(manifest)) {
+ // Composites determine their own requirements.
return manifest.toRequirements(this);
+ }
+ // Gather up all of the content resources for the subsystem.
SubsystemContentHeader header = manifest.getSubsystemContentHeader();
- if (header == null)
+ if (header == null) {
+ // Empty subsystems (i.e. subsystems with no content) are allowed.
return Collections.emptyList();
- // TODO Need the system repository in here. Preferred provider as well?
- LocalRepository localRepo = new LocalRepository(resources);
- RepositoryServiceRepository serviceRepo = new RepositoryServiceRepository(Activator.getInstance().getBundleContext());
- CompositeRepository compositeRepo = new CompositeRepository(localRepo, serviceRepo);
+ }
List<Requirement> requirements = header.toRequirements(this);
List<Resource> resources = new ArrayList<Resource>(requirements.size());
+ // TODO Do we need the system repository in here (e.g., for features)?
+ // What about the preferred provider repository?
+ // Search the local repository and service repositories for content.
+ RepositoryServiceRepository serviceRepo = new RepositoryServiceRepository();
+ // TODO Should we search the service repositories first, the assumption
+ // being they will contain more current content than the subsystem
+ // archive?
+ CompositeRepository compositeRepo = new CompositeRepository(localRepository, serviceRepo);
for (Requirement requirement : requirements) {
Collection<Capability> capabilities = compositeRepo.findProviders(requirement);
- if (capabilities.isEmpty())
- continue;
- resources.add(capabilities.iterator().next().getResource());
+ if (!capabilities.isEmpty()) {
+ resources.add(capabilities.iterator().next().getResource());
+ }
}
+ // Now compute the dependencies of the content resources. These are
+ // dependencies not satisfied by the content resources themselves.
return new DependencyCalculator(resources).calculateDependencies();
}
@@ -523,6 +539,33 @@
return header;
}
+ private Collection<TranslationFile> computeTranslations(IDirectory directory) throws IOException {
+ SubsystemManifest manifest = getSubsystemManifest();
+ SubsystemLocalizationHeader header = manifest.getSubsystemLocalizationHeader();
+ String directoryName = header.getDirectoryName();
+ // TODO Assumes the ZIP file includes directory entries. Issues?
+ IFile file = directoryName == null ? directory : directory.getFile(directoryName);
+ if (file == null || !file.isDirectory())
+ return Collections.emptyList();
+ List<IFile> files = file.convert().listFiles();
+ if (files == null || files.isEmpty())
+ return Collections.emptyList();
+ ArrayList<TranslationFile> result = new ArrayList<TranslationFile>(files.size());
+ for (IFile f : files) {
+ Properties properties = new Properties();
+ InputStream is = f.open();
+ try {
+ properties.load(is);
+ result.add(new TranslationFile(f.getName(), properties));
+ }
+ finally {
+ is.close();
+ }
+ }
+ result.trimToSize();
+ return result;
+ }
+
private DeploymentManifest initializeDeploymentManifest(IDirectory idir)
throws IOException {
Manifest manifest = ManifestProcessor.obtainManifestFromAppDir(idir,
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RepositoryServiceRepository.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RepositoryServiceRepository.java
index 5772e25..7eba8e1 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RepositoryServiceRepository.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/RepositoryServiceRepository.java
@@ -13,6 +13,7 @@
*/
package org.apache.aries.subsystem.core.internal;
+import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -25,34 +26,41 @@
import org.osgi.framework.ServiceReference;
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
-import org.osgi.service.repository.Repository;
+import org.osgi.service.subsystem.SubsystemException;
-public class RepositoryServiceRepository implements Repository {
- private final BundleContext context;
+public class RepositoryServiceRepository implements org.apache.aries.subsystem.core.repository.Repository {
+ private BundleContext context;
public RepositoryServiceRepository() {
- this(Activator.getInstance().getBundleContext());
+ context = Activator.getInstance().getBundleContext();
}
- public RepositoryServiceRepository(BundleContext context) {
- this.context = context;
- }
-
+ @SuppressWarnings("unchecked")
public Collection<Capability> findProviders(Requirement requirement) {
Set<Capability> result = new HashSet<Capability>();
- Collection<ServiceReference<Repository>> references;
+ ServiceReference<?>[] references;
try {
- references = context.getServiceReferences(Repository.class, null);
+ references = context.getAllServiceReferences("org.osgi.service.repository.Repository", null);
+ if (references == null)
+ return result;
}
catch (InvalidSyntaxException e) {
throw new IllegalStateException(e);
}
- for (ServiceReference<Repository> reference : references) {
- Repository repository = context.getService(reference);
+ for (ServiceReference<?> reference : references) {
+ Object repository = context.getService(reference);
+ if (repository == null)
+ continue;
try {
- if (repository == null)
- continue;
- Map<Requirement, Collection<Capability>> map = repository.findProviders(Collections.singleton(requirement));
+ Class<?> clazz = repository.getClass();
+ Map<Requirement, Collection<Capability>> map;
+ try {
+ Method method = clazz.getMethod("findProviders", Collection.class);
+ map = (Map<Requirement, Collection<Capability>>)method.invoke(repository, Collections.singleton(requirement));
+ }
+ catch (Exception e) {
+ throw new SubsystemException(e);
+ }
Collection<Capability> capabilities = map.get(requirement);
if (capabilities == null)
continue;
@@ -66,13 +74,10 @@
}
@Override
- public Map<Requirement, Collection<Capability>> findProviders(
- Collection<? extends Requirement> requirements) {
+ public Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements) {
Map<Requirement, Collection<Capability>> result = new HashMap<Requirement, Collection<Capability>>();
for (Requirement requirement : requirements)
result.put(requirement, findProviders(requirement));
return result;
-
-
}
}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResolveContext.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResolveContext.java
new file mode 100755
index 0000000..afa6f29
--- /dev/null
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResolveContext.java
@@ -0,0 +1,245 @@
+/*
+ * 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.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.aries.subsystem.core.internal.BundleResourceInstaller.BundleConstituent;
+import org.apache.aries.subsystem.core.internal.DependencyCalculator.MissingCapability;
+import org.apache.aries.subsystem.core.repository.Repository;
+import org.eclipse.equinox.region.Region;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.namespace.NativeNamespace;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Namespace;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wiring;
+import org.osgi.service.resolver.HostedCapability;
+import org.osgi.service.subsystem.SubsystemException;
+
+public class ResolveContext extends org.osgi.service.resolver.ResolveContext {
+ private final Repository contentRepository;
+ private final Repository localRepository;
+ private final Repository preferredProviderRepository;
+ private final Repository repositoryServiceRepository;
+ private final SubsystemResource resource;
+ private final Repository systemRepository;
+ private final Map<Resource, Wiring> wirings = computeWirings();
+
+ public ResolveContext(SubsystemResource resource) {
+ this.resource = resource;
+ contentRepository = new ContentRepository(resource.getInstallableContent(), resource.getSharedContent());
+ localRepository = resource.getLocalRepository();
+ preferredProviderRepository = new PreferredProviderRepository(resource);
+ repositoryServiceRepository = new RepositoryServiceRepository();
+ systemRepository = Activator.getInstance().getSystemRepository();
+ }
+
+ @Override
+ public List<Capability> findProviders(Requirement requirement) {
+ ArrayList<Capability> result = new ArrayList<Capability>();
+ try {
+ // Only check the system repository for osgi.ee and osgi.native
+ if (ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE.equals(requirement.getNamespace())
+ || NativeNamespace.NATIVE_NAMESPACE.equals(requirement.getNamespace())) {
+ addDependenciesFromSystemRepository(requirement, result);
+ } else {
+ addDependenciesFromContentRepository(requirement, result);
+ addDependenciesFromPreferredProviderRepository(requirement, result);
+ addDependenciesFromSystemRepository(requirement, result);
+ addDependenciesFromLocalRepository(requirement, result);
+ if (result.isEmpty()) {
+ addDependenciesFromRepositoryServiceRepositories(requirement, result);
+ }
+ }
+ if (result.isEmpty()) {
+ // Is the requirement optional?
+ String resolution = requirement.getDirectives().get(Namespace.REQUIREMENT_RESOLUTION_DIRECTIVE);
+ if (Namespace.RESOLUTION_OPTIONAL.equals(resolution)) {
+ // Yes, it's optional. Add a missing capability to ensure
+ // it gets added to the sharing policy per the specification.
+ result.add(new MissingCapability(requirement));
+ }
+ }
+ }
+ catch (Throwable t) {
+ if (t instanceof SubsystemException)
+ throw (SubsystemException)t;
+ if (t instanceof SecurityException)
+ throw (SecurityException)t;
+ throw new SubsystemException(t);
+ }
+ result.trimToSize();
+ return result;
+ }
+
+ @Override
+ public int insertHostedCapability(List<Capability> capabilities, HostedCapability hostedCapability) {
+ capabilities.add(hostedCapability);
+ return capabilities.size() - 1;
+ }
+
+ @Override
+ public boolean isEffective(Requirement requirement) {
+ return true;
+ }
+
+ @Override
+ public Collection<Resource> getMandatoryResources() {
+ return resource.getMandatoryResources();
+ }
+
+ @Override
+ public Collection<Resource> getOptionalResources() {
+ return resource.getOptionalResources();
+ }
+
+ @Override
+ public Map<Resource, Wiring> getWirings() {
+ return wirings;
+ }
+
+ private boolean addDependencies(Repository repository, Requirement requirement, List<Capability> capabilities, boolean validate) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+ if (repository == null)
+ return false;
+ Map<Requirement, Collection<Capability>> m = repository.findProviders(Collections.singleton(requirement));
+ if (m.containsKey(requirement)) {
+ Collection<Capability> cc = m.get(requirement);
+ addValidCapabilities(cc, capabilities, requirement, validate);
+ }
+ return !capabilities.isEmpty();
+ }
+
+ private boolean addDependenciesFromContentRepository(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+ return addDependencies(contentRepository, requirement, capabilities, false);
+ }
+
+ private boolean addDependenciesFromLocalRepository(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+ return addDependencies(localRepository, requirement, capabilities, true);
+ }
+
+ private boolean addDependenciesFromPreferredProviderRepository(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+ return addDependencies(preferredProviderRepository, requirement, capabilities, true);
+ }
+
+ private boolean addDependenciesFromRepositoryServiceRepositories(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+ return addDependencies(repositoryServiceRepository, requirement, capabilities, true);
+ }
+
+ private boolean addDependenciesFromSystemRepository(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+ return addDependencies(systemRepository, requirement, capabilities, true);
+ }
+
+ private void addValidCapabilities(Collection<Capability> from, Collection<Capability> to, Requirement requirement, boolean validate) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+ for (Capability c : from) {
+ if (!validate || isValid(c, requirement)) {
+ // either validation is not requested or the capability is valid.
+ to.add(c);
+ }
+ }
+ }
+
+ private void addWiring(Resource resource, Map<Resource, Wiring> wirings) {
+ if (resource instanceof BundleConstituent) {
+ BundleConstituent bc = (BundleConstituent)resource;
+ wirings.put(bc.getBundle().adapt(BundleRevision.class), bc.getWiring());
+ }
+ else if (resource instanceof BundleRevision) {
+ BundleRevision br = (BundleRevision)resource;
+ wirings.put(br, br.getWiring());
+ }
+ }
+
+ private Map<Resource, Wiring> computeWirings() {
+ Map<Resource, Wiring> wirings = new HashMap<Resource, Wiring>();
+ for (BasicSubsystem subsystem : Activator.getInstance().getSubsystems().getSubsystems()) { // NEED
+ for (Resource constituent : subsystem.getConstituents()) {
+ addWiring(constituent, wirings);
+ }
+ }
+ return Collections.unmodifiableMap(wirings);
+ }
+
+ private Region findRegionForCapabilityValidation(Resource resource) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+ if (isInstallable(resource)) {
+ // This is an installable resource so we need to figure out where it
+ // will be installed.
+ if (isContent(resource) // If the resource is content of this subsystem, it will be installed here.
+ // Or if this subsystem accepts dependencies, the resource will be installed here.
+ || this.resource.getSubsystemManifest().getSubsystemTypeHeader().getProvisionPolicyDirective().isAcceptDependencies()) {
+ if (this.resource.isComposite()) {
+ // Composites define their own sharing policy with which
+ // their regions are already configured by the time we get
+ // here. We ensure capabilities are visible to this region.
+ return this.resource.getRegion();
+ }
+ // For applications and features, we must ensure capabilities
+ // are visible to their scoped parent. Features import
+ // everything. Applications have their sharing policies
+ // computed, so if capabilities are visible to the parent, we
+ // know we can make them visible to the application.
+ return this.resource.getParents().iterator().next().getRegion();
+ }
+ // Same reasoning as above applies here.
+ if (this.resource.isComposite() && this.resource.getSubsystemManifest().getSubsystemTypeHeader().getProvisionPolicyDirective().isAcceptDependencies()) {
+ return this.resource.getRegion();
+ }
+ return Utils.findFirstSubsystemAcceptingDependenciesStartingFrom(this.resource.getParents().iterator().next()).getRegion();
+ }
+ else {
+ // This is an already installed resource from the system repository.
+ if (Utils.isBundle(resource))
+ // If it's a bundle, use region digraph to get the region in order
+ // to account for bundles in isolated regions outside of the
+ // subsystems API.
+ return Activator.getInstance().getRegionDigraph().getRegion(((BundleRevision)resource).getBundle());
+ else
+ // If it's anything else, get the region from one of the
+ // subsystems referencing it.
+ return Activator.getInstance().getSubsystems().getSubsystemsReferencing(resource).iterator().next().getRegion();
+ }
+ }
+
+ private boolean isContent(Resource resource) {
+ return this.resource.getSubsystemManifest().getSubsystemContentHeader().contains(resource);
+ }
+
+ private boolean isInstallable(Resource resource) {
+ return !isShared(resource);
+ }
+
+ private boolean isShared(Resource resource) {
+ return Utils.isSharedResource(resource);
+ }
+
+ private boolean isValid(Capability capability, Requirement requirement) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
+ if (IdentityNamespace.IDENTITY_NAMESPACE.equals(capability.getNamespace()))
+ return true;
+ Region from = findRegionForCapabilityValidation(capability.getResource());
+ Region to = findRegionForCapabilityValidation(requirement.getResource());
+ return new SharingPolicyValidator(from, to).isValid(capability);
+ }
+}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceHelper.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceHelper.java
index 5bca709..92d0bb8 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceHelper.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/ResourceHelper.java
@@ -34,7 +34,6 @@
import org.osgi.resource.Namespace;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
-import org.osgi.service.repository.Repository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -84,7 +83,7 @@
return getSymbolicNameAttribute(resource) + '@' + getVersionAttribute(resource);
}
- public static Resource getResource(Requirement requirement, Repository repository) {
+ public static Resource getResource(Requirement requirement, org.apache.aries.subsystem.core.repository.Repository repository) {
Map<Requirement, Collection<Capability>> map = repository.findProviders(Arrays.asList(requirement));
Collection<Capability> capabilities = map.get(requirement);
return capabilities == null ? null : capabilities.size() == 0 ? null : capabilities.iterator().next().getResource();
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartAction.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartAction.java
index 298c4ad..92fffa0 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartAction.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/StartAction.java
@@ -59,15 +59,25 @@
private final Coordination coordination;
private final BasicSubsystem instigator;
+ private final boolean resolveOnly;
public StartAction(BasicSubsystem instigator, BasicSubsystem requestor, BasicSubsystem target) {
- this(instigator, requestor, target, null);
+ this(instigator, requestor, target, false);
}
+ public StartAction(BasicSubsystem instigator, BasicSubsystem requestor, BasicSubsystem target, boolean resolveOnly) {
+ this(instigator, requestor, target, null, resolveOnly);
+ }
+
public StartAction(BasicSubsystem instigator, BasicSubsystem requestor, BasicSubsystem target, Coordination coordination) {
+ this(instigator, requestor, target, coordination, false);
+ }
+
+ public StartAction(BasicSubsystem instigator, BasicSubsystem requestor, BasicSubsystem target, Coordination coordination, boolean resolveOnly) {
super(requestor, target, false);
this.instigator = instigator;
this.coordination = coordination;
+ this.resolveOnly = resolveOnly;
}
@Override
@@ -104,6 +114,8 @@
// Resolve if necessary.
if (State.INSTALLED.equals(state))
resolve(target);
+ if (resolveOnly)
+ return null;
target.setState(State.STARTING);
// TODO Need to hold a lock here to guarantee that another start
// operation can't occur when the state goes to RESOLVED.
@@ -284,7 +296,7 @@
String filter = capability.getDirectives().get(SubsystemExportServiceCapability.DIRECTIVE_FILTER);
if (logger.isDebugEnabled())
logger.debug("Allowing " + policy + " of " + filter);
- builder.allow(policy, filter.toString());
+ builder.allow(policy, filter);
}
}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResource.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResource.java
index b0c1d2a..eb85fcd 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResource.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResource.java
@@ -19,7 +19,6 @@
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -40,7 +39,6 @@
import org.apache.aries.subsystem.core.archive.SubsystemImportServiceHeader;
import org.apache.aries.subsystem.core.archive.SubsystemImportServiceRequirement;
import org.apache.aries.subsystem.core.archive.SubsystemManifest;
-import org.apache.aries.subsystem.core.internal.BundleResourceInstaller.BundleConstituent;
import org.apache.aries.util.filesystem.FileSystem;
import org.apache.aries.util.filesystem.IDirectory;
import org.apache.aries.util.manifest.ManifestHeaderProcessor;
@@ -56,16 +54,16 @@
import org.osgi.framework.hooks.weaving.WeavingHook;
import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.namespace.NativeNamespace;
import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.namespace.service.ServiceNamespace;
import org.osgi.resource.Capability;
+import org.osgi.resource.Namespace;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
import org.osgi.resource.Wire;
-import org.osgi.resource.Wiring;
import org.osgi.service.coordinator.Coordination;
import org.osgi.service.coordinator.Participant;
-import org.osgi.service.repository.Repository;
-import org.osgi.service.resolver.HostedCapability;
import org.osgi.service.resolver.ResolutionException;
import org.osgi.service.resolver.ResolveContext;
import org.osgi.service.subsystem.Subsystem;
@@ -83,7 +81,6 @@
private final Collection<DeployedContentHeader.Clause> missingResources = new HashSet<DeployedContentHeader.Clause>();
private final Collection<Resource> optionalResources = new HashSet<Resource>();
private final BasicSubsystem parent;
- private final Repository preferredProviderRepository;
private final RawSubsystemResource resource;
private final Collection<Resource> sharedContent = new HashSet<Resource>();
private final Collection<Resource> sharedDependencies = new HashSet<Resource>();
@@ -95,7 +92,6 @@
public SubsystemResource(RawSubsystemResource resource, BasicSubsystem parent) throws IOException, BundleException, InvalidSyntaxException, URISyntaxException {
this.parent = parent;
this.resource = resource;
- preferredProviderRepository = new PreferredProviderRepository(this);
computeContentResources(resource.getDeploymentManifest());
capabilities = computeCapabilities();
computeDependencies(resource.getDeploymentManifest());
@@ -109,7 +105,6 @@
public SubsystemResource(IDirectory directory) throws IOException, URISyntaxException, ResolutionException, BundleException, InvalidSyntaxException {
parent = null;
resource = new RawSubsystemResource(directory, parent);
- preferredProviderRepository = null;
deploymentManifest = resource.getDeploymentManifest();
computeContentResources(deploymentManifest);
capabilities = computeCapabilities();
@@ -175,7 +170,7 @@
return installableDependencies;
}
- public Repository getLocalRepository() {
+ public org.apache.aries.subsystem.core.repository.Repository getLocalRepository() {
return resource.getLocalRepository();
}
@@ -183,10 +178,18 @@
return resource.getLocation().getValue();
}
+ Collection<Resource> getMandatoryResources() {
+ return mandatoryResources;
+ }
+
public Collection<DeployedContentHeader.Clause> getMissingResources() {
return missingResources;
}
+ Collection<Resource> getOptionalResources() {
+ return optionalResources;
+ }
+
public Collection<BasicSubsystem> getParents() {
if (parent == null) {
Header<?> header = getDeploymentManifest().getHeaders().get(DeploymentManifest.ARIESSUBSYSTEM_PARENTS);
@@ -217,7 +220,9 @@
region.getRegionDigraph().removeRegion(region);
}
});
- setImportIsolationPolicy();
+ if (!isApplication()) {
+ setImportIsolationPolicy();
+ }
}
return region;
}
@@ -236,10 +241,6 @@
}
}
- public Collection<Resource> getResources() {
- return resource.getResources();
- }
-
public Collection<Resource> getSharedContent() {
return sharedContent;
}
@@ -252,6 +253,10 @@
return resource.getSubsystemManifest();
}
+ public Collection<TranslationFile> getTranslations() {
+ return resource.getTranslations();
+ }
+
@Override
public int hashCode() {
int result = 17;
@@ -272,43 +277,6 @@
sharedContent.add(resource);
}
- private boolean addDependencies(Repository repository, Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
- if (repository == null)
- return false;
- Map<Requirement, Collection<Capability>> m = repository.findProviders(Collections.singleton(requirement));
- if (m.containsKey(requirement)) {
- Collection<Capability> cc = m.get(requirement);
- // TODO The following check only needs to be done on capabilities from the system repository.
- addValidCapabilities(cc, capabilities, requirement);
- }
- return !capabilities.isEmpty();
- }
-
- private boolean addDependenciesFromContentRepository(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
- // TODO Why create this with each method call? What not cache it as an instance variable?
- Repository repository = new ContentRepository(installableContent, sharedContent);
- return addDependencies(repository, requirement, capabilities);
- }
-
- private boolean addDependenciesFromLocalRepository(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
- Repository repository = resource.getLocalRepository();
- return addDependencies(repository, requirement, capabilities);
- }
-
- private boolean addDependenciesFromPreferredProviderRepository(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
- return addDependencies(preferredProviderRepository, requirement, capabilities);
- }
-
- private boolean addDependenciesFromRepositoryServiceRepositories(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
- Repository repository = new RepositoryServiceRepository();
- return addDependencies(repository, requirement, capabilities);
- }
-
- private boolean addDependenciesFromSystemRepository(Requirement requirement, List<Capability> capabilities) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
- Repository repository = Activator.getInstance().getSystemRepository();
- return addDependencies(repository, requirement, capabilities);
- }
-
private void addDependency(Resource resource) {
if (resource == null)
return;
@@ -322,12 +290,6 @@
missingResources.add(resource);
}
- private void addValidCapabilities(Collection<Capability> from, Collection<Capability> to, Requirement requirement) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
- for (Capability c : from)
- if (isValid(c, requirement))
- to.add(c);
- }
-
private void addSubsystemServiceImportToSharingPolicy(
RegionFilterBuilder builder) throws InvalidSyntaxException, BundleException, IOException, URISyntaxException {
builder.allow(
@@ -404,10 +366,11 @@
}
}
- private void computeDependencies(SubsystemManifest manifest) {
+ private void computeDependencies(SubsystemManifest manifest) {
SubsystemContentHeader contentHeader = manifest.getSubsystemContentHeader();
try {
Map<Resource, List<Wire>> resolution = Activator.getInstance().getResolver().resolve(createResolveContext());
+ setImportIsolationPolicy(resolution);
for (Map.Entry<Resource, List<Wire>> entry : resolution.entrySet()) {
Resource key = entry.getKey();
if (!contentHeader.contains(key)) {
@@ -424,6 +387,15 @@
catch (ResolutionException e) {
throw new SubsystemException(e);
}
+ catch (Exception e) {
+ if (e instanceof SubsystemException) {
+ throw (SubsystemException)e;
+ }
+ if (e instanceof SecurityException) {
+ throw (SecurityException)e;
+ }
+ throw new SubsystemException(e);
+ }
}
private DeployedContentHeader computeDeployedContentHeader() {
@@ -480,86 +452,7 @@
}
private ResolveContext createResolveContext() {
- return new ResolveContext() {
- private final Map<Resource, Wiring> wirings = computeWirings();
-
- private Map<Resource, Wiring> computeWirings() {
- Map<Resource, Wiring> wirings = new HashMap<Resource, Wiring>();
- for (BasicSubsystem subsystem : Activator.getInstance().getSubsystems().getSubsystems())
- for (Resource constituent : subsystem.getConstituents())
- addWiring(constituent, wirings);
- return Collections.unmodifiableMap(wirings);
- }
-
- private void addWiring(Resource resource, Map<Resource, Wiring> wirings) {
- if (resource instanceof BundleConstituent) {
- BundleConstituent bc = (BundleConstituent)resource;
- wirings.put(bc.getBundle().adapt(BundleRevision.class), bc.getWiring());
- }
- else if (resource instanceof BundleRevision) {
- BundleRevision br = (BundleRevision)resource;
- wirings.put(br, br.getWiring());
- }
- }
-
- @Override
- public List<Capability> findProviders(Requirement requirement) {
- List<Capability> result = new ArrayList<Capability>();
- try {
- // Only check the system repository for osgi.ee and osgi.native
- if (ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE.equals(requirement.getNamespace())
- || DependencyCalculator.NATIVE_NAMESPACE.equals(requirement.getNamespace())) {
- addDependenciesFromSystemRepository(requirement, result);
- return result;
- }
- if (addDependenciesFromContentRepository(requirement, result))
- return result;
- if (addDependenciesFromPreferredProviderRepository(requirement, result))
- return result;
- if (addDependenciesFromSystemRepository(requirement, result))
- return result;
- if (addDependenciesFromLocalRepository(requirement, result))
- return result;
- if (addDependenciesFromRepositoryServiceRepositories(requirement, result))
- return result;
- }
- catch (Throwable t) {
- if (t instanceof SubsystemException)
- throw (SubsystemException)t;
- if (t instanceof SecurityException)
- throw (SecurityException)t;
- throw new SubsystemException(t);
- }
- return result;
- }
-
- @Override
- public Collection<Resource> getMandatoryResources() {
- return SubsystemResource.this.mandatoryResources;
- }
-
- @Override
- public Collection<Resource> getOptionalResources() {
- return SubsystemResource.this.optionalResources;
- }
-
- @Override
- public int insertHostedCapability(List<Capability> capabilities,
- HostedCapability hostedCapability) {
- capabilities.add(hostedCapability);
- return capabilities.size() - 1;
- }
-
- @Override
- public boolean isEffective(Requirement requirement) {
- return true;
- }
-
- @Override
- public synchronized Map<Resource, Wiring> getWirings() {
- return wirings;
- }
- };
+ return new org.apache.aries.subsystem.core.internal.ResolveContext(this);
}
private Resource findContent(Requirement requirement) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
@@ -647,10 +540,16 @@
return result;
}
- private boolean isContent(Resource resource) {
- return getSubsystemManifest().getSubsystemContentHeader().contains(resource);
+ boolean isApplication() {
+ String type = resource.getSubsystemManifest().getSubsystemTypeHeader().getType();
+ return SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(type);
}
+ boolean isComposite() {
+ String type = resource.getSubsystemManifest().getSubsystemTypeHeader().getType();
+ return SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(type);
+ }
+
private boolean isInstallable(Resource resource) {
return !isShared(resource);
}
@@ -662,7 +561,7 @@
return header.isMandatory(resource);
}
- private boolean isRoot() {
+ boolean isRoot() {
return BasicSubsystem.ROOT_LOCATION.equals(getLocation());
}
@@ -671,41 +570,58 @@
}
private boolean isScoped() {
- String type = resource.getSubsystemManifest().getSubsystemTypeHeader().getType();
- return SubsystemConstants.SUBSYSTEM_TYPE_APPLICATION.equals(type) ||
- SubsystemConstants.SUBSYSTEM_TYPE_COMPOSITE.equals(type);
+ return isApplication() || isComposite();
}
private boolean isUnscoped() {
return !isScoped();
}
- private boolean isValid(Capability capability, Requirement requirement) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
- if (IdentityNamespace.IDENTITY_NAMESPACE.equals(capability.getNamespace()))
- return true;
- Region from = findRegionForCapabilityValidation(capability.getResource());
- Region to = findRegionForCapabilityValidation(requirement.getResource());
- return new SharingPolicyValidator(from, to).isValid(capability);
- }
-
- private Region findRegionForCapabilityValidation(Resource resource) throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
- if (isInstallable(resource)) {
- if (isContent(resource))
- return getRegion();
- return Utils.findFirstSubsystemAcceptingDependenciesStartingFrom(parent).getRegion();
+ private void setImportIsolationPolicy(Map<Resource, List<Wire>> resolution) throws Exception {
+ if (!isApplication()) {
+ return;
}
- else {
- // This is an already installed resource from the system repository.
- if (Utils.isBundle(resource))
- // If it's a bundle, use region digraph to get the region in order
- // to account for bundles in isolated regions outside of the
- // subsystems API.
- return Activator.getInstance().getRegionDigraph().getRegion(((BundleRevision)resource).getBundle());
- else
- // If it's anything else, get the region from one of the
- // subsystems referencing it.
- return Activator.getInstance().getSubsystems().getSubsystemsReferencing(resource).iterator().next().getRegion();
+ SubsystemContentHeader contentHeader = getSubsystemManifest().getSubsystemContentHeader();
+ // Prepare the regions and filter builder to set the sharing policy.
+ Region from = getRegion();
+ Region to = ((BasicSubsystem)getParents().iterator().next()).getRegion();
+ RegionFilterBuilder builder = from.getRegionDigraph().createRegionFilterBuilder();
+ // Always provide visibility to this subsystem's service registration.
+ addSubsystemServiceImportToSharingPolicy(builder, to);
+ for (Resource resource : resolution.keySet()) {
+ // If the resource is content but the wire provider is not,
+ // the sharing policy must be updated.
+ List<Wire> wires = resolution.get(resource);
+ for (Wire wire : wires) {
+ Resource provider = wire.getProvider();
+ if (contentHeader.contains(provider)) {
+ // The provider is content so the requirement does
+ // not need to become part of the sharing policy.
+ continue;
+ }
+ // The provider is not content, so the requirement must
+ // be added to the sharing policy.
+ Requirement requirement = wire.getRequirement();
+ String namespace = requirement.getNamespace();
+ if (ServiceNamespace.SERVICE_NAMESPACE.equals(namespace)) {
+ // The osgi.service namespace must be translated to one
+ // that region digraph understands.
+ namespace = RegionFilter.VISIBLE_SERVICE_NAMESPACE;
+ }
+ String filter = requirement.getDirectives().get(Namespace.REQUIREMENT_FILTER_DIRECTIVE);
+ if (filter == null) {
+ builder.allowAll(namespace);
+ }
+ else {
+ builder.allow(namespace, filter);
+ }
+ }
}
+ // Always add access to osgi.ee and osgi.native namespaces
+ setImplicitAccessToNativeAndEECapabilities(builder);
+ // Now set the sharing policy, if the regions are different.
+ RegionFilter regionFilter = builder.build();
+ from.connectRegion(to, regionFilter);
}
private void setImportIsolationPolicy() throws BundleException, IOException, InvalidSyntaxException, URISyntaxException {
@@ -734,7 +650,6 @@
setImportIsolationPolicy(builder, (RequireBundleHeader)header);
// Always add access to osgi.ee and osgi.native namespaces
setImplicitAccessToNativeAndEECapabilities(builder);
-
}
RegionFilter regionFilter = builder.build();
from.connectRegion(to, regionFilter);
@@ -742,14 +657,6 @@
private void setImportIsolationPolicy(RegionFilterBuilder builder, ImportPackageHeader header) throws InvalidSyntaxException {
String policy = RegionFilter.VISIBLE_PACKAGE_NAMESPACE;
- // work around https://www.osgi.org/bugzilla/show_bug.cgi?id=144
- // In the first instance, what if the various weaving services were to have a property,
- // osgi.woven.packages, that was a comma separated list of packages that might be woven
- // by that hook.
- Collection<String> wovenPackages = getWovenPackages();
- for (String pkg : wovenPackages) {
- builder.allow(policy, "(osgi.wiring.package=" + pkg + ")");
- }
if (header == null)
return;
for (ImportPackageHeader.Clause clause : header.getClauses()) {
@@ -758,23 +665,7 @@
builder.allow(policy, filter);
}
}
-
- // First pass at this: really just a sketch.
- private Collection<String> getWovenPackages() throws InvalidSyntaxException
- {
- // Find all weaving services in our region
- BundleContext bc = Activator.getInstance().getBundleContext();
- Collection<ServiceReference<WeavingHook>> weavers = bc.getServiceReferences(WeavingHook.class, null);
- Collection<String> wovenPackages = new ArrayList<String>();
- for (ServiceReference<WeavingHook> sr : weavers) {
- String someWovenPackages = (String) sr.getProperty("osgi.woven.packages");
- if (someWovenPackages != null) {
- wovenPackages.addAll(ManifestHeaderProcessor.split(someWovenPackages, ","));
- }
- }
- return wovenPackages;
- }
-
+
private void setImportIsolationPolicy(RegionFilterBuilder builder, RequireBundleHeader header) throws InvalidSyntaxException {
if (header == null)
return;
@@ -803,10 +694,9 @@
}
}
-
private void setImplicitAccessToNativeAndEECapabilities(RegionFilterBuilder builder) {
builder.allowAll(ExecutionEnvironmentNamespace.EXECUTION_ENVIRONMENT_NAMESPACE);
- builder.allowAll(DependencyCalculator.NATIVE_NAMESPACE);
+ builder.allowAll(NativeNamespace.NATIVE_NAMESPACE);
}
private void setImportIsolationPolicy(RegionFilterBuilder builder, SubsystemImportServiceHeader header) throws InvalidSyntaxException {
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceInstaller.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceInstaller.java
index c6f1e6a..04a6465 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceInstaller.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SubsystemResourceInstaller.java
@@ -13,6 +13,8 @@
*/
package org.apache.aries.subsystem.core.internal;
+import java.io.InputStream;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -22,7 +24,6 @@
import org.osgi.resource.Resource;
import org.osgi.service.coordinator.Coordination;
import org.osgi.service.coordinator.Participant;
-import org.osgi.service.repository.RepositoryContent;
import org.osgi.service.subsystem.Subsystem.State;
public class SubsystemResourceInstaller extends ResourceInstaller {
@@ -31,16 +32,15 @@
}
public Resource install() throws Exception {
- BasicSubsystem result;
- if (resource instanceof RepositoryContent)
- result = installRepositoryContent((RepositoryContent)resource);
- else if (resource instanceof BasicSubsystem)
- result = installAriesSubsystem((BasicSubsystem)resource);
+ if (resource instanceof BasicSubsystem)
+ return installAriesSubsystem((BasicSubsystem)resource);
else if (resource instanceof RawSubsystemResource)
- result = installRawSubsystemResource((RawSubsystemResource)resource);
- else
- result = installSubsystemResource((SubsystemResource)resource);
- return result;
+ return installRawSubsystemResource((RawSubsystemResource)resource);
+ else if (resource instanceof SubsystemResource)
+ return installSubsystemResource((SubsystemResource)resource);
+ else {
+ return installRepositoryContent(resource);
+ }
}
private void addChild(final BasicSubsystem child) {
@@ -147,8 +147,10 @@
});
}
- private BasicSubsystem installRepositoryContent(RepositoryContent resource) throws Exception {
- RawSubsystemResource rawSubsystemResource = new RawSubsystemResource(getLocation(), FileSystem.getFSRoot(resource.getContent()), subsystem);
+ private BasicSubsystem installRepositoryContent(Resource resource) throws Exception {
+ Method method = resource.getClass().getMethod("getContent");
+ InputStream is = (InputStream)method.invoke(resource);
+ RawSubsystemResource rawSubsystemResource = new RawSubsystemResource(getLocation(), FileSystem.getFSRoot(is), subsystem);
return installRawSubsystemResource(rawSubsystemResource);
}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SystemRepository.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SystemRepository.java
index a6e3d63..1345a4b 100644
--- a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SystemRepository.java
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/SystemRepository.java
@@ -21,9 +21,8 @@
import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;
-import org.osgi.service.repository.Repository;
-public class SystemRepository implements Repository {
+public class SystemRepository implements org.apache.aries.subsystem.core.repository.Repository {
private final BasicSubsystem root;
public SystemRepository(BasicSubsystem root) {
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/TranslationFile.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/TranslationFile.java
new file mode 100755
index 0000000..3b73c57
--- /dev/null
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/TranslationFile.java
@@ -0,0 +1,37 @@
+package org.apache.aries.subsystem.core.internal;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Properties;
+
+public class TranslationFile {
+ private static String normalizeName(String name) {
+ int index = name.lastIndexOf('/');
+ if (index == -1)
+ return name;
+ return name.substring(index + 1);
+ }
+
+ private final String name;
+ private final Properties properties;
+
+ public TranslationFile(String name, Properties properties) {
+ if (name == null || properties == null)
+ throw new NullPointerException();
+ if (name.isEmpty())
+ throw new IllegalArgumentException();
+ this.name = normalizeName(name);
+ this.properties = properties;
+ }
+
+ public void write(File directory) throws IOException {
+ FileOutputStream fos = new FileOutputStream(new File(directory, name));
+ try {
+ properties.store(fos, null);
+ }
+ finally {
+ fos.close();
+ }
+ }
+}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/WovenClassListener.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/WovenClassListener.java
new file mode 100755
index 0000000..7d49435
--- /dev/null
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/internal/WovenClassListener.java
@@ -0,0 +1,110 @@
+package org.apache.aries.subsystem.core.internal;
+
+import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.EnumSet;
+import java.util.List;
+
+import org.apache.aries.subsystem.core.archive.DynamicImportPackageHeader;
+import org.apache.aries.subsystem.core.archive.DynamicImportPackageRequirement;
+import org.apache.aries.subsystem.core.internal.BundleResourceInstaller.BundleConstituent;
+import org.eclipse.equinox.region.Region;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.hooks.weaving.WovenClass;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.FrameworkWiring;
+import org.osgi.resource.Requirement;
+import org.osgi.service.subsystem.Subsystem;
+import org.osgi.service.subsystem.SubsystemException;
+
+public class WovenClassListener implements org.osgi.framework.hooks.weaving.WovenClassListener {
+ private final BundleContext context;
+ private final Subsystems subsystems;
+
+ public WovenClassListener(BundleContext context, Subsystems subsystems) {
+ this.context = context;
+ this.subsystems = subsystems;
+ }
+
+ /*
+ * This does not update sharing policies up the chain any further than the
+ * parent. Does not account for providers in child subsystems.
+ */
+ @Override
+ public void modified(WovenClass wovenClass) {
+ if (wovenClass.getState() != WovenClass.TRANSFORMED) {
+ // Dynamic package imports must be added when the woven class is in
+ // the transformed state in order to ensure the class will load once
+ // the defined state is reached.
+ return;
+ }
+ List<String> dynamicImports = wovenClass.getDynamicImports();
+ if (dynamicImports.isEmpty()) {
+ // Nothing to do if there are no dynamic imports.
+ return;
+ }
+ // Add the dynamic imports to the sharing policy of the scoped subsystem
+ // that contains the bundle whose class was woven as a constituent.
+ Bundle wovenBundle = wovenClass.getBundleWiring().getBundle();
+ BundleRevision wovenRevision = wovenBundle.adapt(BundleRevision.class);
+ BasicSubsystem subsystem = subsystems.getSubsystemsByConstituent(new BundleConstituent(null, wovenRevision)).iterator().next();
+ if (subsystem.getSubsystemId() == 0) {
+ // The root subsystem needs no sharing policy.
+ return;
+ }
+ if (EnumSet.of(Subsystem.State.INSTALLING, Subsystem.State.INSTALLED).contains(subsystem.getState())) {
+ // The subsystem must be resolved before adding dynamic package
+ // imports to the sharing policy in order to minimize unpredictable
+ // wirings.
+ AccessController.doPrivileged(new StartAction(subsystem, subsystem, subsystem, true));
+ }
+ // Determine the requirements that must be added to the sharing policy.
+ Collection<Requirement> requirements = new ArrayList<Requirement>();
+ for (String dynamicImport : dynamicImports) {
+ DynamicImportPackageHeader header = new DynamicImportPackageHeader(dynamicImport);
+ for (DynamicImportPackageRequirement requirement : header.toRequirements(wovenRevision)) {
+ String pkg = requirement.getPackageName();
+ if (pkg.endsWith(".*")) {
+ // Dynamic imports with wildcards must always be added.
+ requirements.add(requirement);
+ }
+ else {
+ // Absolute dynamic imports are added to the sharing policy
+ // only if they are not satisfied within the subsystem.
+ FrameworkWiring fw = context.getBundle(org.osgi.framework.Constants.SYSTEM_BUNDLE_LOCATION).adapt(FrameworkWiring.class);
+ Collection<BundleCapability> providers = fw.findProviders(requirement);
+ boolean found = false;
+ for (BundleCapability provider : providers) {
+ BundleRevision br = provider.getResource();
+ if (subsystem.getConstituents().contains(new BundleConstituent(null, br))) {
+ // We found a provider that's a constituent of the subsystem.
+ found = true;
+ break;
+ }
+ }
+ if (!found) {
+ requirements.add(requirement);
+ }
+ }
+ }
+ }
+ if (requirements.isEmpty()) {
+ // No wildcards and all dynamic imports were satisfied within the
+ // subsystem.
+ return;
+ }
+ // Now update the sharing policy with the necessary requirements.
+ Region from = subsystem.getRegion();
+ Region to = ((BasicSubsystem)subsystem.getParents().iterator().next()).getRegion();
+ RegionUpdater updater = new RegionUpdater(from, to);
+ try {
+ updater.addRequirements(requirements);
+ }
+ catch (Exception e) {
+ throw new SubsystemException(e);
+ }
+ }
+}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/ContentNamespace.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/ContentNamespace.java
new file mode 100755
index 0000000..abbec78
--- /dev/null
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/ContentNamespace.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) OSGi Alliance (2011, 2012). 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.apache.aries.subsystem.core.repository;
+
+import org.osgi.resource.Namespace;
+
+/**
+ * Content Capability and Requirement Namespace.
+ *
+ * <p>
+ * This class defines the names for the attributes and directives for this
+ * namespace. All unspecified capability attributes are of type {@code String}
+ * and are used as arbitrary matching attributes for the capability. The values
+ * associated with the specified directive and attribute keys are of type
+ * {@code String}, unless otherwise indicated.
+ *
+ * @Immutable
+ * @version $Id$
+ */
+public final class ContentNamespace extends Namespace {
+
+ /**
+ * Namespace name for content capabilities and requirements.
+ *
+ * <p>
+ * Also, the capability attribute used to specify the unique identifier of
+ * the content. This identifier is the {@code SHA-256} hash of the content.
+ */
+ public static final String CONTENT_NAMESPACE = "osgi.content";
+
+ /**
+ * The capability attribute that contains the URL to the content.
+ */
+ public static final String CAPABILITY_URL_ATTRIBUTE = "url";
+
+ /**
+ * The capability attribute that contains the size, in bytes, of the
+ * content. The value of this attribute must be of type {@code Long}.
+ */
+ public static final String CAPABILITY_SIZE_ATTRIBUTE = "size";
+
+ /**
+ * The capability attribute that defines the IANA MIME Type/Format for this
+ * content.
+ */
+ public static final String CAPABILITY_MIME_ATTRIBUTE = "mime";
+
+ private ContentNamespace() {
+ // empty
+ }
+}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/Repository.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/Repository.java
new file mode 100755
index 0000000..6cd4fe4
--- /dev/null
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/Repository.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) OSGi Alliance (2006, 2012). 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.
+ */
+
+// This document is an experimental draft to enable interoperability
+// between bundle repositories. There is currently no commitment to
+// turn this draft into an official specification.
+
+package org.apache.aries.subsystem.core.repository;
+
+import java.util.Collection;
+import java.util.Map;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+
+/**
+ * A repository service that contains {@link Resource resources}.
+ *
+ * <p>
+ * Repositories may be registered as services and may be used as by a resolve
+ * context during resolver operations.
+ *
+ * <p>
+ * Repositories registered as services may be filtered using standard service
+ * properties.
+ *
+ * @ThreadSafe
+ * @noimplement
+ * @version $Id$
+ */
+public interface Repository {
+ /**
+ * Service property to provide URLs related to this repository.
+ *
+ * <p>
+ * The value of this property must be of type {@code String},
+ * {@code String[]}, or {@code Collection<String>}.
+ */
+ String URL = "repository.url";
+
+ /**
+ * Find the capabilities that match the specified requirements.
+ *
+ * @param requirements The requirements for which matching capabilities
+ * should be returned. Must not be {@code null}.
+ * @return A map of matching capabilities for the specified requirements.
+ * Each specified requirement must appear as a key in the map. If
+ * there are no matching capabilities for a specified requirement,
+ * then the value in the map for the specified requirement must be
+ * an empty collection. The returned map is the property of the
+ * caller and can be modified by the caller.
+ */
+ Map<Requirement, Collection<Capability>> findProviders(Collection<? extends Requirement> requirements);
+}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/RepositoryContent.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/RepositoryContent.java
new file mode 100755
index 0000000..698c636
--- /dev/null
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/RepositoryContent.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2012). 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.apache.aries.subsystem.core.repository;
+
+import java.io.InputStream;
+import org.osgi.resource.Resource;
+
+/**
+ * An accessor for the default content of a resource.
+ *
+ * All {@link Resource} objects which represent resources in a
+ * {@link Repository} must implement this interface. A user of the resource can
+ * then cast the {@link Resource} object to this type and then obtain an
+ * {@code InputStream} to the default content of the resource.
+ *
+ * @ThreadSafe
+ * @noimplement
+ * @version $Id$
+ */
+public interface RepositoryContent {
+
+ /**
+ * Returns a new input stream to the default format of this resource.
+ *
+ * @return A new input stream for associated resource.
+ */
+ InputStream getContent();
+}
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/package-info.java b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/package-info.java
new file mode 100755
index 0000000..d1f3475
--- /dev/null
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/package-info.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) OSGi Alliance (2010, 2012). 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.
+ */
+
+/**
+ * Repository 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. This package has two types of
+ * users: the consumers that use the API in this package and the providers that
+ * implement the API in this package.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.repository; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.repository; version="[1.0,1.1)"}
+ *
+ * @version $Id$
+ */
+
+package org.apache.aries.subsystem.core.repository;
+
diff --git a/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/packageinfo b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/packageinfo
new file mode 100755
index 0000000..c9eb66e
--- /dev/null
+++ b/subsystem/subsystem-core/src/main/java/org/apache/aries/subsystem/core/repository/packageinfo
@@ -0,0 +1,14 @@
+/*
+ * 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.
+ */
+version 1.0
diff --git a/subsystem/subsystem-core/src/test/java/org/apache/aries/subsystem/core/internal/BundleRevisionResourceTest.java b/subsystem/subsystem-core/src/test/java/org/apache/aries/subsystem/core/internal/BundleRevisionResourceTest.java
index da84ca2..3ed2e04 100644
--- a/subsystem/subsystem-core/src/test/java/org/apache/aries/subsystem/core/internal/BundleRevisionResourceTest.java
+++ b/subsystem/subsystem-core/src/test/java/org/apache/aries/subsystem/core/internal/BundleRevisionResourceTest.java
@@ -14,14 +14,18 @@
package org.apache.aries.subsystem.core.internal;
import static org.junit.Assert.assertEquals;
+import static org.easymock.EasyMock.*;
import java.lang.reflect.Field;
+import java.util.Collections;
import org.easymock.EasyMock;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
public class BundleRevisionResourceTest {
Activator storedActivator;
@@ -44,7 +48,9 @@
@Test
public void testNoModellerServiceCapabilities() {
- BundleRevision br = EasyMock.createNiceMock(BundleRevision.class);
+ BundleRevision br = createNiceMock(BundleRevision.class);
+ expect(br.getCapabilities(anyObject(String.class))).andReturn(Collections.<Capability>emptyList());
+ replay(br);
BundleRevisionResource brr = new BundleRevisionResource(br);
assertEquals(0, brr.getCapabilities("osgi.service").size());
}
@@ -52,6 +58,8 @@
@Test
public void testNoModellerServiceRequirements() {
BundleRevision br = EasyMock.createNiceMock(BundleRevision.class);
+ expect(br.getRequirements(anyObject(String.class))).andReturn(Collections.<Requirement>emptyList());
+ replay(br);
BundleRevisionResource brr = new BundleRevisionResource(br);
assertEquals(0, brr.getRequirements("osgi.service").size());
}
diff --git a/subsystem/subsystem-install/pom.xml b/subsystem/subsystem-install/pom.xml
index a52d9c1..7c12773 100644
--- a/subsystem/subsystem-install/pom.xml
+++ b/subsystem/subsystem-install/pom.xml
@@ -49,7 +49,7 @@
<dependency>
<groupId>org.apache.aries.subsystem</groupId>
<artifactId>org.apache.aries.subsystem.api</artifactId>
- <version>0.1-SNAPSHOT</version>
+ <version>1.2.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>
diff --git a/subsystem/subsystem-itests/pom.xml b/subsystem/subsystem-itests/pom.xml
index 074987c..dd9b67c 100644
--- a/subsystem/subsystem-itests/pom.xml
+++ b/subsystem/subsystem-itests/pom.xml
@@ -46,7 +46,7 @@
<dependency>
<groupId>org.osgi</groupId>
<artifactId>org.osgi.core</artifactId>
- <version>5.0.0</version>
+ <version>6.0.0</version>
<scope>test</scope>
</dependency>
<dependency>
@@ -129,7 +129,7 @@
<groupId>org.apache.aries.subsystem</groupId>
<artifactId>org.apache.aries.subsystem.api</artifactId>
<scope>test</scope>
- <version>1.1.1-SNAPSHOT</version>
+ <version>1.2.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.osgi</groupId>
@@ -141,7 +141,7 @@
<groupId>org.apache.aries.subsystem</groupId>
<artifactId>org.apache.aries.subsystem.core</artifactId>
<scope>test</scope>
- <version>1.2.1-SNAPSHOT</version>
+ <version>1.3.0-SNAPSHOT</version>
<exclusions>
<exclusion>
<groupId>org.osgi</groupId>
@@ -199,25 +199,6 @@
</dependency>
<dependency>
<groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.resolver</artifactId>
- <version>1.0.0</version>
- <exclusions>
- <exclusion>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.osgi.core</artifactId>
- </exclusion>
- <exclusion>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.compendium</artifactId>
- </exclusion>
- </exclusions>
- </dependency>
- <dependency>
- <groupId>org.apache.felix</groupId>
<artifactId>org.osgi.service.obr</artifactId>
<scope>test</scope>
<version>1.0.2</version>
@@ -318,7 +299,7 @@
<dependency>
<groupId>org.eclipse.tycho</groupId>
<artifactId>org.eclipse.osgi</artifactId>
- <version>3.8.0.v20120529-1548</version>
+ <version>3.10.0.v20140606-1445</version>
</dependency>
<dependency>
<groupId>org.ops4j.pax.logging</groupId>
diff --git a/subsystem/subsystem-itests/src/test/bundles/dynamicImport/META-INF/MANIFEST.MF b/subsystem/subsystem-itests/src/test/bundles/dynamicImport/META-INF/MANIFEST.MF
index 1aedee4..7de166d 100644
--- a/subsystem/subsystem-itests/src/test/bundles/dynamicImport/META-INF/MANIFEST.MF
+++ b/subsystem/subsystem-itests/src/test/bundles/dynamicImport/META-INF/MANIFEST.MF
@@ -5,6 +5,5 @@
Bundle-Version: 1.0.0
Import-Package: org.osgi.framework
Bundle-Activator: org.apache.aries.subsystem.itests.dynamicImport.Activator
-Provide-Capability: osgi.ee;osgi.ee=JavaSE;version=1.5
DynamicImport-Package: org.apache.aries.subsystem.itests.hello.api
diff --git a/subsystem/subsystem-itests/src/test/bundles/helloImpl/META-INF/MANIFEST.MF b/subsystem/subsystem-itests/src/test/bundles/helloImpl/META-INF/MANIFEST.MF
index 66cdf5c..f7c5c63 100644
--- a/subsystem/subsystem-itests/src/test/bundles/helloImpl/META-INF/MANIFEST.MF
+++ b/subsystem/subsystem-itests/src/test/bundles/helloImpl/META-INF/MANIFEST.MF
@@ -5,5 +5,3 @@
Bundle-Version: 1.0.0
Import-Package: org.apache.aries.subsystem.itests.hello.api, org.osgi.framework
Bundle-Activator: org.apache.aries.subsystem.itests.hello.impl.Activator
-Provide-Capability: osgi.ee;osgi.ee=JavaSE;version=1.5
-
diff --git a/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/DynamicImportTest.java b/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/DynamicImportTest.java
index 027164f..b369d5d 100644
--- a/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/DynamicImportTest.java
+++ b/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/DynamicImportTest.java
@@ -8,9 +8,7 @@
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
-import java.util.Dictionary;
import java.util.HashMap;
-import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -75,16 +73,18 @@
class TokenWeaver implements WeavingHook {
@Override
- public void weave(WovenClass arg0) {}
+ public void weave(WovenClass arg0) {
+ if ("org.apache.aries.subsystem.itests.dynamicImport".equals(arg0.getBundleWiring().getBundle().getSymbolicName())) {
+ arg0.getDynamicImports().add("org.apache.aries.subsystem.itests.hello.api");
+ }
+ }
}
@SuppressWarnings("rawtypes")
@Test
public void testFirstPassWeavingApproach() throws Exception
{
- Dictionary<String, String> props = new Hashtable<String, String>();
- props.put("osgi.woven.packages", "some.woven.package, org.apache.aries.subsystem.itests.hello.api");
- ServiceRegistration sr = bundleContext.registerService(WeavingHook.class, new TokenWeaver(), props);
+ ServiceRegistration<?> sr = bundleContext.registerService(WeavingHook.class, new TokenWeaver(), null);
try {
Subsystem subsystem = installSubsystemFromFile ("dynamicImport.esa");
startSubsystem(subsystem);
@@ -139,8 +139,6 @@
@Test
public void testDynamicPackageImportsAddedToSharingPolicyWhenNoImportPackageHeader() throws Exception {
final AtomicBoolean weavingHookCalled = new AtomicBoolean(false);
- Dictionary<String, Object> props = new Hashtable<String, Object>();
- props.put("osgi.woven.packages", "org.osgi.framework");
ServiceRegistration reg = bundleContext.registerService(
WeavingHook.class,
new WeavingHook() {
@@ -152,7 +150,7 @@
}
}
},
- props);
+ null);
try {
Subsystem s = installSubsystemFromFile(APPLICATION_A);
try {
diff --git a/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/RootSubsystemTest.java b/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/RootSubsystemTest.java
index 142283d..838e12b 100644
--- a/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/RootSubsystemTest.java
+++ b/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/RootSubsystemTest.java
@@ -106,7 +106,7 @@
core.stop();
assertServiceEventsStop(root);
core.uninstall();
- core = bundleContext.installBundle(core.getLocation());
+ core = bundleContext.installBundle(normalizeBundleLocation(core));
core.start();
// There should be install events since the persisted root subsystem was
// deleted when the subsystems implementation bundle was uninstalled.
diff --git a/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java b/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java
index 52c8dc7..55ebf01 100644
--- a/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java
+++ b/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/SubsystemTest.java
@@ -91,7 +91,6 @@
import org.osgi.resource.Capability;
import org.osgi.resource.Resource;
import org.osgi.service.repository.Repository;
-import org.osgi.service.repository.RepositoryContent;
import org.osgi.service.subsystem.Subsystem;
import org.osgi.service.subsystem.Subsystem.State;
import org.osgi.service.subsystem.SubsystemConstants;
@@ -141,7 +140,7 @@
streamBundle(createCoreFragment()).noStart(),
mavenBundle("org.apache.aries.subsystem", "org.apache.aries.subsystem.itest.interfaces").versionAsInProject(),
mavenBundle("org.apache.aries.testsupport", "org.apache.aries.testsupport.unit").versionAsInProject(),
- mavenBundle("org.apache.felix", "org.apache.felix.resolver").versionAsInProject(),
+ //mavenBundle("org.apache.felix", "org.apache.felix.resolver").versionAsInProject(),
mavenBundle("org.eclipse.equinox", "org.eclipse.equinox.coordinator").version("1.1.0.v20120522-1841"),
mavenBundle("org.eclipse.equinox", "org.eclipse.equinox.event").versionAsInProject(),
mavenBundle("org.eclipse.equinox", "org.eclipse.equinox.region").version("1.1.0.v20120522-1841"),
@@ -578,11 +577,11 @@
.end().file("OSGI-INF/blueprint/blueprint.xml", blueprintXml));
}
- private RepositoryContent createBundleRepositoryContent(String file) throws Exception {
+ protected Resource createBundleRepositoryContent(String file) throws Exception {
return createBundleRepositoryContent(new File(file));
}
- private RepositoryContent createBundleRepositoryContent(File file) throws Exception {
+ protected Resource createBundleRepositoryContent(File file) throws Exception {
return new BundleResource(FileSystem.getFSRoot(file));
}
@@ -1004,6 +1003,10 @@
}
}
+ protected static String normalizeBundleLocation(Bundle bundle) {
+ return normalizeBundleLocation(bundle.getLocation());
+ }
+
protected static String normalizeBundleLocation(String location) {
if (location.startsWith("initial@"))
return location.substring(8);
diff --git a/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/UnmanagedBundleTest.java b/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/UnmanagedBundleTest.java
index 63c575c..8325eb4 100644
--- a/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/UnmanagedBundleTest.java
+++ b/subsystem/subsystem-itests/src/test/java/org/apache/aries/subsystem/itests/UnmanagedBundleTest.java
@@ -94,7 +94,7 @@
try {
Bundle a = bundleContext.installBundle(BUNDLE_A, new FileInputStream(BUNDLE_A));
try {
- core = bundleContext.installBundle(core.getLocation());
+ core = bundleContext.installBundle(normalizeBundleLocation(core));
core.start();
assertConstituent(getRootSubsystem(), BUNDLE_A);
}
@@ -104,7 +104,7 @@
}
finally {
if (core.getState() == Bundle.UNINSTALLED) {
- core = bundleContext.installBundle(core.getLocation());
+ core = bundleContext.installBundle(normalizeBundleLocation(core));
core.start();
}
}
diff --git a/subsystem/subsystem-itests/src/test/resources/META-INF/platform-equinox/definition-3.10.0.V20131210-2136.xml b/subsystem/subsystem-itests/src/test/resources/META-INF/platform-equinox/definition-3.10.0.V20131210-2136.xml
new file mode 100755
index 0000000..9d95608
--- /dev/null
+++ b/subsystem/subsystem-itests/src/test/resources/META-INF/platform-equinox/definition-3.10.0.V20131210-2136.xml
@@ -0,0 +1,8 @@
+<platform>
+
+ <name>Equinox 3.10.0</name>
+ <system>mvn:org.eclipse/org.eclipse.osgi/3.10.0.v20131210-2136</system>
+
+ <profile name="minimal" default="true"/>
+
+</platform>
\ No newline at end of file
diff --git a/subsystem/subsystem-itests/src/test/resources/ss-runner.properties b/subsystem/subsystem-itests/src/test/resources/ss-runner.properties
new file mode 100644
index 0000000..98c6561
--- /dev/null
+++ b/subsystem/subsystem-itests/src/test/resources/ss-runner.properties
@@ -0,0 +1,229 @@
+# --------------------------------------------------------------------------------------------------------------------
+# The following bundles will always be instantiated
+# --------------------------------------------------------------------------------------------------------------------
+# handler service (extender for url stream handlers)
+handler.service=org.ops4j.pax.runner.handler.internal.Activator
+# provision service (extender for scanners)
+provision.service=org.ops4j.pax.scanner.internal.Activator
+# platform service (extender for platforms)
+platform.service=org.ops4j.pax.runner.platform.internal.Activator
+
+# --------------------------------------------------------------------------------------------------------------------
+# Known handlers
+# --------------------------------------------------------------------------------------------------------------------
+# assembly protocol handler
+handler.assembly=org.ops4j.pax.url.assembly.internal.Activator
+# cache protocol handler
+handler.cache=org.ops4j.pax.url.cache.internal.Activator
+# classpath protocol handler
+handler.classpath=org.ops4j.pax.url.classpath.internal.Activator
+# dir protocol handler
+handler.dir=org.ops4j.pax.url.dir.internal.Activator
+# mvn protocol handler
+handler.mvn=org.ops4j.pax.url.mvn.internal.Activator
+# link protocol handler
+handler.link=org.ops4j.pax.url.link.internal.Activator
+# obr protocol handler
+handler.obr=org.ops4j.pax.url.obr.internal.Activator
+# war protocol handler
+handler.war=org.ops4j.pax.url.war.internal.Activator
+# wrap protocol handler
+handler.wrap=org.ops4j.pax.url.wrap.internal.Activator
+
+# --------------------------------------------------------------------------------------------------------------------
+# Known scanners
+# --------------------------------------------------------------------------------------------------------------------
+# scan-bundle
+scanner.bundle=org.ops4j.pax.scanner.bundle.internal.Activator
+# scan-composite
+scanner.composite=org.ops4j.pax.scanner.composite.internal.Activator
+# scan-dir
+scanner.dir=org.ops4j.pax.scanner.dir.internal.Activator
+# scan-file
+scanner.features=org.ops4j.pax.scanner.features.internal.Activator
+# scan-file
+scanner.file=org.ops4j.pax.scanner.file.internal.Activator
+# scan-obr
+scanner.obr=org.ops4j.pax.scanner.obr.internal.Activator
+# scan-pom
+scanner.pom=org.ops4j.pax.scanner.pom.internal.Activator
+
+# --------------------------------------------------------------------------------------------------------------------
+# Known platforms
+# --------------------------------------------------------------------------------------------------------------------
+## Equinox
+platform.equinox.3.2.1=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.3.0=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.3.1=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.3.2=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.4.0=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.4.1=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.4.2=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.5.0=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.5.1=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.6.0=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.SNAPSHOT=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.7.0.V20110110=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.7.0.V20110221=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.8.0.V20110621=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.8.0-SNAPSHOT=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.8.0.V20120529-1548=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+platform.equinox.3.10.0.V20140606-1445=org.ops4j.pax.runner.platform.equinox.internal.SsActivator
+# Felix
+platform.felix.1.0.0=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.1.0.1=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.1.0.3=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.1.0.4=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.1.2.0=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.1.2.1=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.1.2.2=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.1.4.0=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.1.4.1=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.1.6.0=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.1.6.1=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.1.8.0=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.1.8.1=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.2.0.0=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.2.0.1=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.2.0.2=org.ops4j.pax.runner.platform.felix.internal.Activator
+platform.felix.SNAPSHOT=org.ops4j.pax.runner.platform.felix.internal.Activator
+# Knopflerfish
+platform.knopflerfish.2.0.0=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.2.0.1=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.2.0.2=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.2.0.3=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.2.0.4=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.2.0.5=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.2.1.0=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.2.1.1=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.2.2.0=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.2.3.0=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.2.3.1=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.2.3.2=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.2.3.3=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.3.0.0=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+platform.knopflerfish.SNAPSHOT=org.ops4j.pax.runner.platform.knopflerfish.internal.Activator
+#Concierge
+platform.concierge.1.0.0=org.ops4j.pax.runner.platform.concierge.internal.Activator
+platform.concierge.SNAPSHOT=org.ops4j.pax.runner.platform.concierge.internal.Activator
+
+# --------------------------------------------------------------------------------------------------------------------
+# Aditional Services
+# --------------------------------------------------------------------------------------------------------------------
+service.obr=org.apache.felix.bundlerepository.Activator
+
+# --------------------------------------------------------------------------------------------------------------------
+# Default values.
+# Default values are used in case that an option / configuration property is not set.
+# --------------------------------------------------------------------------------------------------------------------
+# defaults for runner options
+# default list of handlers
+default.handlers=handler.mvn,handler.classpath,handler.war,handler.wrap,handler.obr,handler.link,handler.cache,handler.assembly,handler.dir
+# default list of scanners
+default.scanners=scanner.bundle,scanner.composite,scanner.dir,scanner.features,scanner.file,scanner.obr,scanner.pom
+# default platfom
+default.platform=platform.felix
+# default felix platform version
+default.platform.felix.version=2.0.2
+# default equinox platform version
+default.platform.equinox.version=3.5.1
+# default knopflerfish platform version
+default.platform.knopflerfish.version=2.3.3
+# default concierge platform version
+default.platform.concierge.version=1.0.0
+# default list of additional services
+default.services=service.obr
+# default obr repositories
+default.obr.repository.url=http://bundles.osgi.org/obr/browse?_xml=1&cmd=repository
+# default profiles repository
+default.profilesRepositories=http://scm.ops4j.org/repos/ops4j/projects/pax/runner-repository
+# default group id
+default.profilesGroupId=org.ops4j.pax.runner.profiles
+# default "snapshot" platform definition repository
+default.snapshotsRepository=http://scm.ops4j.org/repos/ops4j/projects/pax/runner-repository
+# default "snapshot" Felix platform definition URL
+default.felix.snapshot.definition.url=mvn:${snapshotsRepository}!org.ops4j.pax.runner.platforms/felix//xml
+# default "snapshot" Equinox platform definition URL
+default.equinox.snapshot.definition.url=mvn:${snapshotsRepository}!org.ops4j.pax.runner.platforms/equinox//xml
+# default "snapshot" Knopflerfish platform definition URL
+default.knopflerfish.snapshot.definition.url=mvn:${snapshotsRepository}!org.ops4j.pax.runner.platforms/knopflerfish//xml
+# default "snapshot" Concierge platform definition URL
+default.concierge.snapshot.definition.url=mvn:${snapshotsRepository}!org.ops4j.pax.runner.platforms/concierge//xml
+# default working directory
+default.workingDirectory=runner
+# default caching directory
+default.org.ops4j.pax.url.cache.workingDirectory=${workingDirectory}/cache
+# default platform working directory
+default.org.ops4j.pax.runner.platform.workingDirectory=${workingDirectory}
+
+
+# --------------------------------------------------------------------------------------------------------------------
+# Configuration properties alias
+# Alias are used to transform configuration properties from the fully qualified ones to simple option name or
+# to convert simple values from start arguments to the actual ones.
+# --------------------------------------------------------------------------------------------------------------------
+# aliases for runner options
+alias.platform=p
+alias.platform.equinox=platform.equinox
+alias.platform.e=platform.equinox
+alias.platform.eq=platform.equinox
+alias.platform.felix=platform.felix
+alias.platform.f=platform.felix
+alias.platform.knopflerfish=platform.knopflerfish
+alias.platform.k=platform.knopflerfish
+alias.platform.kf=platform.knopflerfish
+alias.platform.concierge=platform.concierge
+alias.platform.c=platform.concierge
+alias.version=v
+alias.snapshot=s
+alias.workingDirectory=dir
+
+# aliases for handlers
+alias.org.ops4j.pax.url.mvn.certificateCheck=certificateCheck
+alias.org.ops4j.pax.url.mvn.defaultRepositories=defaultRepositories,dr
+alias.org.ops4j.pax.url.mvn.localRepository=localRepository,lr,maven.repo.local
+alias.org.ops4j.pax.url.mvn.repositories=repositories,repos
+alias.org.ops4j.pax.url.mvn.settings=settings
+alias.org.ops4j.pax.url.mvn.useFallbackRepositories=useFallbackRepositories,ufr
+alias.org.ops4j.pax.url.obr.certificateCheck=certificateCheck
+alias.org.ops4j.pax.url.war.certificateCheck=certificateCheck
+alias.org.ops4j.pax.url.wrap.certificateCheck=certificateCheck
+alias.org.ops4j.pax.scanner.composite.certificateCheck=certificateCheck
+alias.org.ops4j.pax.scanner.features.certificateCheck=certificateCheck
+
+# aliases for platform options
+alias.org.ops4j.pax.runner.platform.bootDelegation=bootDelegation,bd
+alias.org.ops4j.pax.runner.platform.bundleStartLevel=bundleStartLevel,bsl
+alias.org.ops4j.pax.runner.platform.classpath=classPath,cp
+alias.org.ops4j.pax.runner.platform.console=console
+alias.org.ops4j.pax.runner.platform.definitionURL=definitionURL
+alias.org.ops4j.pax.runner.platform.frameworkProfile=frameworkProfile,fp
+alias.org.ops4j.pax.runner.platform.ee=ee
+alias.org.ops4j.pax.runner.platform.javaHome=javaHome,home
+alias.org.ops4j.pax.runner.platform.overwrite=overwrite
+alias.org.ops4j.pax.runner.platform.overwriteUserBundles=overwriteUserBundles
+alias.org.ops4j.pax.runner.platform.overwriteSystemBundles=overwriteSystemBundles
+alias.org.ops4j.pax.runner.platform.profileStartLevel=profileStartLevel,psl
+alias.org.ops4j.pax.runner.platform.startLevel=startLevel,sl
+alias.org.ops4j.pax.runner.platform.systemPackages=systemPackages,sp
+alias.org.ops4j.pax.runner.platform.usePersistedState=usePersistedState,ups
+alias.org.ops4j.pax.runner.platform.vmOptions=vmOptions,vmo
+alias.org.ops4j.pax.runner.platform.debugClassLoading=debugClassLoading,dcl
+alias.org.ops4j.pax.runner.platform.downloadFeedback=downloadFeedback,df
+alias.org.ops4j.pax.runner.platform.autoWrap=autoWrap
+alias.org.ops4j.pax.runner.platform.keepOriginalUrls=keepOriginalUrls,kou
+alias.org.ops4j.pax.runner.platform.bundleValidation=bundleValidation
+alias.org.ops4j.pax.runner.platform.skipInvalidBundles=skipInvalidBundles,sib
+alias.org.ops4j.pax.runner.platform.useAbsoluteFilePaths=useAbsoluteFilePaths,absoluteFilePaths,uafp
+
+# aliases for scanners
+alias.org.ops4j.pax.scanner.bundle.start=start
+alias.org.ops4j.pax.scanner.composite.start=start
+alias.org.ops4j.pax.scanner.dir.start=start
+alias.org.ops4j.pax.scanner.features.start=start
+alias.org.ops4j.pax.scanner.file.start=start
+alias.org.ops4j.pax.scanner.obr.start=start
+alias.org.ops4j.pax.scanner.pom.start=start
+
+# aliases for additional services
+alias.obr.repository.url=obrRepositories|obrRepos