[felix-framework] 03/09: Imported Upstream version 4.6.0
Markus Koschany
apo-guest at moszumanska.debian.org
Mon Feb 9 15:41:17 UTC 2015
This is an automated email from the git hooks/post-receive script.
apo-guest pushed a commit to branch experimental
in repository felix-framework.
commit b58dea853a99a216f56d78eef7182ed2703dd910
Author: Markus Koschany <apo at gambaru.de>
Date: Mon Feb 2 00:26:02 2015 +0100
Imported Upstream version 4.6.0
---
DEPENDENCIES | 6 +-
NOTICE | 4 +-
doc/changelog.txt | 40 ++
pom.xml | 62 +-
src/main/appended-resources/META-INF/DEPENDENCIES | 6 +-
src/main/appended-resources/META-INF/NOTICE | 2 +-
.../apache/felix/framework/BundleContextImpl.java | 145 +++-
.../org/apache/felix/framework/BundleImpl.java | 8 +-
.../felix/framework/BundleProtectionDomain.java | 365 +++++++++-
.../apache/felix/framework/BundleRevisionImpl.java | 15 +-
.../apache/felix/framework/BundleWiringImpl.java | 571 +++++++++-------
.../org/apache/felix/framework/DTOFactory.java | 480 +++++++++++++
.../apache/felix/framework/ExtensionManager.java | 207 +++++-
.../java/org/apache/felix/framework/Felix.java | 357 +++++++---
.../felix/framework/FrameworkStartLevelImpl.java | 12 +-
.../felix/framework/FrameworkWiringImpl.java | 20 +-
.../apache/felix/framework/ResolveContextImpl.java | 6 +-
.../felix/framework/ServiceRegistrationImpl.java | 38 +-
.../apache/felix/framework/ServiceRegistry.java | 167 +++--
.../apache/felix/framework/StatefulResolver.java | 85 +--
.../org/apache/felix/framework/URLHandlers.java | 95 ++-
.../felix/framework/URLHandlersActivator.java | 7 +-
.../org/apache/felix/framework/WovenClassImpl.java | 187 +++--
.../framework/capabilityset/CapabilitySet.java | 32 +-
.../felix/framework/util/EventDispatcher.java | 74 +-
.../felix/framework/util/FelixConstants.java | 5 +-
.../apache/felix/framework/util/ImmutableList.java | 12 +
.../apache/felix/framework/util/SecureAction.java | 88 +++
.../java/org/apache/felix/framework/util/Util.java | 59 +-
.../util/manifestparser/ManifestParser.java | 208 ++++--
.../{R4Library.java => NativeLibrary.java} | 4 +-
.../util/manifestparser/NativeLibraryClause.java | 758 +++++++++++++++++++++
.../util/manifestparser/R4LibraryClause.java | 529 --------------
src/main/java/org/osgi/dto/DTO.java | 273 ++++++++
src/main/java/org/osgi/dto/package-info.java | 42 ++
src/main/java/org/osgi/dto/packageinfo | 1 +
.../java/org/osgi/framework/AdaptPermission.java | 25 +-
.../java/org/osgi/framework/AdminPermission.java | 31 +-
.../org/osgi/framework/AllServiceListener.java | 8 +-
src/main/java/org/osgi/framework/Bundle.java | 211 +++---
.../java/org/osgi/framework/BundleActivator.java | 12 +-
.../java/org/osgi/framework/BundleContext.java | 274 +++++---
src/main/java/org/osgi/framework/BundleEvent.java | 24 +-
.../java/org/osgi/framework/BundleException.java | 6 +-
.../java/org/osgi/framework/BundleListener.java | 7 +-
.../java/org/osgi/framework/BundlePermission.java | 13 +-
.../java/org/osgi/framework/BundleReference.java | 8 +-
.../org/osgi/framework/CapabilityPermission.java | 28 +-
src/main/java/org/osgi/framework/Configurable.java | 4 +-
src/main/java/org/osgi/framework/Constants.java | 129 +++-
src/main/java/org/osgi/framework/Filter.java | 7 +-
.../java/org/osgi/framework/FrameworkEvent.java | 24 +-
.../java/org/osgi/framework/FrameworkListener.java | 7 +-
.../java/org/osgi/framework/FrameworkUtil.java | 74 +-
.../org/osgi/framework/InvalidSyntaxException.java | 6 +-
.../java/org/osgi/framework/PackagePermission.java | 23 +-
.../osgi/framework/PrototypeServiceFactory.java | 124 ++++
src/main/java/org/osgi/framework/ServiceEvent.java | 4 +-
.../java/org/osgi/framework/ServiceException.java | 10 +-
.../java/org/osgi/framework/ServiceFactory.java | 51 +-
.../java/org/osgi/framework/ServiceListener.java | 7 +-
.../java/org/osgi/framework/ServiceObjects.java | 142 ++++
.../java/org/osgi/framework/ServicePermission.java | 33 +-
.../java/org/osgi/framework/ServiceReference.java | 9 +-
.../org/osgi/framework/ServiceRegistration.java | 32 +-
.../java/org/osgi/framework/SignerProperty.java | 6 +-
.../osgi/framework/SynchronousBundleListener.java | 8 +-
.../osgi/framework/UnfilteredServiceListener.java | 7 +-
src/main/java/org/osgi/framework/Version.java | 47 +-
src/main/java/org/osgi/framework/VersionRange.java | 54 +-
.../java/org/osgi/framework/dto/BundleDTO.java | 66 ++
.../java/org/osgi/framework/dto/FrameworkDTO.java | 60 ++
.../osgi/framework/dto/ServiceReferenceDTO.java | 69 ++
.../java/org/osgi/framework/dto/package-info.java | 42 ++
src/main/java/org/osgi/framework/dto/packageinfo | 1 +
.../osgi/framework/hooks/bundle/CollisionHook.java | 14 +-
.../org/osgi/framework/hooks/bundle/EventHook.java | 6 +-
.../org/osgi/framework/hooks/bundle/FindHook.java | 6 +-
.../osgi/framework/hooks/bundle/package-info.java | 36 +
.../org/osgi/framework/hooks/bundle/packageinfo | 1 +
.../framework/hooks/resolver/ResolverHook.java | 52 +-
.../hooks/resolver/ResolverHookFactory.java | 6 +-
.../framework/hooks/resolver/package-info.java | 36 +
.../org/osgi/framework/hooks/resolver/packageinfo | 1 +
.../osgi/framework/hooks/service/EventHook.java | 7 +-
.../framework/hooks/service/EventListenerHook.java | 7 +-
.../org/osgi/framework/hooks/service/FindHook.java | 7 +-
.../osgi/framework/hooks/service/ListenerHook.java | 10 +-
.../osgi/framework/hooks/service/package-info.java | 36 +
.../org/osgi/framework/hooks/service/packageinfo | 1 +
.../framework/hooks/weaving/WeavingException.java | 4 +-
.../osgi/framework/hooks/weaving/WeavingHook.java | 8 +-
.../osgi/framework/hooks/weaving/WovenClass.java | 133 +++-
.../hooks/weaving/WovenClassListener.java | 71 ++
.../osgi/framework/hooks/weaving/package-info.java | 38 ++
.../org/osgi/framework/hooks/weaving/packageinfo | 1 +
.../java/org/osgi/framework/launch/Framework.java | 56 +-
.../osgi/framework/launch/FrameworkFactory.java | 7 +-
.../package-info.java} | 40 +-
.../java/org/osgi/framework/launch/packageinfo | 1 +
.../namespace/AbstractWiringNamespace.java | 6 +-
.../osgi/framework/namespace/BundleNamespace.java | 4 +-
.../namespace/ExecutionEnvironmentNamespace.java | 4 +-
.../osgi/framework/namespace/HostNamespace.java | 6 +-
.../framework/namespace/IdentityNamespace.java | 4 +-
.../osgi/framework/namespace/NativeNamespace.java | 81 +++
.../osgi/framework/namespace/PackageNamespace.java | 4 +-
.../package-info.java} | 32 +-
.../java/org/osgi/framework/namespace/packageinfo | 1 +
.../{BundleReference.java => package-info.java} | 36 +-
src/main/java/org/osgi/framework/packageinfo | 1 +
.../framework/startlevel/BundleStartLevel.java | 7 +-
.../framework/startlevel/FrameworkStartLevel.java | 15 +-
.../startlevel/dto/BundleStartLevelDTO.java | 61 ++
.../startlevel/dto/FrameworkStartLevelDTO.java | 47 ++
.../framework/startlevel/dto/package-info.java | 42 ++
.../org/osgi/framework/startlevel/dto/packageinfo | 1 +
.../osgi/framework/startlevel/package-info.java | 83 +++
.../java/org/osgi/framework/startlevel/packageinfo | 1 +
.../osgi/framework/wiring/BundleCapability.java | 7 +-
.../osgi/framework/wiring/BundleRequirement.java | 7 +-
.../org/osgi/framework/wiring/BundleRevision.java | 9 +-
.../org/osgi/framework/wiring/BundleRevisions.java | 7 +-
.../java/org/osgi/framework/wiring/BundleWire.java | 7 +-
.../org/osgi/framework/wiring/BundleWiring.java | 43 +-
.../org/osgi/framework/wiring/FrameworkWiring.java | 52 +-
.../framework/wiring/dto/BundleRevisionDTO.java | 62 ++
.../osgi/framework/wiring/dto/BundleWireDTO.java | 48 ++
.../osgi/framework/wiring/dto/BundleWiringDTO.java | 97 +++
.../osgi/framework/wiring/dto/package-info.java | 42 ++
.../java/org/osgi/framework/wiring/dto/packageinfo | 1 +
.../package-info.java} | 35 +-
.../java/org/osgi/framework/wiring/packageinfo | 1 +
src/main/java/org/osgi/resource/Capability.java | 6 +-
src/main/java/org/osgi/resource/Namespace.java | 7 +-
src/main/java/org/osgi/resource/Requirement.java | 6 +-
src/main/java/org/osgi/resource/Resource.java | 6 +-
src/main/java/org/osgi/resource/Wire.java | 7 +-
src/main/java/org/osgi/resource/Wiring.java | 18 +-
.../java/org/osgi/resource/dto/CapabilityDTO.java | 70 ++
.../org/osgi/resource/dto/CapabilityRefDTO.java | 41 ++
.../java/org/osgi/resource/dto/RequirementDTO.java | 70 ++
.../org/osgi/resource/dto/RequirementRefDTO.java | 41 ++
.../java/org/osgi/resource/dto/ResourceDTO.java | 51 ++
src/main/java/org/osgi/resource/dto/WireDTO.java | 58 ++
src/main/java/org/osgi/resource/dto/WiringDTO.java | 73 ++
.../java/org/osgi/resource/dto/package-info.java | 42 ++
src/main/java/org/osgi/resource/dto/packageinfo | 1 +
.../package-info.java} | 35 +-
src/main/java/org/osgi/resource/packageinfo | 1 +
.../osgi/service/packageadmin/ExportedPackage.java | 4 +-
.../osgi/service/packageadmin/PackageAdmin.java | 40 +-
.../osgi/service/packageadmin/RequiredBundle.java | 4 +-
.../osgi/service/packageadmin/package-info.java | 38 ++
.../java/org/osgi/service/packageadmin/packageinfo | 1 +
.../org/osgi/service/startlevel/StartLevel.java | 23 +-
.../org/osgi/service/startlevel/package-info.java | 38 ++
.../java/org/osgi/service/startlevel/packageinfo | 1 +
.../url/AbstractURLStreamHandlerService.java | 23 +-
.../java/org/osgi/service/url/URLConstants.java | 8 +-
.../osgi/service/url/URLStreamHandlerService.java | 19 +-
.../osgi/service/url/URLStreamHandlerSetter.java | 8 +-
.../url/package-info.java} | 36 +-
src/main/java/org/osgi/service/url/packageinfo | 1 +
.../org/osgi/util/tracker/AbstractTracked.java | 4 +-
.../java/org/osgi/util/tracker/BundleTracker.java | 8 +-
.../osgi/util/tracker/BundleTrackerCustomizer.java | 6 +-
.../java/org/osgi/util/tracker/ServiceTracker.java | 19 +-
.../util/tracker/ServiceTrackerCustomizer.java | 6 +-
.../tracker/package-info.java} | 36 +-
src/main/java/org/osgi/util/tracker/packageinfo | 1 +
src/main/resources/default.properties | 65 +-
.../felix/framework/BundleWiringImplTest.java | 464 +++++++++++++
.../apache/felix/framework/CollisionHookTest.java | 6 +-
.../org/apache/felix/framework/DTOFactoryTest.java | 272 ++++++++
.../felix/framework/ExtensionManagerTest.java | 197 ++++++
.../felix/framework/FrameworkVersionTest.java | 49 ++
.../felix/framework/PackageAdminImplTest.java | 163 +++++
.../framework/RequirementsCapabilitiesTest.java | 24 +
.../apache/felix/framework/StartBundleTest.java | 57 ++
.../felix/framework/StartStopBundleTest.java | 1 +
.../util/manifestparser/ManifestParserTest.java | 81 +++
.../manifestparser/NativeLibraryClauseTest.java | 146 ++++
183 files changed, 8471 insertions(+), 2013 deletions(-)
diff --git a/DEPENDENCIES b/DEPENDENCIES
index 03546b3..6ece774 100644
--- a/DEPENDENCIES
+++ b/DEPENDENCIES
@@ -9,7 +9,7 @@ Apache Felix Framework
-Copyright 2013 The Apache Software Foundation
+Copyright 2015 The Apache Software Foundation
This software was developed at the Apache Software Foundation
(http://www.apache.org) and may have dependencies on other
@@ -19,14 +19,14 @@ I. Included Third-Party Software
This product includes software developed at
The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2012).
+Copyright (c) OSGi Alliance (2000, 2014).
Licensed under the Apache License 2.0.
II. Used Third-Party Software
This product uses software developed at
The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2012).
+Copyright (c) OSGi Alliance (2000, 2014).
Licensed under the Apache License 2.0.
III. License Summary
diff --git a/NOTICE b/NOTICE
index 61635c3..47afa37 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,6 +1,6 @@
Apache Felix Framework
-Copyright 2006-2014 The Apache Software Foundation
+Copyright 2006-2015 The Apache Software Foundation
This product includes software developed at
The Apache Software Foundation (http://www.apache.org/).
@@ -8,5 +8,5 @@ The Apache Software Foundation (http://www.apache.org/).
This product includes software developed at
The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2012).
+Copyright (c) OSGi Alliance (2000, 2015).
Licensed under the Apache License 2.0.
diff --git a/doc/changelog.txt b/doc/changelog.txt
index 72f9425..72e23b1 100644
--- a/doc/changelog.txt
+++ b/doc/changelog.txt
@@ -1,3 +1,43 @@
+Changes from 4.4.1 to 4.6.0
+---------------------------
+** Sub-task
+ * [FELIX-4503] - [Core R6] Support osgi.native capability
+ * [FELIX-4504] - [Core R6] Support Framework DTOs
+ * [FELIX-4505] - [Core R6] Support Prototype Service Factory
+ * [FELIX-4578] - [Core R6] Support new Framework.init(FrameworkListener ... listeners) override
+ * [FELIX-4579] - [Core R6] Support Framework Extension Bundle Activators
+ * [FELIX-4580] - [Core R6] Support service.bundleid Service Registration property
+ * [FELIX-4581] - [Core R6] Support FrameworkWiring.findProviders(Requirement)
+ * [FELIX-4582] - [Core R6] Support WovenClassListener
+ * [FELIX-4583] - [Core R6] Ensure that all OSGi Core R6 CT tests pass
+ * [FELIX-4590] - [Core R6] Update to R6 API
+ * [FELIX-4593] - Support the JavaSE/compact profiles for Java 8
+ * [FELIX-4726] - [Core R6] Update bundle and service hooks for the system bundle
+
+** Bug
+ * [FELIX-3883] - [Framework] Move OS and processor aliases to configuration properties
+ * [FELIX-4690] - Some bundles containing native code can fail to start on Windows 7+
+ * [FELIX-4701] - Properties with surprising spelling in AutoProcessor
+ * [FELIX-4729] - [Core R6] Support for osgi.native namespace with Loading native code libraries
+
+** Improvement
+ * [FELIX-4502] - [Core R6] Provide an OSGi R6 compliant framework implementation
+ * [FELIX-4658] - URL of the CodeSource of a ProtectionDomain should resolve to the right JAR
+ * [FELIX-4692] - Improve Service access time
+ * [FELIX-4757] - Native Capabilities should allow OS and Processor alias to load from default and config properties
+
+Changes form 4.4.0 to 4.4.1
+---------------------------
+** Bug
+ * [FELIX-3239] - PackageAdmin#getExportedPackages does not work on packages exported by attached fragments
+ * [FELIX-3309] - Dashes in qualifier get replaced by periods causing framework not to start up
+ * [FELIX-3701] - Intermittent CNFE with embedded jars in Fragment Bundles
+ * [FELIX-4220] - BundleException type is always set to 0
+ * [FELIX-4281] - Security Warning: Felix with Java Web Start
+ * [FELIX-4515] - BundleRevision for system extension has no capabilities
+ * [FELIX-4523] - Deadlock in URLHandlers when Felix.init and Felix.stop are called concurrently
+ * [FELIX-4534] - Bundles containing native code fails to start on Windows 7
+
Changes from 4.2.1 to 4.4.0
---------------------------
** Bug
diff --git a/pom.xml b/pom.xml
index 1432244..556d115 100644
--- a/pom.xml
+++ b/pom.xml
@@ -27,17 +27,17 @@
<packaging>bundle</packaging>
<name>Apache Felix Framework</name>
<artifactId>org.apache.felix.framework</artifactId>
- <version>4.4.0</version>
- <dependencies>
- </dependencies>
+ <version>4.6.0</version>
+
<properties>
<dollar>$</dollar>
</properties>
- <scm>
- <connection>scm:svn:http://svn.apache.org/repos/asf/felix/releases/org.apache.felix.framework-4.4.0</connection>
- <developerConnection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.apache.felix.framework-4.4.0</developerConnection>
- <url>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.apache.felix.framework-4.4.0</url>
- </scm>
+ <scm>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/felix/releases/org.apache.felix.framework-4.6.0</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.apache.felix.framework-4.6.0</developerConnection>
+ <url>scm:svn:https://svn.apache.org/repos/asf/felix/releases/org.apache.felix.framework-4.6.0</url>
+ </scm>
+
<build>
<plugins>
<plugin>
@@ -52,15 +52,22 @@
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
- <version>2.3.5</version>
+ <version>2.5.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>org.apache.felix.framework</Bundle-SymbolicName>
<Bundle-Name>Apache Felix Framework</Bundle-Name>
- <Bundle-Description>OSGi R4 framework implementation.</Bundle-Description>
+ <Bundle-Description>OSGi R5 framework implementation.</Bundle-Description>
<Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
- <Export-Package>org.osgi.framework.*;-split-package:=merge-first,org.osgi.resource,org.osgi.service.*,org.osgi.util.tracker</Export-Package>
+ <Export-Package>
+ org.osgi.framework.*;-split-package:=merge-first,
+ org.osgi.resource,
+ org.osgi.resource.dto,
+ org.osgi.service.*,
+ org.osgi.util.tracker,
+ org.osgi.dto
+ </Export-Package>
<Private-Package>org.apache.felix.framework.*</Private-Package>
<Import-Package>!*</Import-Package>
</instructions>
@@ -89,6 +96,25 @@
</excludes>
</configuration>
</plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-sources</id>
+ <goals>
+ <goal>jar</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <failOnError>false</failOnError>
+ </configuration>
+ </plugin>
</plugins>
<resources>
<resource>
@@ -97,4 +123,18 @@
</resource>
</resources>
</build>
+ <dependencies>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.annotation</artifactId>
+ <version>6.0.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.ow2.asm</groupId>
+ <artifactId>asm-all</artifactId>
+ <version>4.2</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
</project>
diff --git a/src/main/appended-resources/META-INF/DEPENDENCIES b/src/main/appended-resources/META-INF/DEPENDENCIES
index 310180d..984b61d 100644
--- a/src/main/appended-resources/META-INF/DEPENDENCIES
+++ b/src/main/appended-resources/META-INF/DEPENDENCIES
@@ -1,4 +1,4 @@
-Copyright 2013 The Apache Software Foundation
+Copyright 2015 The Apache Software Foundation
This software was developed at the Apache Software Foundation
(http://www.apache.org) and may have dependencies on other
@@ -8,14 +8,14 @@ I. Included Third-Party Software
This product includes software developed at
The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2012).
+Copyright (c) OSGi Alliance (2000, 2014).
Licensed under the Apache License 2.0.
II. Used Third-Party Software
This product uses software developed at
The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2012).
+Copyright (c) OSGi Alliance (2000, 2014).
Licensed under the Apache License 2.0.
III. License Summary
diff --git a/src/main/appended-resources/META-INF/NOTICE b/src/main/appended-resources/META-INF/NOTICE
index 8b4b009..d4d1ad8 100644
--- a/src/main/appended-resources/META-INF/NOTICE
+++ b/src/main/appended-resources/META-INF/NOTICE
@@ -1,4 +1,4 @@
This product includes software developed at
The OSGi Alliance (http://www.osgi.org/).
-Copyright (c) OSGi Alliance (2000, 2012).
+Copyright (c) OSGi Alliance (2000, 2015).
Licensed under the Apache License 2.0.
diff --git a/src/main/java/org/apache/felix/framework/BundleContextImpl.java b/src/main/java/org/apache/felix/framework/BundleContextImpl.java
index bbdd980..c5a1011 100644
--- a/src/main/java/org/apache/felix/framework/BundleContextImpl.java
+++ b/src/main/java/org/apache/felix/framework/BundleContextImpl.java
@@ -20,10 +20,12 @@ package org.apache.felix.framework;
import java.io.File;
import java.io.InputStream;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Dictionary;
+import java.util.List;
import org.apache.felix.framework.ext.FelixBundleContext;
import org.osgi.framework.AdminPermission;
@@ -34,7 +36,9 @@ import org.osgi.framework.Constants;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServicePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
@@ -465,25 +469,20 @@ class BundleContextImpl implements FelixBundleContext
((SecurityManager) sm).checkPermission(new ServicePermission(ref, ServicePermission.GET));
}
- return m_felix.getService(m_bundle, ref);
+ return m_felix.getService(m_bundle, ref, false);
}
public boolean ungetService(ServiceReference<?> ref)
{
checkValidity();
- // CONCURRENCY NOTE: This is a check-then-act situation,
- // but we ignore it since the time window is small and
- // the result is the same as if the calling thread had
- // won the race condition.
-
if (ref == null)
{
throw new NullPointerException("Specified service reference cannot be null.");
}
// Unget the specified service.
- return m_felix.ungetService(m_bundle, ref);
+ return m_felix.ungetService(m_bundle, ref, null);
}
public File getDataFile(String s)
@@ -513,4 +512,136 @@ class BundleContextImpl implements FelixBundleContext
throw new IllegalStateException("Invalid BundleContext.");
}
+
+ /**
+ * @see org.osgi.framework.BundleContext#registerService(java.lang.Class, org.osgi.framework.ServiceFactory, java.util.Dictionary)
+ */
+ public <S> ServiceRegistration<S> registerService(Class<S> clazz,
+ ServiceFactory<S> factory, Dictionary<String, ?> properties)
+ {
+ return (ServiceRegistration<S>)
+ registerService(new String[] { clazz.getName() }, factory, properties);
+ }
+
+ /**
+ * @see org.osgi.framework.BundleContext#getServiceObjects(org.osgi.framework.ServiceReference)
+ */
+ public <S> ServiceObjects<S> getServiceObjects(final ServiceReference<S> ref)
+ {
+ checkValidity();
+
+ Object sm = System.getSecurityManager();
+
+ if (sm != null)
+ {
+ ((SecurityManager) sm).checkPermission(new ServicePermission(ref, ServicePermission.GET));
+ }
+
+ ServiceRegistrationImpl reg =
+ ((ServiceRegistrationImpl.ServiceReferenceImpl) ref).getRegistration();
+ if ( reg.isValid() )
+ {
+ return new ServiceObjectsImpl(ref);
+ }
+ return null;
+ }
+
+ //
+ // ServiceObjects implementation
+ //
+ class ServiceObjectsImpl<S> implements ServiceObjects<S>
+ {
+ private final ServiceReference<S> m_ref;
+
+ private final List<S> srvObjects = new ArrayList<S>();
+
+ public ServiceObjectsImpl(final ServiceReference<S> ref)
+ {
+ this.m_ref = ref;
+ }
+
+ public S getService() {
+ S srvObj = null;
+ // special handling for prototype scope
+ if ( m_ref.getProperty(Constants.SERVICE_SCOPE) == Constants.SCOPE_PROTOTYPE )
+ {
+ checkValidity();
+
+ // CONCURRENCY NOTE: This is a check-then-act situation,
+ // but we ignore it since the time window is small and
+ // the result is the same as if the calling thread had
+ // won the race condition.
+
+ Object sm = System.getSecurityManager();
+
+ if (sm != null)
+ {
+ ((SecurityManager) sm).checkPermission(new ServicePermission(m_ref, ServicePermission.GET));
+ }
+
+ srvObj = m_felix.getService(m_bundle, m_ref, true);
+ }
+ else
+ {
+ // getService handles singleton and bundle scope
+ srvObj = BundleContextImpl.this.getService(m_ref);
+ }
+
+ if ( srvObj != null )
+ {
+ synchronized ( srvObjects )
+ {
+ srvObjects.add(srvObj);
+ }
+ }
+
+ return srvObj;
+ }
+
+ public void ungetService(final S srvObj)
+ {
+ if ( srvObj != null )
+ {
+ // check if this object was returned by this service objects
+ synchronized ( srvObjects )
+ {
+ boolean found = false;
+ int i = 0;
+ while ( !found && i < srvObjects.size() )
+ {
+ found = srvObjects.get(i) == srvObj;
+ i++;
+ }
+ if ( !found )
+ {
+ throw new IllegalArgumentException();
+ }
+ srvObjects.remove(i-1);
+ }
+
+ }
+ // special handling for prototype scope
+ if ( m_ref.getProperty(Constants.SERVICE_SCOPE) == Constants.SCOPE_PROTOTYPE )
+ {
+ checkValidity();
+
+ // Unget the specified service.
+ if ( !m_felix.ungetService(m_bundle, m_ref, srvObj) )
+ {
+ throw new IllegalArgumentException();
+ }
+ }
+ else
+ {
+ // ungetService handles singleton and bundle scope
+ BundleContextImpl.this.ungetService(m_ref);
+ }
+ }
+
+ public ServiceReference<S> getServiceReference()
+ {
+ return m_ref;
+ }
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/org/apache/felix/framework/BundleImpl.java b/src/main/java/org/apache/felix/framework/BundleImpl.java
index f04bac7..b9ac3ab 100644
--- a/src/main/java/org/apache/felix/framework/BundleImpl.java
+++ b/src/main/java/org/apache/felix/framework/BundleImpl.java
@@ -42,6 +42,7 @@ import org.apache.felix.framework.util.SecurityManagerEx;
import org.apache.felix.framework.util.ShrinkableCollection;
import org.apache.felix.framework.util.StringMap;
import org.apache.felix.framework.util.Util;
+import org.osgi.dto.DTO;
import org.osgi.framework.AdaptPermission;
import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
@@ -1114,6 +1115,11 @@ class BundleImpl implements Bundle, BundleRevisions
return (A) new AccessControlContext(new ProtectionDomain[] {pd});
}
+ else if (DTO.class.isAssignableFrom(type) ||
+ DTO[].class.isAssignableFrom(type))
+ {
+ return DTOFactory.createDTO(this, type);
+ }
return null;
}
@@ -1278,7 +1284,7 @@ class BundleImpl implements Bundle, BundleRevisions
Collection<Bundle> shrinkableCollisionCandidates = new ShrinkableCollection<Bundle>(collisionCanditates);
for (ServiceReference<CollisionHook> hook : hooks)
{
- CollisionHook ch = getFramework().getService(getFramework(), hook);
+ CollisionHook ch = getFramework().getService(getFramework(), hook, false);
if (ch != null)
{
int operationType;
diff --git a/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java b/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
index 061105c..9c3befc 100644
--- a/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
+++ b/src/main/java/org/apache/felix/framework/BundleProtectionDomain.java
@@ -18,36 +18,371 @@
*/
package org.apache.felix.framework;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
import java.lang.ref.WeakReference;
+import java.net.JarURLConnection;
import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
import java.security.CodeSource;
import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import org.apache.felix.framework.cache.Content;
+import org.apache.felix.framework.cache.JarContent;
+import org.osgi.framework.PackagePermission;
import org.osgi.framework.wiring.BundleRevision;
public class BundleProtectionDomain extends ProtectionDomain
{
+ private static final class BundleInputStream extends InputStream
+ {
+ private final Content m_root;
+ private final Enumeration m_content;
+ private final OutputStreamBuffer m_outputBuffer = new OutputStreamBuffer();
+
+ private ByteArrayInputStream m_buffer = null;
+ private JarOutputStream m_output = null;
+
+ private static final String DUMMY_ENTRY = "__DUMMY-ENTRY__/";
+
+ public BundleInputStream(Content root) throws IOException
+ {
+ m_root = root;
+
+ List entries = new ArrayList();
+
+ int count = 0;
+ String manifest = null;
+ for (Enumeration e = m_root.getEntries(); e.hasMoreElements();)
+ {
+ String entry = (String) e.nextElement();
+ if (entry.endsWith("/"))
+ {
+ // ignore
+ }
+ else if (entry.equalsIgnoreCase("META-INF/MANIFEST.MF"))
+ {
+ if (manifest == null)
+ {
+ manifest = entry;
+ }
+ }
+ else if (entry.toUpperCase().startsWith("META-INF/")
+ && entry.indexOf('/', "META-INF/".length()) < 0)
+ {
+ entries.add(count++, entry);
+ }
+ else
+ {
+ entries.add(entry);
+ }
+ }
+ entries.add(count++, DUMMY_ENTRY);
+ if (manifest == null)
+ {
+ manifest = "META-INF/MANIFEST.MF";
+ }
+ m_content = Collections.enumeration(entries);
+
+ m_output = new JarOutputStream(m_outputBuffer);
+ readNext(manifest);
+ m_buffer = new ByteArrayInputStream(m_outputBuffer.m_outBuffer
+ .toByteArray());
+
+ m_outputBuffer.m_outBuffer = null;
+ }
+
+ public int read() throws IOException
+ {
+ if ((m_output == null) && (m_buffer == null))
+ {
+ return -1;
+ }
+
+ if (m_buffer != null)
+ {
+ int result = m_buffer.read();
+
+ if (result == -1)
+ {
+ m_buffer = null;
+ return read();
+ }
+
+ return result;
+ }
+
+ if (m_content.hasMoreElements())
+ {
+ String current = (String) m_content.nextElement();
+
+ readNext(current);
+
+ if (!m_content.hasMoreElements())
+ {
+ m_output.close();
+ m_output = null;
+ }
+
+ m_buffer = new ByteArrayInputStream(m_outputBuffer.m_outBuffer
+ .toByteArray());
+
+ m_outputBuffer.m_outBuffer = null;
+ }
+ else
+ {
+ m_output.close();
+ m_output = null;
+ }
+
+ return read();
+ }
+
+ private void readNext(String path) throws IOException
+ {
+ m_outputBuffer.m_outBuffer = new ByteArrayOutputStream();
+
+ if (path == DUMMY_ENTRY)
+ {
+ JarEntry entry = new JarEntry(path);
+
+ m_output.putNextEntry(entry);
+ }
+ else
+ {
+ InputStream in = null;
+ try
+ {
+ in = m_root.getEntryAsStream(path);
+
+ if (in == null)
+ {
+ throw new IOException("Missing entry");
+ }
+
+ JarEntry entry = new JarEntry(path);
+
+ m_output.putNextEntry(entry);
+
+ byte[] buffer = new byte[4 * 1024];
+
+ for (int c = in.read(buffer); c != -1; c = in.read(buffer))
+ {
+ m_output.write(buffer, 0, c);
+ }
+ }
+ finally
+ {
+ if (in != null)
+ {
+ try
+ {
+ in.close();
+ }
+ catch (Exception ex)
+ {
+ // Not much we can do
+ }
+ }
+ }
+ }
+
+ m_output.closeEntry();
+
+ m_output.flush();
+ }
+ }
+
+ private static final class OutputStreamBuffer extends OutputStream
+ {
+ ByteArrayOutputStream m_outBuffer = null;
+
+ public void write(int b)
+ {
+ m_outBuffer.write(b);
+ }
+
+ public void write(byte[] buffer) throws IOException
+ {
+ m_outBuffer.write(buffer);
+ }
+
+ public void write(byte[] buffer, int offset, int length)
+ {
+ m_outBuffer.write(buffer, offset, length);
+ }
+ }
+
+ private static final class RevisionAsJarURL extends URLStreamHandler
+ {
+ private final WeakReference m_revision;
+
+ private RevisionAsJarURL(BundleRevisionImpl revision)
+ {
+ m_revision = new WeakReference(revision);
+ }
+
+
+ @Override
+ protected URLConnection openConnection(URL u) throws IOException
+ {
+ return new JarURLConnection(u)
+ {
+ @Override
+ public JarFile getJarFile() throws IOException
+ {
+ BundleRevisionImpl revision = (BundleRevisionImpl) m_revision.get();
+
+ if (revision != null)
+ {
+ Content content = ((BundleRevisionImpl) m_revision.get()).getContent();
+ if (content instanceof JarContent)
+ {
+ return Felix.m_secureAction.openJarFile(((JarContent) content).getFile());
+ }
+ else
+ {
+ File target = Felix.m_secureAction.createTempFile("jar", null, null);
+ Felix.m_secureAction.deleteFileOnExit(target);
+ FileOutputStream output = null;
+ InputStream input = null;
+ IOException rethrow = null;
+ try
+ {
+ output = new FileOutputStream(target);
+ input = new BundleInputStream(revision.getContent());
+ byte[] buffer = new byte[64 * 1024];
+ for (int i = input.read(buffer);i != -1; i = input.read(buffer))
+ {
+ output.write(buffer,0, i);
+ }
+ }
+ catch (IOException ex)
+ {
+ rethrow = ex;
+ }
+ finally
+ {
+ if (output != null)
+ {
+ try
+ {
+ output.close();
+ }
+ catch (IOException ex)
+ {
+ if (rethrow == null)
+ {
+ rethrow = ex;
+ }
+ }
+ }
+
+ if (input != null)
+ {
+ try
+ {
+ input.close();
+ }
+ catch (IOException ex)
+ {
+ if (rethrow == null)
+ {
+ rethrow = ex;
+ }
+ }
+ }
+
+ if (rethrow != null)
+ {
+ throw rethrow;
+ }
+ }
+ return Felix.m_secureAction.openJarFile(target);
+ }
+ }
+ throw new IOException("Unable to access bundle revision.");
+ }
+
+ @Override
+ public void connect() throws IOException
+ {
+
+ }
+ };
+ }
+
+ private static URL create(BundleImpl bundle) throws MalformedURLException
+ {
+ String location = bundle._getLocation();
+
+ if (location.startsWith("reference:"))
+ {
+ location = location.substring("reference:".length());
+ }
+
+ BundleRevisionImpl revision = bundle.adapt(BundleRevisionImpl.class);
+ RevisionAsJarURL handler = new RevisionAsJarURL(revision);
+
+ URL url;
+ try
+ {
+ url = Felix.m_secureAction.createURL(
+ Felix.m_secureAction.createURL(null, "jar:", handler), location, null);
+ }
+ catch (MalformedURLException ex)
+ {
+ url = null;
+ }
+
+ if (url != null && !url.getProtocol().equalsIgnoreCase("jar"))
+ {
+ return url;
+ }
+ else if (url == null)
+ {
+ location = "jar:" + revision.getEntry("/") + "!/";
+ }
+
+ return Felix.m_secureAction.createURL(
+ Felix.m_secureAction.createURL(null, "jar:", handler),
+ location,
+ handler
+ );
+ }
+ }
+
private final WeakReference m_felix;
private final WeakReference m_bundle;
private final int m_hashCode;
private final String m_toString;
private final WeakReference m_revision;
+ private volatile PermissionCollection m_woven;
- // TODO: SECURITY - This should probably take a revision, not a bundle.
BundleProtectionDomain(Felix felix, BundleImpl bundle, Object certificates)
throws MalformedURLException
{
super(
new CodeSource(
- Felix.m_secureAction.createURL(
- Felix.m_secureAction.createURL(null, "location:", new FakeURLStreamHandler()),
- bundle._getLocation().startsWith("reference:") ?
- bundle._getLocation().substring("reference:".length()) :
- bundle._getLocation(),
- new FakeURLStreamHandler()
- ),
+ RevisionAsJarURL.create(bundle),
(Certificate[]) certificates),
null, null, null);
m_felix = new WeakReference(felix);
@@ -81,6 +416,20 @@ public class BundleProtectionDomain extends ProtectionDomain
felix.impliesBundlePermission(this, permission, true) : false;
}
+ boolean impliesWoven(Permission permission)
+ {
+ return m_woven != null && m_woven.implies(permission);
+ }
+
+ synchronized void addWoven(String s)
+ {
+ if (m_woven == null)
+ {
+ m_woven = new Permissions();
+ }
+ m_woven.add(new PackagePermission(s, PackagePermission.IMPORT));
+ }
+
BundleImpl getBundle()
{
return (BundleImpl) m_bundle.get();
diff --git a/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java b/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java
index bc8de71..01bf4b8 100644
--- a/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java
+++ b/src/main/java/org/apache/felix/framework/BundleRevisionImpl.java
@@ -28,12 +28,13 @@ import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
+
import org.apache.felix.framework.cache.Content;
import org.apache.felix.framework.util.FelixConstants;
import org.apache.felix.framework.util.SecureAction;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.manifestparser.ManifestParser;
-import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.apache.felix.framework.util.manifestparser.NativeLibrary;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
@@ -62,7 +63,7 @@ public class BundleRevisionImpl implements BundleRevision, Resource
private final List<BundleCapability> m_declaredCaps;
private final List<BundleRequirement> m_declaredReqs;
- private final List<R4Library> m_declaredNativeLibs;
+ private final List<NativeLibrary> m_declaredNativeLibs;
private final int m_declaredActivationPolicy;
private final List<String> m_activationIncludes;
private final List<String> m_activationExcludes;
@@ -126,7 +127,7 @@ public class BundleRevisionImpl implements BundleRevision, Resource
// system bundle directly later on.
m_manifestVersion = mp.getManifestVersion();
m_version = mp.getBundleVersion();
- m_declaredCaps = mp.isExtension() ? Collections.EMPTY_LIST : mp.getCapabilities();
+ m_declaredCaps = mp.getCapabilities();
m_declaredReqs = mp.getRequirements();
m_declaredNativeLibs = mp.getLibraries();
m_declaredActivationPolicy = mp.getActivationPolicy();
@@ -282,7 +283,7 @@ public class BundleRevisionImpl implements BundleRevision, Resource
return m_manifestVersion;
}
- public List<R4Library> getDeclaredNativeLibraries()
+ public List<NativeLibrary> getDeclaredNativeLibraries()
{
return m_declaredNativeLibs;
}
@@ -371,7 +372,11 @@ public class BundleRevisionImpl implements BundleRevision, Resource
List<Content> fragmentContents = null;
if (m_wiring != null)
{
- fragments = Util.getFragments(m_wiring);
+ // Get fragments and their contents from the wiring.
+ // Note that we don't use Util.getFragments() here because
+ // the wiring returns parallel arrays and the utility method
+ // doesn't necessarily return the correct order.
+ fragments = m_wiring.getFragments();
fragmentContents = m_wiring.getFragmentContents();
}
if (fragments != null)
diff --git a/src/main/java/org/apache/felix/framework/BundleWiringImpl.java b/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
index beecd41..8e984cd 100644
--- a/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
+++ b/src/main/java/org/apache/felix/framework/BundleWiringImpl.java
@@ -52,7 +52,7 @@ import org.apache.felix.framework.util.ImmutableList;
import org.apache.felix.framework.util.SecurityManagerEx;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.manifestparser.ManifestParser;
-import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.apache.felix.framework.util.manifestparser.NativeLibrary;
import org.apache.felix.framework.wiring.BundleRequirementImpl;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
@@ -64,6 +64,8 @@ import org.osgi.framework.PackagePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.hooks.weaving.WeavingException;
import org.osgi.framework.hooks.weaving.WeavingHook;
+import org.osgi.framework.hooks.weaving.WovenClass;
+import org.osgi.framework.hooks.weaving.WovenClassListener;
import org.osgi.framework.namespace.IdentityNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
@@ -97,7 +99,7 @@ public class BundleWiringImpl implements BundleWiring
private final Map<String, List<List<String>>> m_includedPkgFilters;
private final Map<String, List<List<String>>> m_excludedPkgFilters;
private final List<BundleRequirement> m_resolvedReqs;
- private final List<R4Library> m_resolvedNativeLibs;
+ private final List<NativeLibrary> m_resolvedNativeLibs;
private final List<Content> m_fragmentContents;
private volatile List<BundleRequirement> m_wovenReqs = null;
@@ -399,14 +401,14 @@ public class BundleWiringImpl implements BundleWiring
m_excludedPkgFilters = (excludedPkgFilters.isEmpty())
? Collections.EMPTY_MAP : excludedPkgFilters;
- List<R4Library> libList = (m_revision.getDeclaredNativeLibraries() == null)
- ? new ArrayList<R4Library>()
- : new ArrayList<R4Library>(m_revision.getDeclaredNativeLibraries());
+ List<NativeLibrary> libList = (m_revision.getDeclaredNativeLibraries() == null)
+ ? new ArrayList<NativeLibrary>()
+ : new ArrayList<NativeLibrary>(m_revision.getDeclaredNativeLibraries());
for (int fragIdx = 0;
(m_fragments != null) && (fragIdx < m_fragments.size());
fragIdx++)
{
- List<R4Library> libs =
+ List<NativeLibrary> libs =
((BundleRevisionImpl) m_fragments.get(fragIdx))
.getDeclaredNativeLibraries();
for (int reqIdx = 0;
@@ -501,6 +503,11 @@ public class BundleWiringImpl implements BundleWiring
return m_importedPkgs.get(pkgName);
}
+ List<BundleRevision> getFragments()
+ {
+ return m_fragments;
+ }
+
List<Content> getFragmentContents()
{
return m_fragmentContents;
@@ -579,14 +586,14 @@ public class BundleWiringImpl implements BundleWiring
return null;
}
- public List<R4Library> getNativeLibraries()
+ public List<NativeLibrary> getNativeLibraries()
{
return m_resolvedNativeLibs;
}
private static List<Wire> asWireList(List wires)
{
- return (List<Wire>) wires;
+ return wires;
}
public List<Wire> getProvidedResourceWires(String namespace)
@@ -701,11 +708,11 @@ public class BundleWiringImpl implements BundleWiring
// enabled; otherwise, create it directly.
try
{
- Constructor ctor = (Constructor) BundleRevisionImpl.getSecureAction()
- .getConstructor(clazz, new Class[] { BundleWiringImpl.class, ClassLoader.class });
+ Constructor ctor = BundleRevisionImpl.getSecureAction()
+ .getConstructor(clazz, new Class[] { BundleWiringImpl.class, ClassLoader.class, Logger.class });
m_classLoader = (BundleClassLoader)
BundleRevisionImpl.getSecureAction().invoke(ctor,
- new Object[] { this, determineParentClassLoader() });
+ new Object[] { this, determineParentClassLoader(), m_logger });
}
catch (Exception ex)
{
@@ -1516,11 +1523,11 @@ public class BundleWiringImpl implements BundleWiring
+ m_revision.getSymbolicName()
+ " is no longer valid.");
}
- result = (Object) ((BundleClassLoader) cl).findClass(name);
+ result = ((BundleClassLoader) cl).findClass(name);
}
else
{
- result = (Object) m_revision.getResourceLocal(name);
+ result = m_revision.getResourceLocal(name);
}
// If still not found, then try the revision's dynamic imports.
@@ -1878,6 +1885,7 @@ public class BundleWiringImpl implements BundleWiring
m_isParallel = registered;
}
+ @Override
protected boolean isParallel()
{
return m_isParallel;
@@ -1885,9 +1893,9 @@ public class BundleWiringImpl implements BundleWiring
private final BundleWiringImpl m_wiring;
- public BundleClassLoaderJava5(BundleWiringImpl wiring, ClassLoader parent)
+ public BundleClassLoaderJava5(BundleWiringImpl wiring, ClassLoader parent, Logger logger)
{
- super(wiring, parent);
+ super(wiring, parent, logger);
m_wiring = wiring;
}
@@ -1938,8 +1946,9 @@ public class BundleWiringImpl implements BundleWiring
private static final int LIBPATH_IDX = 1;
private final Map<String, Thread> m_classLocks = new HashMap<String, Thread>();
private final BundleWiringImpl m_wiring;
+ private final Logger m_logger;
- public BundleClassLoader(BundleWiringImpl wiring, ClassLoader parent)
+ public BundleClassLoader(BundleWiringImpl wiring, ClassLoader parent, Logger logger)
{
super(parent);
if (m_dexFileClassLoadClass != null)
@@ -1951,6 +1960,7 @@ public class BundleWiringImpl implements BundleWiring
m_jarContentToDexFile = null;
}
m_wiring = wiring;
+ m_logger = logger;
}
protected boolean isParallel()
@@ -1995,7 +2005,7 @@ public class BundleWiringImpl implements BundleWiring
catch (ClassNotFoundException cnfe)
{
ClassNotFoundException ex = cnfe;
- if (m_wiring.m_logger.getLogLevel() >= Logger.LOG_DEBUG)
+ if (m_logger.getLogLevel() >= Logger.LOG_DEBUG)
{
String msg = diagnoseClassLoadError(m_wiring.m_resolver, m_wiring.m_revision, name);
ex = (msg != null)
@@ -2065,58 +2075,32 @@ public class BundleWiringImpl implements BundleWiring
// as a race condition, doing any necessary clean up in
// the error handling.
Felix felix = ((BundleImpl) m_wiring.m_revision.getBundle()).getFramework();
+
Set<ServiceReference<WeavingHook>> hooks =
felix.getHooks(WeavingHook.class);
+
+ Set<ServiceReference<WovenClassListener>> wovenClassListeners =
+ felix.getHooks(WovenClassListener.class);
+
WovenClassImpl wci = null;
if (!hooks.isEmpty())
{
// Create woven class to be used for hooks.
wci = new WovenClassImpl(name, m_wiring, bytes);
- // Loop through hooks in service ranking order.
- for (ServiceReference<WeavingHook> sr : hooks)
+ try
{
- // Only use the hook if it is not black listed.
- if (!felix.isHookBlackListed(sr))
- {
- // Get the hook service object.
- // Note that we don't use the bundle context
- // to get the service object since that would
- // perform sercurity checks.
- WeavingHook wh = felix.getService(felix, sr);
- if (wh != null)
- {
- try
- {
- BundleRevisionImpl.getSecureAction()
- .invokeWeavingHook(wh, wci);
- }
- catch (Throwable th)
- {
- if (!(th instanceof WeavingException))
- {
- felix.blackListHook(sr);
- }
- felix.fireFrameworkEvent(
- FrameworkEvent.ERROR,
- sr.getBundle(),
- th);
-
- // Mark the woven class as incomplete.
- wci.complete(null, null, null);
- // Throw class format exception per spec.
- Error error = new ClassFormatError("Weaving hook failed.");
- error.initCause(th);
- throw error;
- }
- finally
- {
- felix.ungetService(felix, sr);
- }
- }
- }
+ transformClass(felix, wci, hooks, wovenClassListeners,
+ name, bytes);
+ }
+ catch (Error e)
+ {
+ // Mark the woven class as incomplete.
+ wci.complete(null, null, null);
+ wci.setState(WovenClass.TRANSFORMING_FAILED);
+ callWovenClassListeners(felix, wovenClassListeners, wci);
+ throw e;
}
}
-
// Before we actually attempt to define the class, grab
// the lock for this class loader and make sure than no
// other thread has defined this class in the meantime.
@@ -2145,240 +2129,329 @@ public class BundleWiringImpl implements BundleWiring
}
}
- byte[] wovenBytes = null;
- Class wovenClass = null;
- List<String> wovenImports = null;
try
{
- if (clazz == null)
+ clazz = defineClass(felix, wovenClassListeners, wci, name,
+ clazz, bytes, content, pkgName, lock);
+ }
+ catch (ClassFormatError e)
+ {
+ if(wci != null)
+ {
+ wci.setState(WovenClass.DEFINE_FAILED);
+ callWovenClassListeners(felix, wovenClassListeners, wci);
+ }
+ throw e;
+ }
+
+ // Perform deferred activation without holding the class loader lock,
+ // if the class we are returning is the instigating class.
+ List deferredList = (List) m_deferredActivation.get();
+ if ((deferredList != null)
+ && (deferredList.size() > 0)
+ && ((Object[]) deferredList.get(0))[0].equals(name))
+ {
+ // Null the deferred list.
+ m_deferredActivation.set(null);
+ while (!deferredList.isEmpty())
{
- // If we have a woven class then get the class bytes from
- // it since they may have changed.
- // NOTE: We are taking a snapshot of these values and
- // are not preventing a malbehaving weaving hook from
- // modifying them after the fact. The price of preventing
- // this isn't worth it, since they can already wreck
- // havoc via weaving anyway. However, we do pass the
- // snapshot values into the woven class when we mark it
- // as complete so that it will refect the actual values
- // we used to define the class.
- if (wci != null)
+ // Lazy bundles should be activated in the reverse order
+ // of when they were added to the deferred list, so grab
+ // them from the end of the deferred list.
+ Object[] lazy = (Object[]) deferredList.remove(deferredList.size() - 1);
+ try
{
- bytes = wovenBytes = wci._getBytes();
- wovenImports = wci.getDynamicImportsInternal();
-
- // Try to add any woven dynamic imports, since they
- // could potentially be needed when defining the class.
- List<BundleRequirement> allWovenReqs =
- new ArrayList<BundleRequirement>();
- for (String s : wovenImports)
- {
- try
- {
- List<BundleRequirement> wovenReqs =
- ManifestParser.parseDynamicImportHeader(
- m_wiring.m_logger, m_wiring.m_revision, s);
- allWovenReqs.addAll(wovenReqs);
- }
- catch (BundleException ex)
- {
- // There should be no exception here
- // since we checked syntax before adding
- // dynamic import strings to list.
- }
- }
- // Add the dynamic requirements.
- if (!allWovenReqs.isEmpty())
- {
- // Check for duplicate woven imports.
- // First grab existing woven imports, if any.
- Set<String> filters = new HashSet<String>();
- if (m_wiring.m_wovenReqs != null)
- {
- for (BundleRequirement req : m_wiring.m_wovenReqs)
- {
- filters.add(
- ((BundleRequirementImpl) req)
- .getFilter().toString());
- }
- }
- // Then check new woven imports for duplicates
- // against existing and self.
- int idx = allWovenReqs.size();
- while (idx < allWovenReqs.size())
- {
- BundleRequirement wovenReq = allWovenReqs.get(idx);
- String filter = ((BundleRequirementImpl)
- wovenReq).getFilter().toString();
- if (!filters.contains(filter))
- {
- filters.add(filter);
- idx++;
- }
- else
- {
- allWovenReqs.remove(idx);
- }
- }
- // Merge existing with new imports, if any.
- if (!allWovenReqs.isEmpty())
- {
- if (m_wiring.m_wovenReqs != null)
- {
- allWovenReqs.addAll(0, m_wiring.m_wovenReqs);
- }
- m_wiring.m_wovenReqs = allWovenReqs;
- }
- }
+ felix.getFramework().activateBundle((BundleImpl) (lazy)[1], true);
}
+ catch (Throwable ex)
+ {
+ m_logger.log((BundleImpl) (lazy)[1],
+ Logger.LOG_WARNING,
+ "Unable to lazily start bundle.",
+ ex);
+ }
+ }
+ }
+ }
+ }
- int activationPolicy =
- ((BundleImpl) getBundle()).isDeclaredActivationPolicyUsed()
- ? ((BundleRevisionImpl) getBundle()
- .adapt(BundleRevision.class)).getDeclaredActivationPolicy()
- : EAGER_ACTIVATION;
+ return clazz;
+ }
+
+ Class defineClass(Felix felix,
+ Set<ServiceReference<WovenClassListener>> wovenClassListeners,
+ WovenClassImpl wci, String name, Class clazz, byte[] bytes,
+ Content content, String pkgName, Object lock)
+ throws ClassFormatError
+ {
- // If the revision is using deferred activation, then if
- // we load this class from this revision we need to activate
- // the bundle before returning the class. We will short
- // circuit the trigger matching if the trigger is already
- // tripped.
- boolean isTriggerClass = m_isActivationTriggered
- ? false : m_wiring.m_revision.isActivationTrigger(pkgName);
- if (!m_isActivationTriggered
- && isTriggerClass
- && (activationPolicy == BundleRevisionImpl.LAZY_ACTIVATION)
- && (getBundle().getState() == Bundle.STARTING))
+ try
+ {
+ if (clazz == null)
+ {
+ // If we have a woven class then get the class bytes from
+ // it since they may have changed.
+ // NOTE: We are taking a snapshot of these values and
+ // are not preventing a malbehaving weaving hook from
+ // modifying them after the fact. The price of preventing
+ // this isn't worth it, since they can already wreck
+ // havoc via weaving anyway. However, we do pass the
+ // snapshot values into the woven class when we mark it
+ // as complete so that it will refect the actual values
+ // we used to define the class.
+ if (wci != null)
+ {
+ bytes = wci._getBytes();
+ List<String> wovenImports = wci.getDynamicImportsInternal();
+
+ // Try to add any woven dynamic imports, since they
+ // could potentially be needed when defining the class.
+ List<BundleRequirement> allWovenReqs =
+ new ArrayList<BundleRequirement>();
+ for (String s : wovenImports)
+ {
+ try
{
- List deferredList = (List) m_deferredActivation.get();
- if (deferredList == null)
- {
- deferredList = new ArrayList();
- m_deferredActivation.set(deferredList);
- }
- deferredList.add(new Object[] { name, getBundle() });
+ List<BundleRequirement> wovenReqs =
+ ManifestParser.parseDynamicImportHeader(
+ m_logger, m_wiring.m_revision, s);
+ allWovenReqs.addAll(wovenReqs);
}
- // We need to try to define a Package object for the class
- // before we call defineClass() if we haven't already
- // created it.
- if (pkgName.length() > 0)
+ catch (BundleException ex)
{
- if (getPackage(pkgName) == null)
+ // There should be no exception here
+ // since we checked syntax before adding
+ // dynamic import strings to list.
+ }
+ }
+ // Add the dynamic requirements.
+ if (!allWovenReqs.isEmpty())
+ {
+ // Check for duplicate woven imports.
+ // First grab existing woven imports, if any.
+ Set<String> filters = new HashSet<String>();
+ if (m_wiring.m_wovenReqs != null)
+ {
+ for (BundleRequirement req : m_wiring.m_wovenReqs)
{
- Object[] params = definePackage(pkgName);
-
- // This is a harmless check-then-act situation,
- // where threads might be racing to create different
- // classes in the same package, so catch and ignore
- // any IAEs that may occur.
- try
- {
- definePackage(
- pkgName,
- (String) params[0],
- (String) params[1],
- (String) params[2],
- (String) params[3],
- (String) params[4],
- (String) params[5],
- null);
- }
- catch (IllegalArgumentException ex)
- {
- // Ignore.
- }
+ filters.add(
+ ((BundleRequirementImpl) req)
+ .getFilter().toString());
}
}
-
- // If we can load the class from a dex file do so
- if (content instanceof JarContent)
+ // Then check new woven imports for duplicates
+ // against existing and self.
+ int idx = allWovenReqs.size();
+ while (idx < allWovenReqs.size())
{
- try
+ BundleRequirement wovenReq = allWovenReqs.get(idx);
+ String filter = ((BundleRequirementImpl)
+ wovenReq).getFilter().toString();
+ if (!filters.contains(filter))
{
- clazz = getDexFileClass((JarContent) content, name, this);
+ filters.add(filter);
+ idx++;
}
- catch (Exception ex)
+ else
{
- // Looks like we can't
+ allWovenReqs.remove(idx);
}
}
-
- if (clazz == null)
+ // Merge existing with new imports, if any.
+ if (!allWovenReqs.isEmpty())
{
- // If we have a security context, then use it to
- // define the class with it for security purposes,
- // otherwise define the class without a protection domain.
- if (m_wiring.m_revision.getProtectionDomain() != null)
+ if (m_wiring.m_wovenReqs != null)
{
- clazz = defineClass(name, bytes, 0, bytes.length,
- m_wiring.m_revision.getProtectionDomain());
+ allWovenReqs.addAll(0, m_wiring.m_wovenReqs);
}
- else
- {
- clazz = defineClass(name, bytes, 0, bytes.length);
- }
-
- wovenClass = clazz;
+ m_wiring.m_wovenReqs = allWovenReqs;
}
+ }
+ }
+
+ int activationPolicy =
+ ((BundleImpl) getBundle()).isDeclaredActivationPolicyUsed()
+ ? ((BundleRevisionImpl) getBundle()
+ .adapt(BundleRevision.class)).getDeclaredActivationPolicy()
+ : EAGER_ACTIVATION;
- // At this point if we have a trigger class, then the deferred
- // activation trigger has tripped.
- if (!m_isActivationTriggered && isTriggerClass && (clazz != null))
+ // If the revision is using deferred activation, then if
+ // we load this class from this revision we need to activate
+ // the bundle before returning the class. We will short
+ // circuit the trigger matching if the trigger is already
+ // tripped.
+ boolean isTriggerClass = m_isActivationTriggered
+ ? false : m_wiring.m_revision.isActivationTrigger(pkgName);
+ if (!m_isActivationTriggered
+ && isTriggerClass
+ && (activationPolicy == BundleRevisionImpl.LAZY_ACTIVATION)
+ && (getBundle().getState() == Bundle.STARTING))
+ {
+ List deferredList = (List) m_deferredActivation.get();
+ if (deferredList == null)
+ {
+ deferredList = new ArrayList();
+ m_deferredActivation.set(deferredList);
+ }
+ deferredList.add(new Object[] { name, getBundle() });
+ }
+ // We need to try to define a Package object for the class
+ // before we call defineClass() if we haven't already
+ // created it.
+ if (pkgName.length() > 0)
+ {
+ if (getPackage(pkgName) == null)
+ {
+ Object[] params = definePackage(pkgName);
+
+ // This is a harmless check-then-act situation,
+ // where threads might be racing to create different
+ // classes in the same package, so catch and ignore
+ // any IAEs that may occur.
+ try
+ {
+ definePackage(
+ pkgName,
+ (String) params[0],
+ (String) params[1],
+ (String) params[2],
+ (String) params[3],
+ (String) params[4],
+ (String) params[5],
+ null);
+ }
+ catch (IllegalArgumentException ex)
{
- m_isActivationTriggered = true;
+ // Ignore.
}
}
}
- finally
+
+ // If we can load the class from a dex file do so
+ if (content instanceof JarContent)
{
- // If we have a woven class, mark it as complete.
- // Not exactly clear how we should deal with the
- // case where the weaving didn't happen because
- // someone else beat us in defining the class.
- if (wci != null)
+ try
+ {
+ clazz = getDexFileClass((JarContent) content, name, this);
+ }
+ catch (Exception ex)
{
- wci.complete(wovenClass, wovenBytes, wovenImports);
+ // Looks like we can't
}
+ }
- synchronized (lock)
+ if (clazz == null)
+ {
+ // If we have a security context, then use it to
+ // define the class with it for security purposes,
+ // otherwise define the class without a protection domain.
+ if (m_wiring.m_revision.getProtectionDomain() != null)
{
- m_classLocks.remove(name);
- lock.notifyAll();
+ clazz = defineClass(name, bytes, 0, bytes.length,
+ m_wiring.m_revision.getProtectionDomain());
+ }
+ else
+ {
+ clazz = defineClass(name, bytes, 0, bytes.length);
+ }
+ if(wci != null)
+ {
+ wci.completeDefine(clazz);
+ wci.setState(WovenClass.DEFINED);
+ callWovenClassListeners(felix, wovenClassListeners, wci);
}
}
- // Perform deferred activation without holding the class loader lock,
- // if the class we are returning is the instigating class.
- List deferredList = (List) m_deferredActivation.get();
- if ((deferredList != null)
- && (deferredList.size() > 0)
- && ((Object[]) deferredList.get(0))[0].equals(name))
+ // At this point if we have a trigger class, then the deferred
+ // activation trigger has tripped.
+ if (!m_isActivationTriggered && isTriggerClass && (clazz != null))
{
- // Null the deferred list.
- m_deferredActivation.set(null);
- while (!deferredList.isEmpty())
+ m_isActivationTriggered = true;
+ }
+ }
+ }
+ finally
+ {
+ synchronized (lock)
+ {
+ m_classLocks.remove(name);
+ lock.notifyAll();
+ }
+ }
+ return clazz;
+ }
+
+ void transformClass(Felix felix, WovenClassImpl wci,
+ Set<ServiceReference<WeavingHook>> hooks,
+ Set<ServiceReference<WovenClassListener>> wovenClassListeners,
+ String name, byte[] bytes) throws Error {
+
+ // Loop through hooks in service ranking order.
+ for (ServiceReference<WeavingHook> sr : hooks)
+ {
+ // Only use the hook if it is not black listed.
+ if (!felix.isHookBlackListed(sr))
+ {
+ // Get the hook service object.
+ // Note that we don't use the bundle context
+ // to get the service object since that would
+ // perform sercurity checks.
+ WeavingHook wh = felix.getService(felix, sr, false);
+ if (wh != null)
+ {
+ try
{
- // Lazy bundles should be activated in the reverse order
- // of when they were added to the deferred list, so grab
- // them from the end of the deferred list.
- Object[] lazy = (Object[]) deferredList.remove(deferredList.size() - 1);
- try
- {
- felix.getFramework().activateBundle((BundleImpl) (lazy)[1], true);
- }
- catch (Throwable ex)
+ BundleRevisionImpl.getSecureAction()
+ .invokeWeavingHook(wh, wci);
+ }
+ catch (Throwable th)
+ {
+ if (!(th instanceof WeavingException))
{
- m_wiring.m_logger.log((BundleImpl) (lazy)[1],
- Logger.LOG_WARNING,
- "Unable to lazily start bundle.",
- ex);
+ felix.blackListHook(sr);
}
+ felix.fireFrameworkEvent(
+ FrameworkEvent.ERROR,
+ sr.getBundle(),
+ th);
+
+ // Throw class format exception per spec.
+ Error error = new ClassFormatError("Weaving hook failed.");
+ error.initCause(th);
+ throw error;
+ }
+ finally
+ {
+ felix.ungetService(felix, sr, null);
}
}
}
}
+ wci.setState(WovenClass.TRANSFORMED);
+ callWovenClassListeners(felix, wovenClassListeners, wci);
+ }
- return clazz;
+ protected void callWovenClassListeners(Felix felix, Set<ServiceReference<WovenClassListener>> wovenClassListeners, WovenClass wovenClass)
+ {
+ if(wovenClassListeners != null)
+ {
+ for(ServiceReference<WovenClassListener> currentWovenClassListenerRef : wovenClassListeners)
+ {
+ WovenClassListener currentWovenClassListner = felix.getService(felix, currentWovenClassListenerRef, false);
+ try
+ {
+ BundleRevisionImpl.getSecureAction().invokeWovenClassListener(currentWovenClassListner, wovenClass);
+ }
+ catch (Exception e)
+ {
+ m_logger.log(Logger.LOG_ERROR, "Woven Class Listner failed.", e);
+ }
+ finally
+ {
+ felix.ungetService(felix, currentWovenClassListenerRef, null);
+ }
+ }
+ }
}
private Object[] definePackage(String pkgName)
@@ -2508,7 +2581,7 @@ public class BundleWiringImpl implements BundleWiring
// native library.
if (result == null)
{
- List<R4Library> libs = m_wiring.getNativeLibraries();
+ List<NativeLibrary> libs = m_wiring.getNativeLibraries();
for (int libIdx = 0; (libs != null) && (libIdx < libs.size()); libIdx++)
{
if (libs.get(libIdx).match(m_wiring.m_configMap, name))
diff --git a/src/main/java/org/apache/felix/framework/DTOFactory.java b/src/main/java/org/apache/felix/framework/DTOFactory.java
new file mode 100644
index 0000000..e3cb64f
--- /dev/null
+++ b/src/main/java/org/apache/felix/framework/DTOFactory.java
@@ -0,0 +1,480 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.Version;
+import org.osgi.framework.dto.BundleDTO;
+import org.osgi.framework.dto.FrameworkDTO;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
+import org.osgi.framework.startlevel.dto.FrameworkStartLevelDTO;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleRevisions;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.framework.wiring.dto.BundleRevisionDTO;
+import org.osgi.framework.wiring.dto.BundleWireDTO;
+import org.osgi.framework.wiring.dto.BundleWiringDTO;
+import org.osgi.framework.wiring.dto.BundleWiringDTO.NodeDTO;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.resource.Wire;
+import org.osgi.resource.Wiring;
+import org.osgi.resource.dto.CapabilityDTO;
+import org.osgi.resource.dto.CapabilityRefDTO;
+import org.osgi.resource.dto.RequirementDTO;
+import org.osgi.resource.dto.RequirementRefDTO;
+import org.osgi.resource.dto.WireDTO;
+
+/**
+ * Creates various DTOs provided by the core framework.
+ */
+public class DTOFactory
+{
+ private DTOFactory()
+ {
+ // Only static methods
+ }
+
+ static <T> T createDTO(Bundle bundle, Class<T> type)
+ {
+ if (Bundle.UNINSTALLED == bundle.getState())
+ return null;
+
+ if (type == BundleDTO.class)
+ {
+ return type.cast(createBundleDTO(bundle));
+ }
+ else if (type == BundleStartLevelDTO.class)
+ {
+ return type.cast(createBundleStartLevelDTO(bundle));
+ }
+ else if (type == BundleRevisionDTO.class)
+ {
+ return type.cast(createBundleRevisionDTO(bundle));
+ }
+ else if (type == BundleRevisionDTO[].class)
+ {
+ return type.cast(createBundleRevisionDTOArray(bundle));
+ }
+ else if (type == BundleWiringDTO.class)
+ {
+ return type.cast(createBundleWiringDTO(bundle));
+ }
+ else if (type == BundleWiringDTO[].class)
+ {
+ return type.cast(createBundleWiringDTOArray(bundle));
+ }
+ else if (type == ServiceReferenceDTO[].class)
+ {
+ return type.cast(createServiceReferenceDTOArray(bundle));
+ }
+ else if (type == FrameworkDTO.class && bundle instanceof Felix)
+ {
+ return type.cast(createFrameworkDTO((Felix) bundle));
+ }
+ else if (type == FrameworkStartLevelDTO.class && bundle instanceof Framework)
+ {
+ return type.cast(createFrameworkStartLevelDTO((Framework) bundle));
+ }
+ return null;
+ }
+
+ private static BundleDTO createBundleDTO(Bundle bundle)
+ {
+ BundleDTO dto = new BundleDTO();
+ dto.id = bundle.getBundleId();
+ dto.lastModified = bundle.getLastModified();
+ dto.state = bundle.getState();
+ dto.symbolicName = bundle.getSymbolicName();
+ dto.version = "" + bundle.getVersion();
+ return dto;
+ }
+
+ private static BundleRevisionDTO createBundleRevisionDTO(Bundle bundle)
+ {
+ BundleRevision br = bundle.adapt(BundleRevision.class);
+ if (!(br instanceof BundleRevisionImpl))
+ return null;
+
+ return createBundleRevisionDTO(bundle, (BundleRevisionImpl) br, new HashSet<BundleRevisionDTO>());
+ }
+
+ private static BundleRevisionDTO[] createBundleRevisionDTOArray(Bundle bundle)
+ {
+ BundleRevisions brs = bundle.adapt(BundleRevisions.class);
+ if (brs == null || brs.getRevisions() == null)
+ return null;
+
+ List<BundleRevision> revisions = brs.getRevisions();
+ BundleRevisionDTO[] dtos = new BundleRevisionDTO[revisions.size()];
+ for (int i=0; i < revisions.size(); i++)
+ {
+ if (revisions.get(i) instanceof BundleRevisionImpl)
+ dtos[i] = createBundleRevisionDTO(bundle, (BundleRevisionImpl) revisions.get(i), new HashSet<BundleRevisionDTO>());
+ }
+ return dtos;
+ }
+
+ private static BundleRevisionDTO createBundleRevisionDTO(BundleRevision revision, Set<BundleRevisionDTO> resources)
+ {
+ if (revision instanceof BundleRevisionImpl)
+ return createBundleRevisionDTO(revision.getBundle(), (BundleRevisionImpl) revision, resources);
+ else
+ return null;
+ }
+
+ private static BundleRevisionDTO createBundleRevisionDTO(Bundle bundle, BundleRevisionImpl revision, Set<BundleRevisionDTO> resources)
+ {
+ BundleRevisionDTO dto = new BundleRevisionDTO();
+ dto.id = getRevisionID(revision);
+ addBundleRevisionDTO(dto, resources);
+
+ dto.bundle = bundle.getBundleId();
+ dto.symbolicName = revision.getSymbolicName();
+ dto.type = revision.getTypes();
+ dto.version = revision.getVersion().toString();
+
+ dto.capabilities = new ArrayList<CapabilityDTO>();
+ for (Capability cap : revision.getCapabilities(null))
+ {
+ CapabilityDTO cdto = new CapabilityDTO();
+ cdto.id = getCapabilityID(cap);
+ cdto.namespace = cap.getNamespace();
+ cdto.attributes = convertAttrsToDTO(cap.getAttributes());
+ cdto.directives = new HashMap<String, String>(cap.getDirectives());
+ cdto.resource = getResourceIDAndAdd(cap.getResource(), resources);
+
+ dto.capabilities.add(cdto);
+ }
+
+ dto.requirements = new ArrayList<RequirementDTO>();
+ for (Requirement req : revision.getRequirements(null))
+ {
+ RequirementDTO rdto = new RequirementDTO();
+ rdto.id = getRequirementID(req);
+ rdto.namespace = req.getNamespace();
+ rdto.attributes = convertAttrsToDTO(req.getAttributes());
+ rdto.directives = new HashMap<String, String>(req.getDirectives());
+ rdto.resource = getResourceIDAndAdd(req.getResource(), resources);
+
+ dto.requirements.add(rdto);
+ }
+ return dto;
+ }
+
+ private static BundleWiringDTO createBundleWiringDTO(Bundle bundle)
+ {
+ BundleWiring bw = bundle.adapt(BundleWiring.class);
+ return createBundleWiringDTO(bw);
+ }
+
+ private static BundleWiringDTO createBundleWiringDTO(BundleWiring wiring)
+ {
+ BundleWiringDTO dto = new BundleWiringDTO();
+ dto.bundle = wiring.getBundle().getBundleId();
+ dto.root = getWiringID(wiring);
+ dto.nodes = new HashSet<BundleWiringDTO.NodeDTO>();
+ dto.resources = new HashSet<BundleRevisionDTO>();
+
+ createBundleRevisionDTO(wiring.getRevision(), dto.resources);
+ createBundleWiringNodeDTO(wiring, dto.resources, dto.nodes);
+
+ return dto;
+ }
+
+ private static BundleWiringDTO[] createBundleWiringDTOArray(Bundle bundle)
+ {
+ BundleRevisions brs = bundle.adapt(BundleRevisions.class);
+ if (brs == null || brs.getRevisions() == null)
+ return null;
+
+ List<BundleRevision> revisions = brs.getRevisions();
+ BundleWiringDTO[] dtos = new BundleWiringDTO[revisions.size()];
+ for (int i=0; i < revisions.size(); i++)
+ {
+ BundleWiring wiring = revisions.get(i).getWiring();
+ dtos[i] = createBundleWiringDTO(wiring);
+ }
+ return dtos;
+ }
+
+ private static void createBundleWiringNodeDTO(BundleWiring bw, Set<BundleRevisionDTO> resources, Set<NodeDTO> nodes)
+ {
+ NodeDTO node = new BundleWiringDTO.NodeDTO();
+ node.id = getWiringID(bw);
+ nodes.add(node);
+
+ node.current = bw.isCurrent();
+ node.inUse = bw.isInUse();
+ node.resource = getResourceIDAndAdd(bw.getResource(), resources);
+
+ node.capabilities = new ArrayList<CapabilityRefDTO>();
+ for (Capability cap : bw.getCapabilities(null))
+ {
+ CapabilityRefDTO cdto = new CapabilityRefDTO();
+ cdto.capability = getCapabilityID(cap);
+ cdto.resource = getResourceIDAndAdd(cap.getResource(), resources);
+ node.capabilities.add(cdto);
+ }
+
+ node.requirements = new ArrayList<RequirementRefDTO>();
+ for (Requirement req : bw.getRequirements(null))
+ {
+ RequirementRefDTO rdto = new RequirementRefDTO();
+ rdto.requirement = getRequirementID(req);
+ rdto.resource = getResourceIDAndAdd(req.getResource(), resources);
+ node.requirements.add(rdto);
+ }
+
+ node.providedWires = new ArrayList<WireDTO>();
+ for (Wire pw : bw.getProvidedWires(null))
+ {
+ node.providedWires.add(createBundleWireDTO(pw, resources, nodes));
+ }
+
+ node.requiredWires = new ArrayList<WireDTO>();
+ for (Wire rw : bw.getRequiredWires(null))
+ {
+ node.requiredWires.add(createBundleWireDTO(rw, resources, nodes));
+ }
+ }
+
+ private static BundleWireDTO createBundleWireDTO(Wire wire, Set<BundleRevisionDTO> resources, Set<NodeDTO> nodes)
+ {
+ BundleWireDTO wdto = new BundleWireDTO();
+ if (wire instanceof BundleWire)
+ {
+ BundleWire w = (BundleWire) wire;
+
+ BundleWiring pw = w.getProviderWiring();
+ addWiringNodeIfNotPresent(pw, resources, nodes);
+ wdto.providerWiring = getWiringID(pw);
+
+ BundleWiring rw = w.getRequirerWiring();
+ addWiringNodeIfNotPresent(rw, resources, nodes);
+ wdto.requirerWiring = getWiringID(rw);
+ }
+ wdto.provider = getResourceIDAndAdd(wire.getProvider(), resources);
+ wdto.requirer = getResourceIDAndAdd(wire.getRequirer(), resources);
+ wdto.capability = new CapabilityRefDTO();
+ wdto.capability.capability = getCapabilityID(wire.getCapability());
+ wdto.capability.resource = getResourceIDAndAdd(wire.getCapability().getResource(), resources);
+ wdto.requirement = new RequirementRefDTO();
+ wdto.requirement.requirement = getRequirementID(wire.getRequirement());
+ wdto.requirement.resource = getResourceIDAndAdd(wire.getRequirement().getResource(), resources);
+ return wdto;
+ }
+
+ private static BundleStartLevelDTO createBundleStartLevelDTO(Bundle bundle)
+ {
+ BundleStartLevelDTO dto = new BundleStartLevelDTO();
+ dto.bundle = bundle.getBundleId();
+
+ BundleStartLevel sl = bundle.adapt(BundleStartLevel.class);
+ dto.activationPolicyUsed = sl.isActivationPolicyUsed();
+ dto.persistentlyStarted = sl.isPersistentlyStarted();
+ dto.startLevel = sl.getStartLevel();
+
+ return dto;
+ }
+
+ private static ServiceReferenceDTO[] createServiceReferenceDTOArray(Bundle bundle)
+ {
+ BundleContext ctx = bundle.getBundleContext();
+ if (ctx == null)
+ return null;
+
+ ServiceReference<?>[] svcs = bundle.getRegisteredServices();
+ if (svcs == null)
+ return new ServiceReferenceDTO[0];
+
+ ServiceReferenceDTO[] dtos = new ServiceReferenceDTO[svcs.length];
+ for (int i=0; i < svcs.length; i++)
+ {
+ dtos[i] = createServiceReferenceDTO(svcs[i]);
+ }
+ return dtos;
+ }
+
+ private static ServiceReferenceDTO createServiceReferenceDTO(ServiceReference<?> svc)
+ {
+ ServiceReferenceDTO dto = new ServiceReferenceDTO();
+ dto.bundle = svc.getBundle().getBundleId();
+ dto.id = (Long) svc.getProperty(Constants.SERVICE_ID);
+ Map<String, Object> props = new HashMap<String, Object>();
+ for (String key : svc.getPropertyKeys())
+ {
+ props.put(key, svc.getProperty(key));
+ }
+ dto.properties = new HashMap<String, Object>(props);
+
+ Bundle[] ubs = svc.getUsingBundles();
+ if (ubs == null)
+ {
+ dto.usingBundles = new long[0];
+ }
+ else
+ {
+ dto.usingBundles = new long[ubs.length];
+ for (int j=0; j < ubs.length; j++)
+ {
+ dto.usingBundles[j] = ubs[j].getBundleId();
+ }
+ }
+ return dto;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static FrameworkDTO createFrameworkDTO(Felix framework)
+ {
+ FrameworkDTO dto = new FrameworkDTO();
+ dto.properties = framework.getConfig(); // This map is immutable, so it's fine to share
+
+ dto.bundles = new ArrayList<BundleDTO>();
+ for (Bundle b : framework.getBundleContext().getBundles())
+ {
+ dto.bundles.add(DTOFactory.createDTO(b, BundleDTO.class));
+ }
+
+ dto.services = new ArrayList<ServiceReferenceDTO>();
+
+ ServiceReference<?>[] refs = null;
+ try
+ {
+ refs = framework.getBundleContext().getAllServiceReferences(null, null);
+ }
+ catch (InvalidSyntaxException e)
+ {
+ // No filter, should never happen
+ }
+
+ for (ServiceReference<?> sr : refs)
+ {
+ dto.services.add(createServiceReferenceDTO(sr));
+ }
+
+ return dto;
+ }
+
+ private static FrameworkStartLevelDTO createFrameworkStartLevelDTO(Framework framework)
+ {
+ FrameworkStartLevel fsl = framework.adapt(FrameworkStartLevel.class);
+
+ FrameworkStartLevelDTO dto = new FrameworkStartLevelDTO();
+ dto.initialBundleStartLevel = fsl.getInitialBundleStartLevel();
+ dto.startLevel = fsl.getStartLevel();
+
+ return dto;
+ }
+
+ private static void addBundleRevisionDTO(BundleRevisionDTO dto, Set<BundleRevisionDTO> resources)
+ {
+ for (BundleRevisionDTO r : resources)
+ {
+ if (r.id == dto.id)
+ return;
+ }
+ resources.add(dto);
+ }
+
+ private static void addWiringNodeIfNotPresent(BundleWiring bw, Set<BundleRevisionDTO> resources, Set<NodeDTO> nodes)
+ {
+ int wiringID = getWiringID(bw);
+ for (NodeDTO n : nodes)
+ {
+ if (n.id == wiringID)
+ return;
+ }
+ createBundleWiringNodeDTO(bw, resources, nodes);
+ }
+
+ // Attributes contain Version values which are not supported for DTOs, so if
+ // these are found they need to be converted to String values.
+ private static Map<String, Object> convertAttrsToDTO(Map<String, Object> map)
+ {
+ Map<String, Object> m = new HashMap<String, Object>();
+ for (Map.Entry<String, Object> entry : map.entrySet())
+ {
+ if (entry.getValue() instanceof Version)
+ // DTOs don't support Version objects
+ m.put(entry.getKey(), entry.getValue().toString());
+ else
+ m.put(entry.getKey(), entry.getValue());
+ }
+ return m;
+ }
+
+ private static int getWiringID(Wiring bw)
+ {
+ return bw.hashCode();
+ }
+
+ private static int getCapabilityID(Capability capability)
+ {
+ return capability.hashCode();
+ }
+
+ private static int getRequirementID(Requirement requirement)
+ {
+ return requirement.hashCode();
+ }
+
+ private static int getResourceIDAndAdd(Resource res, Set<BundleRevisionDTO> resources)
+ {
+ if (res instanceof BundleRevisionImpl)
+ {
+ BundleRevisionImpl bres = (BundleRevisionImpl) res;
+ int id = bres.getId().hashCode();
+
+ if (resources == null)
+ return id;
+
+ for (BundleRevisionDTO rdto : resources)
+ {
+ if (rdto.id == id)
+ return id;
+ }
+ createBundleRevisionDTO(bres, resources);
+ return id;
+ }
+ return res.hashCode();
+ }
+
+ private static int getRevisionID(BundleRevisionImpl revision)
+ {
+ return revision.getId().hashCode();
+ }
+}
diff --git a/src/main/java/org/apache/felix/framework/ExtensionManager.java b/src/main/java/org/apache/felix/framework/ExtensionManager.java
index 002cea3..541365b 100644
--- a/src/main/java/org/apache/felix/framework/ExtensionManager.java
+++ b/src/main/java/org/apache/felix/framework/ExtensionManager.java
@@ -19,14 +19,15 @@
package org.apache.felix.framework;
import java.io.IOException;
-import java.net.InetAddress;
import java.io.InputStream;
+import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.security.AllPermission;
import java.util.ArrayList;
import java.util.Collections;
+import java.util.Dictionary;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
@@ -36,13 +37,15 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
+
+import org.apache.felix.framework.cache.Content;
import org.apache.felix.framework.util.FelixConstants;
import org.apache.felix.framework.util.ImmutableList;
import org.apache.felix.framework.util.StringMap;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.util.manifestparser.ManifestParser;
-import org.apache.felix.framework.cache.Content;
-import org.apache.felix.framework.util.manifestparser.R4Library;
+import org.apache.felix.framework.util.manifestparser.NativeLibrary;
+import org.apache.felix.framework.util.manifestparser.NativeLibraryClause;
import org.apache.felix.framework.wiring.BundleCapabilityImpl;
import org.apache.felix.framework.wiring.BundleWireImpl;
import org.osgi.framework.AdminPermission;
@@ -51,7 +54,9 @@ import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
+import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.Version;
+import org.osgi.framework.namespace.NativeNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
@@ -91,30 +96,38 @@ class ExtensionManager extends URLStreamHandler implements Content
static
{
// pre-init the url sub-system as otherwise we don't work on gnu/classpath
- ExtensionManager extensionManager = new ExtensionManager();
- try
- {
- (new URL("http://felix.extensions:9/")).openConnection();
- }
- catch (Throwable t)
- {
- // This doesn't matter much - we only need the above to init the url subsystem
- }
+ ExtensionManager extensionManager = null;
- // We use the secure action of Felix to add a new instance to the parent
- // classloader.
- try
+ if (!"true".equalsIgnoreCase(Felix.m_secureAction.getSystemProperty(
+ FelixConstants.FELIX_EXTENSIONS_DISABLE, "false")))
{
- Felix.m_secureAction.addURLToURLClassLoader(Felix.m_secureAction.createURL(
- Felix.m_secureAction.createURL(null, "http:", extensionManager),
- "http://felix.extensions:9/", extensionManager),
- Felix.class.getClassLoader());
- }
- catch (Throwable ex)
- {
- // extension bundles will not be supported.
- extensionManager = null;
+ try
+ {
+ (new URL("http://felix.extensions:9/")).openConnection();
+ }
+ catch (Throwable t)
+ {
+ // This doesn't matter much - we only need the above to init the url subsystem
+ }
+
+ // We use the secure action of Felix to add a new instance to the parent
+ // classloader.
+ try
+ {
+ extensionManager = new ExtensionManager();
+
+ Felix.m_secureAction.addURLToURLClassLoader(Felix.m_secureAction.createURL(
+ Felix.m_secureAction.createURL(null, "http:", extensionManager),
+ "http://felix.extensions:9/", extensionManager),
+ Felix.class.getClassLoader());
+ }
+ catch (Throwable ex)
+ {
+ // extension bundles will not be supported.
+ extensionManager = null;
+ }
}
+
m_extensionManager = extensionManager;
}
@@ -129,6 +142,22 @@ class ExtensionManager extends URLStreamHandler implements Content
private volatile Bundle[] m_extensionsCache;
private final Set m_names;
private final Map m_sourceToExtensions;
+ private final List<ExtensionTuple> m_extensionTuples = Collections.synchronizedList(new ArrayList<ExtensionTuple>());
+
+ private static class ExtensionTuple
+ {
+ private final BundleActivator m_activator;
+ private final Bundle m_bundle;
+ private volatile boolean m_failed;
+ private volatile boolean m_started;
+
+ public ExtensionTuple(BundleActivator activator, Bundle bundle)
+ {
+ m_activator = activator;
+ m_bundle = bundle;
+ }
+
+ }
// This constructor is only used for the private instance added to the parent
// classloader.
@@ -221,6 +250,7 @@ class ExtensionManager extends URLStreamHandler implements Content
ManifestParser mp = new ManifestParser(
m_logger, m_configMap, m_systemBundleRevision, m_headerMap);
List<BundleCapability> caps = aliasSymbolicName(mp.getCapabilities());
+ caps.add(buildNativeCapabilites());
appendCapabilities(caps);
}
catch (Exception ex)
@@ -233,6 +263,40 @@ class ExtensionManager extends URLStreamHandler implements Content
}
}
+ protected BundleCapability buildNativeCapabilites() {
+ String osArchitecture = (String)m_configMap.get(FelixConstants.FRAMEWORK_PROCESSOR);
+ String osName = (String)m_configMap.get(FelixConstants.FRAMEWORK_OS_NAME);
+ String osVersion = (String)m_configMap.get(FelixConstants.FRAMEWORK_OS_VERSION);
+ String userLang = (String)m_configMap.get(FelixConstants.FRAMEWORK_LANGUAGE);
+ Map<String, Object> attributes = new HashMap<String, Object>();
+
+ //Add all startup properties so we can match selection-filters
+ attributes.putAll(m_configMap);
+
+ if( osArchitecture != null )
+ {
+ attributes.put(NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE, NativeLibraryClause.getProcessorWithAliases(osArchitecture));
+ }
+
+ if( osName != null)
+ {
+ attributes.put(NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE, NativeLibraryClause.getOsNameWithAliases(osName));
+ }
+
+ if( osVersion != null)
+ {
+ osVersion = NativeLibraryClause.formatOSVersion(osVersion);
+ attributes.put(NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE, Version.parseVersion(osVersion));
+ }
+
+ if( userLang != null)
+ {
+ attributes.put(NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE, userLang);
+ }
+
+ return new BundleCapabilityImpl(getRevision(), NativeNamespace.NATIVE_NAMESPACE, Collections.<String, String> emptyMap(), attributes);
+ }
+
private static List<BundleCapability> aliasSymbolicName(List<BundleCapability> caps)
{
if (caps == null)
@@ -359,7 +423,7 @@ class ExtensionManager extends URLStreamHandler implements Content
{
exports = ManifestParser.parseExportHeader(
m_logger, m_systemBundleRevision,
- (String) ((BundleRevisionImpl) bundle.adapt(BundleRevision.class))
+ (String) ((BundleRevisionImpl) bundle.adapt(BundleRevisionImpl.class))
.getHeaders().get(Constants.EXPORT_PACKAGE),
m_systemBundleRevision.getSymbolicName(), m_systemBundleRevision.getVersion());
exports = aliasSymbolicName(exports);
@@ -370,7 +434,7 @@ class ExtensionManager extends URLStreamHandler implements Content
bundle,
Logger.LOG_ERROR,
"Error parsing extension bundle export statement: "
- + ((BundleRevisionImpl) bundle.adapt(BundleRevision.class))
+ + ((BundleRevisionImpl) bundle.adapt(BundleRevisionImpl.class))
.getHeaders().get(Constants.EXPORT_PACKAGE), ex);
return;
}
@@ -396,7 +460,7 @@ class ExtensionManager extends URLStreamHandler implements Content
throw ex;
}
- BundleRevisionImpl bri = (BundleRevisionImpl) bundle.adapt(BundleRevision.class);
+ BundleRevisionImpl bri = (BundleRevisionImpl) bundle.adapt(BundleRevisionImpl.class);
List<BundleRequirement> reqs = bri.getDeclaredRequirements(BundleRevision.HOST_NAMESPACE);
List<BundleCapability> caps = getCapabilities(BundleRevision.HOST_NAMESPACE);
BundleWire bw = new BundleWireImpl(bri, reqs.get(0), m_systemBundleRevision, caps.get(0));
@@ -423,12 +487,18 @@ class ExtensionManager extends URLStreamHandler implements Content
*/
void startExtensionBundle(Felix felix, BundleImpl bundle)
{
- String activatorClass = (String)
- ((BundleRevisionImpl) bundle.adapt(BundleRevision.class))
- .getHeaders().get(FelixConstants.FELIX_EXTENSION_ACTIVATOR);
+ Map<?,?> headers = bundle.adapt(BundleRevisionImpl.class).getHeaders();
+ String activatorClass = (String) headers.get(Constants.EXTENSION_BUNDLE_ACTIVATOR);
+ boolean felixExtension = false;
+ if (activatorClass == null)
+ {
+ felixExtension = true;
+ activatorClass = (String) headers.get(FelixConstants.FELIX_EXTENSION_ACTIVATOR);
+ }
if (activatorClass != null)
{
+ ExtensionTuple tuple = null;
try
{
// TODO: SECURITY - Should this consider security?
@@ -436,24 +506,91 @@ class ExtensionManager extends URLStreamHandler implements Content
felix.getClass().getClassLoader().loadClass(
activatorClass.trim()).newInstance();
-// TODO: EXTENSIONMANAGER - This is kind of hacky, can we improve it?
- felix.m_activatorList.add(activator);
-
BundleContext context = felix._getBundleContext();
bundle.setBundleContext(context);
+// TODO: EXTENSIONMANAGER - This is kind of hacky, can we improve it?
+ if (!felixExtension)
+ {
+ tuple = new ExtensionTuple(activator, bundle);
+ m_extensionTuples.add(tuple);
+ }
+ else
+ {
+ felix.m_activatorList.add(activator);
+ }
+
if ((felix.getState() == Bundle.ACTIVE) || (felix.getState() == Bundle.STARTING))
{
+ if (tuple != null)
+ {
+ tuple.m_started = true;
+ }
Felix.m_secureAction.startActivator(activator, context);
}
}
catch (Throwable ex)
{
+ if (tuple != null)
+ {
+ tuple.m_failed = true;
+ }
+ felix.fireFrameworkEvent(FrameworkEvent.ERROR, bundle,
+ new BundleException("Unable to start Bundle", ex));
+
m_logger.log(bundle, Logger.LOG_WARNING,
- "Unable to start Felix Extension Activator", ex);
+ "Unable to start Extension Activator", ex);
+ }
+ }
+ }
+
+ void startPendingExtensionBundles(Felix felix)
+ {
+ for (int i = 0;i < m_extensionTuples.size();i++)
+ {
+ if (!m_extensionTuples.get(i).m_started)
+ {
+ m_extensionTuples.get(i).m_started = true;
+ try
+ {
+ Felix.m_secureAction.startActivator(m_extensionTuples.get(i).m_activator, felix._getBundleContext());
+ }
+ catch (Throwable ex)
+ {
+ m_extensionTuples.get(i).m_failed = true;
+
+ felix.fireFrameworkEvent(FrameworkEvent.ERROR, m_extensionTuples.get(i).m_bundle,
+ new BundleException("Unable to start Bundle", BundleException.ACTIVATOR_ERROR, ex));
+
+ m_logger.log(m_extensionTuples.get(i).m_bundle, Logger.LOG_WARNING,
+ "Unable to start Extension Activator", ex);
+ }
+ }
+ }
+ }
+
+ void stopExtensionBundles(Felix felix)
+ {
+ for (int i = m_extensionTuples.size() - 1; i >= 0;i--)
+ {
+ if (m_extensionTuples.get(i).m_started && !m_extensionTuples.get(i).m_failed)
+ {
+ try
+ {
+ Felix.m_secureAction.stopActivator(m_extensionTuples.get(i).m_activator, felix._getBundleContext());
+ }
+ catch (Throwable ex)
+ {
+ felix.fireFrameworkEvent(FrameworkEvent.ERROR, m_extensionTuples.get(i).m_bundle,
+ new BundleException("Unable to stop Bundle", BundleException.ACTIVATOR_ERROR, ex));
+
+ m_logger.log(m_extensionTuples.get(i).m_bundle, Logger.LOG_WARNING,
+ "Unable to stop Extension Activator", ex);
+ }
}
}
+ m_extensionTuples.clear();
}
/**
@@ -829,7 +966,7 @@ class ExtensionManager extends URLStreamHandler implements Content
}
@Override
- public List<R4Library> getNativeLibraries()
+ public List<NativeLibrary> getNativeLibraries()
{
return Collections.EMPTY_LIST;
}
diff --git a/src/main/java/org/apache/felix/framework/Felix.java b/src/main/java/org/apache/felix/framework/Felix.java
index d670d78..2b418f3 100644
--- a/src/main/java/org/apache/felix/framework/Felix.java
+++ b/src/main/java/org/apache/felix/framework/Felix.java
@@ -18,10 +18,37 @@
*/
package org.apache.felix.framework;
-import java.io.*;
-import java.net.*;
-import java.security.*;
-import java.util.*;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLStreamHandler;
+import java.security.AccessControlException;
+import java.security.Permission;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.StringTokenizer;
+import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
import org.apache.felix.framework.BundleWiringImpl.BundleClassLoader;
import org.apache.felix.framework.ServiceRegistry.ServiceRegistryCallbacks;
@@ -40,7 +67,7 @@ import org.apache.felix.framework.util.ShrinkableCollection;
import org.apache.felix.framework.util.StringMap;
import org.apache.felix.framework.util.ThreadGate;
import org.apache.felix.framework.util.Util;
-import org.apache.felix.framework.util.manifestparser.R4LibraryClause;
+import org.apache.felix.framework.util.manifestparser.NativeLibraryClause;
import org.apache.felix.framework.wiring.BundleRequirementImpl;
import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
@@ -56,6 +83,7 @@ import org.osgi.framework.FrameworkEvent;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.PackagePermission;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceException;
import org.osgi.framework.ServiceFactory;
@@ -64,12 +92,15 @@ import org.osgi.framework.ServicePermission;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.launch.Framework;
+import org.osgi.framework.namespace.HostNamespace;
import org.osgi.framework.startlevel.FrameworkStartLevel;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleRevisions;
+import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
import org.osgi.framework.wiring.FrameworkWiring;
+import org.osgi.resource.Requirement;
import org.osgi.service.packageadmin.ExportedPackage;
public class Felix extends BundleImpl implements Framework
@@ -372,6 +403,9 @@ public class Felix extends BundleImpl implements Framework
m_bootPkgs[i] = s;
}
+ //Initialize Native Library Aliases
+ NativeLibraryClause.initializeNativeAliases(m_configMap);
+
// Read the security default policy property
m_securityDefaultPolicy = "true".equals(getProperty(FelixConstants.SECURITY_DEFAULT_POLICY));
@@ -476,6 +510,7 @@ public class Felix extends BundleImpl implements Framework
// This overrides the default behavior of BundleImpl.getFramework()
// to return "this", since the system bundle is the framework.
+ @Override
Felix getFramework()
{
return this;
@@ -503,41 +538,49 @@ public class Felix extends BundleImpl implements Framework
return super.adapt(type);
}
+ @Override
public long getBundleId()
{
return 0;
}
+ @Override
public long getLastModified()
{
return 0;
}
+ @Override
void setLastModified(long l)
{
// Ignore.
}
+ @Override
String _getLocation()
{
return Constants.SYSTEM_BUNDLE_LOCATION;
}
+ @Override
public int getPersistentState()
{
return Bundle.ACTIVE;
}
+ @Override
public void setPersistentStateInactive()
{
// Ignore.
}
+ @Override
public void setPersistentStateActive()
{
// Ignore.
}
+ @Override
public void setPersistentStateUninstalled()
{
// Ignore.
@@ -549,6 +592,7 @@ public class Felix extends BundleImpl implements Framework
* @param defaultLevel This parameter is ignored by the system bundle.
* @return Always returns zero.
**/
+ @Override
int getStartLevel(int defaultLevel)
{
return 0;
@@ -562,29 +606,28 @@ public class Felix extends BundleImpl implements Framework
* @throws IllegalArgumentException Always throws exception since system
* bundle's start level cannot be changed.
**/
+ @Override
void setStartLevel(int level)
{
throw new IllegalArgumentException("Cannot set the system bundle's start level.");
}
+ @Override
public boolean hasPermission(Object obj)
{
return true;
}
- /**
- * This method initializes the framework, which is comprised of resolving
- * the system bundle, reloading any cached bundles, and activating the system
- * bundle. The framework is left in the <tt>Bundle.STARTING</tt> state and
- * reloaded bundles are in the <tt>Bundle.INSTALLED</tt> state. After
- * successfully invoking this method, <tt>getBundleContext()</tt> will
- * return a valid <tt>BundleContext</tt> for the system bundle. To finish
- * starting the framework, invoke the <tt>start()</tt> method.
- *
- * @throws org.osgi.framework.BundleException if any error occurs.
- **/
+
public void init() throws BundleException
{
+ init((FrameworkListener[]) null);
+ }
+ /**
+ * @see org.osgi.framework.launch.Framework#init(org.osgi.framework.FrameworkListener[])
+ */
+ public void init(final FrameworkListener... listeners) throws BundleException
+ {
// The system bundle can only be initialized if it currently isn't started.
acquireBundleLock(this,
Bundle.INSTALLED | Bundle.RESOLVED | Bundle.STARTING | Bundle.ACTIVE);
@@ -780,6 +823,15 @@ public class Felix extends BundleImpl implements Framework
// so create a gate for that purpose.
m_shutdownGate = new ThreadGate();
+ // add framework listeners
+ if ( listeners != null )
+ {
+ for(final FrameworkListener fl : listeners)
+ {
+ addFrameworkListener(this, fl);
+ }
+ }
+
// Start services
m_fwkWiring.start();
m_fwkStartLevel.start();
@@ -819,7 +871,7 @@ public class Felix extends BundleImpl implements Framework
{
if (bundle != this)
{
- setBundleProtectionDomain((BundleImpl) bundle, (BundleRevisionImpl) ((BundleImpl) bundle).adapt(BundleRevisionImpl.class));
+ setBundleProtectionDomain((BundleImpl) bundle, ((BundleImpl) bundle).adapt(BundleRevisionImpl.class));
}
}
catch (Exception ex)
@@ -847,6 +899,9 @@ public class Felix extends BundleImpl implements Framework
}
}
+ m_extensionManager.startPendingExtensionBundles(Felix.this);
+ m_fwkWiring.refreshBundles(null);
+
// Clear the cache of classes coming from the system bundle.
// This is only used for Felix.getBundle(Class clazz) to speed
// up class lookup for the system bundle.
@@ -859,6 +914,14 @@ public class Felix extends BundleImpl implements Framework
finally
{
releaseBundleLock(this);
+
+ if ( listeners != null )
+ {
+ for(final FrameworkListener fl : listeners)
+ {
+ removeFrameworkListener(this, fl);
+ }
+ }
}
}
@@ -885,6 +948,7 @@ public class Felix extends BundleImpl implements Framework
*
* @throws org.osgi.framework.BundleException if any error occurs.
**/
+ @Override
public void start() throws BundleException
{
int startLevel = FelixConstants.FRAMEWORK_DEFAULT_STARTLEVEL;
@@ -934,6 +998,7 @@ public class Felix extends BundleImpl implements Framework
fireFrameworkEvent(FrameworkEvent.STARTED, this, null);
}
+ @Override
public void start(int options) throws BundleException
{
start();
@@ -943,6 +1008,7 @@ public class Felix extends BundleImpl implements Framework
* This method asynchronously shuts down the framework, it must be called at the
* end of a session in order to shutdown all active bundles.
**/
+ @Override
public void stop() throws BundleException
{
Object sm = System.getSecurityManager();
@@ -976,6 +1042,7 @@ public class Felix extends BundleImpl implements Framework
}
}
+ @Override
public void stop(int options) throws BundleException
{
stop();
@@ -1020,16 +1087,19 @@ public class Felix extends BundleImpl implements Framework
return event;
}
+ @Override
public void uninstall() throws BundleException
{
throw new BundleException("Cannot uninstall the system bundle.");
}
+ @Override
public void update() throws BundleException
{
update(null);
}
+ @Override
public void update(InputStream is) throws BundleException
{
Object sm = System.getSecurityManager();
@@ -1112,6 +1182,7 @@ public class Felix extends BundleImpl implements Framework
}).start();
}
+ @Override
public String toString()
{
return getSymbolicName() + " [" + getBundleId() +"]";
@@ -1938,7 +2009,7 @@ public class Felix extends BundleImpl implements Framework
"Cannot start bundle " + bundle + " because its start level is "
+ bundleLevel
+ ", which is greater than the framework's start level of "
- + m_activeStartLevel + ".");
+ + m_activeStartLevel + ".", BundleException.START_TRANSIENT_ERROR);
}
else if (bundleLevel > m_targetStartLevel)
{
@@ -1967,7 +2038,7 @@ public class Felix extends BundleImpl implements Framework
"Cannot start bundle " + bundle + " because its start level is "
+ bundleLevel
+ ", which is greater than the framework's start level of "
- + m_activeStartLevel + ".");
+ + m_activeStartLevel + ".", BundleException.START_TRANSIENT_ERROR);
}
// If the start level bundle queue is not empty, then we know
@@ -3021,7 +3092,7 @@ public class Felix extends BundleImpl implements Framework
bundles = new ShrinkableCollection<Bundle>(bundles);
for (ServiceReference<org.osgi.framework.hooks.bundle.FindHook> hook : hooks)
{
- org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook);
+ org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook, false);
if (fh != null)
{
try
@@ -3040,11 +3111,19 @@ public class Felix extends BundleImpl implements Framework
}
}
}
- if (bundles.isEmpty())
+
+ if (origin != this)
{
- throw new BundleException(
- "Bundle installation rejected by hook.",
- BundleException.REJECTED_BY_HOOK);
+ // If the origin was something else than the system bundle, reject this action if
+ // the bundle has been removed by the hooks. However, if it is the system bundle,
+ // the install action should always succeed, regardless of whether the hooks are
+ // trying to prevent it.
+ if (bundles.isEmpty())
+ {
+ throw new BundleException(
+ "Bundle installation rejected by hook.",
+ BundleException.REJECTED_BY_HOOK);
+ }
}
}
}
@@ -3107,7 +3186,7 @@ public class Felix extends BundleImpl implements Framework
bundles = new ShrinkableCollection<Bundle>(bundles);
for (ServiceReference<org.osgi.framework.hooks.bundle.FindHook> hook : hooks)
{
- org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook);
+ org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook, false);
if (fh != null)
{
try
@@ -3125,7 +3204,12 @@ public class Felix extends BundleImpl implements Framework
}
}
}
- bundle = (bundles.isEmpty()) ? null : bundle;
+
+ if (bc.getBundle() != this)
+ {
+ // If the requesting bundle is not the system bundle, return the filtered result
+ bundle = (bundles.isEmpty()) ? null : bundle;
+ }
}
return bundle;
}
@@ -3172,15 +3256,15 @@ public class Felix extends BundleImpl implements Framework
getHooks(org.osgi.framework.hooks.bundle.FindHook.class);
if (!hooks.isEmpty())
{
- bundles = new ShrinkableCollection<Bundle>(new ArrayList(bundles));
+ Collection<Bundle> shrunkBundles = new ShrinkableCollection<Bundle>(new ArrayList(bundles));
for (ServiceReference<org.osgi.framework.hooks.bundle.FindHook> hook : hooks)
{
- org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook);
+ org.osgi.framework.hooks.bundle.FindHook fh = getService(this, hook, false);
if (fh != null)
{
try
{
- m_secureAction.invokeBundleFindHook(fh, bc, bundles);
+ m_secureAction.invokeBundleFindHook(fh, bc, shrunkBundles);
}
catch (Throwable th)
{
@@ -3193,8 +3277,16 @@ public class Felix extends BundleImpl implements Framework
}
}
}
+
+ if (bc.getBundle() != this)
+ {
+ // If the requesting bundle is something other than the system bundle, return the shrunk
+ // collection of bundles. If it *is* the system bundle, it should receive the unfiltered bundles.
+ bundles = shrunkBundles;
+ }
}
- return (Bundle[]) bundles.toArray(new Bundle[bundles.size()]);
+
+ return bundles.toArray(new Bundle[bundles.size()]);
}
/**
@@ -3206,7 +3298,7 @@ public class Felix extends BundleImpl implements Framework
Bundle[] getBundles()
{
Collection<Bundle> bundles = m_installedBundles[IDENTIFIER_MAP_IDX].values();
- return (Bundle[]) bundles.toArray(new Bundle[bundles.size()]);
+ return bundles.toArray(new Bundle[bundles.size()]);
}
void addBundleListener(BundleImpl bundle, BundleListener l)
@@ -3249,7 +3341,7 @@ public class Felix extends BundleImpl implements Framework
ServiceListener.class, l, oldFilter, null, true));
for (ServiceReference<org.osgi.framework.hooks.service.ListenerHook> sr : listenerHooks)
{
- org.osgi.framework.hooks.service.ListenerHook lh = getService(this, sr);
+ org.osgi.framework.hooks.service.ListenerHook lh = getService(this, sr, false);
if (lh != null)
{
try
@@ -3263,7 +3355,7 @@ public class Felix extends BundleImpl implements Framework
}
finally
{
- m_registry.ungetService(this, sr);
+ m_registry.ungetService(this, sr, null);
}
}
}
@@ -3275,7 +3367,7 @@ public class Felix extends BundleImpl implements Framework
ServiceListener.class, l, newFilter, null, false));
for (ServiceReference<org.osgi.framework.hooks.service.ListenerHook> sr : listenerHooks)
{
- org.osgi.framework.hooks.service.ListenerHook lh = getService(this, sr);
+ org.osgi.framework.hooks.service.ListenerHook lh = getService(this, sr, false);
if (lh != null)
{
try
@@ -3289,7 +3381,7 @@ public class Felix extends BundleImpl implements Framework
}
finally
{
- m_registry.ungetService(this, sr);
+ m_registry.ungetService(this, sr, null);
}
}
}
@@ -3316,7 +3408,7 @@ public class Felix extends BundleImpl implements Framework
Collection removed = Collections.singleton(listener);
for (ServiceReference<org.osgi.framework.hooks.service.ListenerHook> sr : listenerHooks)
{
- org.osgi.framework.hooks.service.ListenerHook lh = getService(this, sr);
+ org.osgi.framework.hooks.service.ListenerHook lh = getService(this, sr, false);
if (lh != null)
{
try
@@ -3330,7 +3422,7 @@ public class Felix extends BundleImpl implements Framework
}
finally
{
- m_registry.ungetService(this, sr);
+ m_registry.ungetService(this, sr, null);
}
}
}
@@ -3405,7 +3497,7 @@ public class Felix extends BundleImpl implements Framework
{
org.osgi.framework.hooks.service.ListenerHook lh =
(org.osgi.framework.hooks.service.ListenerHook)
- getService(this, reg.getReference());
+ getService(this, reg.getReference(), false);
if (lh != null)
{
try
@@ -3420,7 +3512,7 @@ public class Felix extends BundleImpl implements Framework
}
finally
{
- m_registry.ungetService(this, reg.getReference());
+ m_registry.ungetService(this, reg.getReference(), null);
}
}
}
@@ -3461,31 +3553,33 @@ public class Felix extends BundleImpl implements Framework
}
// Ask the service registry for all matching service references.
- final List refList = m_registry.getServiceReferences(className, filter);
+ final Collection refList = m_registry.getServiceReferences(className, filter);
// Filter on assignable references
if (checkAssignable)
{
- for (int refIdx = 0; (refList != null) && (refIdx < refList.size()); refIdx++)
+ for (Iterator refIter = refList.iterator(); refIter.hasNext();)
{
// Get the current service reference.
- ServiceReference ref = (ServiceReference) refList.get(refIdx);
+ ServiceReference ref = (ServiceReference) refIter.next();
// Now check for castability.
if (!Util.isServiceAssignable(bundle, ref))
{
- refList.remove(refIdx);
- refIdx--;
+ refIter.remove();
}
}
}
+ // If the requesting bundle is the system bundle, ignore the effects of the findhooks
+ Collection resRefList = (bundle == this ? new ArrayList(refList) : refList);
+
// activate findhooks
Set<ServiceReference<org.osgi.framework.hooks.service.FindHook>> findHooks =
m_registry.getHooks(org.osgi.framework.hooks.service.FindHook.class);
for (ServiceReference<org.osgi.framework.hooks.service.FindHook> sr : findHooks)
{
- org.osgi.framework.hooks.service.FindHook fh = getService(this, sr);
+ org.osgi.framework.hooks.service.FindHook fh = getService(this, sr, false);
if (fh != null)
{
try
@@ -3505,14 +3599,17 @@ public class Felix extends BundleImpl implements Framework
}
finally
{
- m_registry.ungetService(this, sr);
+ m_registry.ungetService(this, sr, null);
}
}
}
- if (refList.size() > 0)
+ // We return resRefList which is normally the same as refList and therefore any modifications
+ // to refList are also visible to resRefList. However in the case of the system bundle being
+ // the requestor, resRefList is a copy of the original list before the hooks were invoked.
+ if (resRefList.size() > 0)
{
- return (ServiceReference[]) refList.toArray(new ServiceReference[refList.size()]);
+ return (ServiceReference[]) resRefList.toArray(new ServiceReference[resRefList.size()]);
}
return null;
@@ -3567,11 +3664,11 @@ public class Felix extends BundleImpl implements Framework
}
- <S> S getService(Bundle bundle, ServiceReference<S> ref)
+ <S> S getService(Bundle bundle, ServiceReference<S> ref, boolean isPrototype)
{
try
{
- return (S) m_registry.getService(bundle, ref);
+ return m_registry.getService(bundle, ref, isPrototype);
}
catch (ServiceException ex)
{
@@ -3581,9 +3678,9 @@ public class Felix extends BundleImpl implements Framework
return null;
}
- boolean ungetService(Bundle bundle, ServiceReference ref)
+ boolean ungetService(Bundle bundle, ServiceReference ref, Object srvObj)
{
- return m_registry.ungetService(bundle, ref);
+ return m_registry.ungetService(bundle, ref, srvObj);
}
File getDataFile(BundleImpl bundle, String s)
@@ -3747,22 +3844,40 @@ public class Felix extends BundleImpl implements Framework
// newest to oldest. We assume that the first revision found to
// be exporting the package is the provider of the package,
// which makes sense since it must have been resolved first.
- List<BundleRevision> revisions =
+ List<BundleRevision> originRevisions =
bundle.adapt(BundleRevisions.class).getRevisions();
- for (int i = revisions.size() - 1; i >= 0; i--)
+ for (int i = originRevisions.size() - 1; i >= 0; i--)
{
- BundleRevision br = revisions.get(i);
- List<BundleCapability> caps = (br.getWiring() == null)
- ? br.getDeclaredCapabilities(null)
- : br.getWiring().getCapabilities(null);
- for (BundleCapability cap : caps)
+ BundleRevision originBr = originRevisions.get(i);
+ List<BundleRevision> revisions = Collections.singletonList(originBr);
+
+ if ((originBr.getTypes() & BundleRevision.TYPE_FRAGMENT) != 0)
{
- if (cap.getNamespace().equals(req.getNamespace())
- && CapabilitySet.matches(cap, req.getFilter()))
+ // If it's a fragment, find the revisions of the attached
+ // bundle(s) and work with those instead. Note that fragments
+ // can be attached to multiple hosts...
+ revisions = new ArrayList<BundleRevision>();
+
+ for (BundleWire bw : originBr.getWiring().getRequiredWires(HostNamespace.HOST_NAMESPACE))
{
- pkgs.add(
- new ExportedPackageImpl(
- this, (BundleImpl) bundle, br, cap));
+ revisions.add(bw.getProviderWiring().getRevision());
+ }
+ }
+
+ for (BundleRevision br : revisions)
+ {
+ List<BundleCapability> caps = (br.getWiring() == null)
+ ? br.getDeclaredCapabilities(null)
+ : br.getWiring().getCapabilities(null);
+ for (BundleCapability cap : caps)
+ {
+ if (cap.getNamespace().equals(req.getNamespace())
+ && CapabilitySet.matches(cap, req.getFilter()))
+ {
+ pkgs.add(
+ new ExportedPackageImpl(
+ this, (BundleImpl) br.getBundle(), br, cap));
+ }
}
}
}
@@ -4301,6 +4416,13 @@ public class Felix extends BundleImpl implements Framework
boolean impliesBundlePermission(BundleProtectionDomain bundleProtectionDomain, Permission permission, boolean direct)
{
+ if (direct && permission instanceof PackagePermission)
+ {
+ if (bundleProtectionDomain.impliesWoven(permission))
+ {
+ return true;
+ }
+ }
if (m_securityProvider != null)
{
return m_securityProvider.hasBundlePermission(bundleProtectionDomain, permission, direct);
@@ -4365,7 +4487,7 @@ public class Felix extends BundleImpl implements Framework
// Remove dependencies.
m_dependencies.removeDependencies(bundle);
// Reset the bundle object.
- ((BundleImpl) bundle).refresh();
+ bundle.refresh();
// Fire UNRESOLVED event if necessary
// and notify state change..
if (fire)
@@ -4458,23 +4580,46 @@ public class Felix extends BundleImpl implements Framework
"false");
String s = null;
- s = R4LibraryClause.normalizeOSName(System.getProperty("os.name"));
+ s = NativeLibraryClause.normalizeOSName(System.getProperty("os.name"));
m_configMutableMap.put(FelixConstants.FRAMEWORK_OS_NAME, s);
- s = R4LibraryClause.normalizeProcessor(System.getProperty("os.arch"));
+ s = NativeLibraryClause.normalizeProcessor(System.getProperty("os.arch"));
m_configMutableMap.put(FelixConstants.FRAMEWORK_PROCESSOR, s);
m_configMutableMap.put(
FelixConstants.FELIX_VERSION_PROPERTY, getFrameworkVersion());
+ Properties defaultProperties = Util.loadDefaultProperties(m_logger);
// Set supported execution environments to default value,
// if not explicitly configured.
- if (!getConfig().containsKey(Constants.FRAMEWORK_EXECUTIONENVIRONMENT))
+ loadFromDefaultIfNotDefined(defaultProperties, Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
+
+ // Set supported native capabilities to default value,
+ // if not explicitly configured.
+ loadPrefixFromDefaultIfNotDefined(m_configMutableMap, defaultProperties, FelixConstants.NATIVE_OS_NAME_ALIAS_PREFIX);
+ loadPrefixFromDefaultIfNotDefined(m_configMutableMap, defaultProperties, FelixConstants.NATIVE_PROC_NAME_ALIAS_PREFIX);
+ }
+
+ private void loadFromDefaultIfNotDefined(Properties defaultProperties, String propertyName)
+ {
+ String s;
+ if (!getConfig().containsKey(propertyName))
{
- s = Util.getDefaultProperty(
- m_logger, Constants.FRAMEWORK_EXECUTIONENVIRONMENT);
+ s = Util.getDefaultProperty(m_logger, propertyName);
if (s != null)
{
- m_configMutableMap.put(
- Constants.FRAMEWORK_EXECUTIONENVIRONMENT, s);
+ m_configMutableMap.put(propertyName, s);
+ }
+ }
+ }
+
+ private void loadPrefixFromDefaultIfNotDefined(Map configMap, Properties defaultProperties, String prefix)
+ {
+ Map<String, String> defaultPropsWithPrefix = Util.getDefaultPropertiesWithPrefix(defaultProperties, prefix);
+
+ for(String currentDefaultProperty: defaultPropsWithPrefix.keySet())
+ {
+ if(!configMap.containsKey(currentDefaultProperty))
+ {
+ configMap.put(currentDefaultProperty, defaultPropsWithPrefix.get(currentDefaultProperty));
}
}
}
@@ -4517,11 +4662,7 @@ public class Felix extends BundleImpl implements Framework
new StringBuffer(
props.getProperty(
FelixConstants.FELIX_VERSION_PROPERTY, "0.0.0"));
- if (sb.toString().indexOf("-") >= 0)
- {
- sb.setCharAt(sb.toString().indexOf("-"), '.');
- }
- String toRet = sb.toString();
+ String toRet = cleanMavenVersion(sb);
if (toRet.indexOf("${pom") >= 0)
{
return "0.0.0";
@@ -4532,6 +4673,40 @@ public class Felix extends BundleImpl implements Framework
}
}
+ /**
+ * The main purpose of this method is to turn a.b.c-SNAPSHOT into a.b.c.SNAPSHOT
+ * it can also deal with a.b-SNAPSHOT and turns it into a.b.0.SNAPSHOT and
+ * will leave the dash in a.b.c.something-else, as it's valid in that last example.
+ * In short this method attempts to map a Maven version to an OSGi version as well
+ * as possible.
+ * @param sb The version to be cleaned
+ * @return The cleaned version
+ */
+ private static String cleanMavenVersion(StringBuffer sb)
+ {
+ int dots = 0;
+ for (int i = 0; i < sb.length(); i++)
+ {
+ switch (sb.charAt(i))
+ {
+ case '.':
+ dots++;
+ break;
+ case '-':
+ if (dots < 3)
+ {
+ sb.setCharAt(i, '.');
+ for (int j = dots; j < 2; j++)
+ {
+ sb.insert(i, ".0");
+ }
+ }
+ break;
+ }
+ }
+ return sb.toString();
+ }
+
//
// Private utility methods.
//
@@ -4646,10 +4821,23 @@ public class Felix extends BundleImpl implements Framework
m_activatorList.add(0, new URLHandlersActivator(m_configMap, Felix.this));
// Start all activators.
- for (int i = 0; i < m_activatorList.size(); i++)
+ for (Iterator<BundleActivator> iter = m_activatorList.iterator(); iter.hasNext(); )
{
- Felix.m_secureAction.startActivator(
- (BundleActivator) m_activatorList.get(i), context);
+ try
+ {
+ Felix.m_secureAction.startActivator(
+ iter.next(), context);
+ }
+ catch (Throwable throwable)
+ {
+ iter.remove();
+ fireFrameworkEvent(FrameworkEvent.ERROR, context.getBundle(),
+ new BundleException("Unable to start Bundle", throwable));
+ m_logger.log(
+ Logger.LOG_WARNING,
+ "Exception starting a system bundle activator.",
+ throwable);
+ }
}
}
@@ -4724,6 +4912,7 @@ public class Felix extends BundleImpl implements Framework
((BundleImpl) bundles[i]).close();
}
+ m_extensionManager.stopExtensionBundles(Felix.this);
// Stop all system bundle activators.
for (int i = 0; i < m_activatorList.size(); i++)
{
@@ -4734,13 +4923,14 @@ public class Felix extends BundleImpl implements Framework
}
catch (Throwable throwable)
{
+ fireFrameworkEvent(FrameworkEvent.ERROR, context.getBundle(),
+ new BundleException("Unable to stop Bundle", throwable));
m_logger.log(
Logger.LOG_WARNING,
"Exception stopping a system bundle activator.",
throwable);
}
}
-
if (m_securityManager != null)
{
System.setSecurityManager(null);
@@ -5199,4 +5389,9 @@ public class Felix extends BundleImpl implements Framework
{
return m_urlHandlersActivator.getContentHandlerService(mimeType);
}
+
+ Collection<BundleCapability> findProviders(final Requirement requirement)
+ {
+ return m_resolver.findProvidersInternal(null, requirement, true, false);
+ }
}
diff --git a/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java b/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
index e6509ce..995faad 100644
--- a/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
+++ b/src/main/java/org/apache/felix/framework/FrameworkStartLevelImpl.java
@@ -20,6 +20,7 @@ package org.apache.felix.framework;
import java.util.ArrayList;
import java.util.List;
+
import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
@@ -50,9 +51,10 @@ class FrameworkStartLevelImpl implements FrameworkStartLevel, Runnable
m_registry = registry;
}
+ @SuppressWarnings("unchecked")
void start()
{
- m_slReg = m_registry.registerService(m_felix._getBundleContext(),
+ m_slReg = (ServiceRegistration<StartLevel>) m_registry.registerService(m_felix._getBundleContext(),
new String[] { StartLevel.class.getName() },
new StartLevelImpl(m_felix),
null);
@@ -124,8 +126,10 @@ class FrameworkStartLevelImpl implements FrameworkStartLevel, Runnable
synchronized (m_requests)
{
- // Start thread if necessary.
- startThread();
+ if (m_thread == null)
+ {
+ throw new IllegalStateException("No inital startlevel yet");
+ }
// Queue request.
m_requestListeners.add(listeners);
m_requests.add(new Integer(startlevel));
@@ -235,7 +239,7 @@ class FrameworkStartLevelImpl implements FrameworkStartLevel, Runnable
// Start thread if necessary.
startThread();
// Synchronously persists the start level.
- ((BundleImpl) m_bundle).setStartLevel(startlevel);
+ m_bundle.setStartLevel(startlevel);
// Queue request.
m_requestListeners.add(null);
m_requests.add(new Object[] { m_bundle, new Integer(startlevel) });
diff --git a/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java b/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
index 8ad803c..a0173ed 100644
--- a/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
+++ b/src/main/java/org/apache/felix/framework/FrameworkWiringImpl.java
@@ -21,11 +21,15 @@ package org.apache.felix.framework;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+
import org.osgi.framework.AdminPermission;
import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.FrameworkWiring;
+import org.osgi.resource.Requirement;
import org.osgi.service.packageadmin.PackageAdmin;
class FrameworkWiringImpl implements FrameworkWiring, Runnable
@@ -45,9 +49,10 @@ class FrameworkWiringImpl implements FrameworkWiring, Runnable
m_registry = registry;
}
+ @SuppressWarnings("unchecked")
void start()
{
- m_paReg = m_registry.registerService(m_felix._getBundleContext(),
+ m_paReg = (ServiceRegistration<PackageAdmin>) m_registry.registerService(m_felix._getBundleContext(),
new String[] { PackageAdmin.class.getName() },
new PackageAdminImpl(m_felix),
null);
@@ -120,6 +125,11 @@ class FrameworkWiringImpl implements FrameworkWiring, Runnable
new AdminPermission(m_felix, AdminPermission.RESOLVE));
}
+ if (m_thread == null)
+ {
+ return false;
+ }
+
return m_felix.resolveBundles(bundles);
}
@@ -185,4 +195,12 @@ class FrameworkWiringImpl implements FrameworkWiring, Runnable
}
}
}
+
+ /**
+ * @see org.osgi.framework.wiring.FrameworkWiring#findProviders(org.osgi.resource.Requirement)
+ */
+ public Collection<BundleCapability> findProviders(final Requirement requirement)
+ {
+ return m_felix.findProviders(requirement);
+ }
}
\ No newline at end of file
diff --git a/src/main/java/org/apache/felix/framework/ResolveContextImpl.java b/src/main/java/org/apache/felix/framework/ResolveContextImpl.java
index 393dabf..270da4f 100644
--- a/src/main/java/org/apache/felix/framework/ResolveContextImpl.java
+++ b/src/main/java/org/apache/felix/framework/ResolveContextImpl.java
@@ -77,11 +77,13 @@ public class ResolveContextImpl extends ResolveContext
return new ArrayList<BundleRevision>(m_ondemand);
}
+ @Override
public List<BundleCapability> findProviders(BundleRequirement br, boolean obeyMandatory)
{
- return m_state.findProvidersInternal(m_resolverHookrecord, br, obeyMandatory);
+ return m_state.findProvidersInternal(m_resolverHookrecord, br, obeyMandatory, true);
}
+ @Override
public int insertHostedCapability(List<BundleCapability> caps, HostedCapability hc)
{
int idx = Collections.binarySearch(caps, hc, new CandidateComparator());
@@ -93,11 +95,13 @@ public class ResolveContextImpl extends ResolveContext
return idx;
}
+ @Override
public boolean isEffective(BundleRequirement br)
{
return m_state.isEffective(br);
}
+ @Override
public Map<BundleRevision, BundleWiring> getWirings()
{
return m_wirings;
diff --git a/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java b/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
index ce35e18..6d77019 100644
--- a/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
+++ b/src/main/java/org/apache/felix/framework/ServiceRegistrationImpl.java
@@ -21,14 +21,26 @@ package org.apache.felix.framework;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
-import java.util.*;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import org.apache.felix.framework.util.MapToDictionary;
import org.apache.felix.framework.util.StringMap;
import org.apache.felix.framework.util.Util;
import org.apache.felix.framework.wiring.BundleCapabilityImpl;
-import org.osgi.framework.*;
+import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
+import org.osgi.framework.Constants;
+import org.osgi.framework.PrototypeServiceFactory;
+import org.osgi.framework.ServiceException;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWire;
@@ -48,7 +60,7 @@ class ServiceRegistrationImpl implements ServiceRegistration
// Service factory interface.
private volatile ServiceFactory m_factory;
// Associated property dictionary.
- private volatile Map m_propMap = new StringMap();
+ private volatile Map<String, Object> m_propMap = new StringMap();
// Re-usable service reference.
private final ServiceReferenceImpl m_ref;
// Flag indicating that we are unregistering.
@@ -281,18 +293,18 @@ class ServiceRegistrationImpl implements ServiceRegistration
}
}
- private void initializeProperties(Dictionary dict)
+ private void initializeProperties(Dictionary<String, Object> dict)
{
// Create a case-insensitive map for the properties.
- Map props = new StringMap();
+ Map<String, Object> props = new StringMap();
if (dict != null)
{
// Make sure there are no duplicate keys.
- Enumeration keys = dict.keys();
+ Enumeration<String> keys = dict.keys();
while (keys.hasMoreElements())
{
- Object key = keys.nextElement();
+ String key = keys.nextElement();
if (props.get(key) == null)
{
props.put(key, dict.get(key));
@@ -307,6 +319,17 @@ class ServiceRegistrationImpl implements ServiceRegistration
// Add the framework assigned properties.
props.put(Constants.OBJECTCLASS, m_classes);
props.put(Constants.SERVICE_ID, m_serviceId);
+ props.put(Constants.SERVICE_BUNDLEID, m_bundle.getBundleId());
+ if ( m_factory != null )
+ {
+ props.put(Constants.SERVICE_SCOPE,
+ (m_factory instanceof PrototypeServiceFactory
+ ? Constants.SCOPE_PROTOTYPE : Constants.SCOPE_BUNDLE));
+ }
+ else
+ {
+ props.put(Constants.SERVICE_SCOPE, Constants.SCOPE_SINGLETON);
+ }
// Update the service property map.
m_propMap = props;
@@ -470,6 +493,7 @@ class ServiceRegistrationImpl implements ServiceRegistration
return ServiceRegistrationImpl.this.getUsingBundles();
}
+ @Override
public String toString()
{
String[] ocs = (String[]) getProperty("objectClass");
diff --git a/src/main/java/org/apache/felix/framework/ServiceRegistry.java b/src/main/java/org/apache/felix/framework/ServiceRegistry.java
index 46c880b..7bd01d2 100644
--- a/src/main/java/org/apache/felix/framework/ServiceRegistry.java
+++ b/src/main/java/org/apache/felix/framework/ServiceRegistry.java
@@ -18,7 +18,18 @@
*/
package org.apache.felix.framework;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.WeakHashMap;
import org.apache.felix.framework.capabilityset.CapabilitySet;
import org.apache.felix.framework.capabilityset.SimpleFilter;
@@ -38,21 +49,21 @@ public class ServiceRegistry
private final Logger m_logger;
private long m_currentServiceId = 1L;
// Maps bundle to an array of service registrations.
- private final Map m_regsMap = Collections.synchronizedMap(new HashMap());
+ private final Map<Bundle, ServiceRegistration<?>[]> m_regsMap = Collections.synchronizedMap(new HashMap<Bundle, ServiceRegistration<?>[]>());
// Capability set for all service registrations.
private final CapabilitySet m_regCapSet;
// Maps registration to thread to keep track when a
// registration is in use, which will cause other
// threads to wait.
- private final Map m_lockedRegsMap = new HashMap();
+ private final Map<ServiceRegistration<?>, Object> m_lockedRegsMap = new HashMap<ServiceRegistration<?>, Object>();
// Maps bundle to an array of usage counts.
- private final Map m_inUseMap = new HashMap();
+ private final Map<Bundle, UsageCount[]> m_inUseMap = new HashMap<Bundle, UsageCount[]>();
private final ServiceRegistryCallbacks m_callbacks;
- private final WeakHashMap<ServiceReference, ServiceReference> m_blackList =
- new WeakHashMap<ServiceReference, ServiceReference>();
+ private final WeakHashMap<ServiceReference<?>, ServiceReference<?>> m_blackList =
+ new WeakHashMap<ServiceReference<?>, ServiceReference<?>>();
private final static Class<?>[] m_hookClasses = {
org.osgi.framework.hooks.bundle.CollisionHook.class,
@@ -63,6 +74,7 @@ public class ServiceRegistry
org.osgi.framework.hooks.service.FindHook.class,
org.osgi.framework.hooks.service.ListenerHook.class,
org.osgi.framework.hooks.weaving.WeavingHook.class,
+ org.osgi.framework.hooks.weaving.WovenClassListener.class,
org.osgi.framework.hooks.resolver.ResolverHookFactory.class,
org.osgi.service.url.URLStreamHandlerService.class,
java.net.ContentHandler.class
@@ -80,12 +92,12 @@ public class ServiceRegistry
m_regCapSet = new CapabilitySet(indices, false);
}
- public ServiceReference[] getRegisteredServices(Bundle bundle)
+ public ServiceReference<?>[] getRegisteredServices(Bundle bundle)
{
- ServiceRegistration[] regs = (ServiceRegistration[]) m_regsMap.get(bundle);
+ ServiceRegistration<?>[] regs = m_regsMap.get(bundle);
if (regs != null)
{
- List refs = new ArrayList(regs.length);
+ List<Object> refs = new ArrayList<Object>(regs.length);
for (int i = 0; i < regs.length; i++)
{
try
@@ -97,13 +109,13 @@ public class ServiceRegistry
// Don't include the reference as it is not valid anymore
}
}
- return (ServiceReference[]) refs.toArray(new ServiceReference[refs.size()]);
+ return refs.toArray(new ServiceReference[refs.size()]);
}
return null;
}
// Caller is expected to fire REGISTERED event.
- public ServiceRegistration registerService(
+ public ServiceRegistration<?> registerService(
BundleContext context, String[] classNames, Object svcObj, Dictionary dict)
{
ServiceRegistrationImpl reg = null;
@@ -120,7 +132,7 @@ public class ServiceRegistry
addHooks(classNames, svcObj, reg.getReference());
// Get the bundles current registered services.
- ServiceRegistration[] regs = (ServiceRegistration[]) m_regsMap.get(bundle);
+ ServiceRegistration<?>[] regs = m_regsMap.get(bundle);
m_regsMap.put(bundle, addServiceRegistration(regs, reg));
m_regCapSet.addCapability((BundleCapabilityImpl) reg.getReference());
}
@@ -128,7 +140,7 @@ public class ServiceRegistry
return reg;
}
- public void unregisterService(Bundle bundle, ServiceRegistration reg)
+ public void unregisterService(Bundle bundle, ServiceRegistration<?> reg)
{
// If this is a hook, it should be removed.
removeHook(reg.getReference());
@@ -142,7 +154,7 @@ public class ServiceRegistry
// new bundles will be able to look up the service.
// Now remove the registered service.
- ServiceRegistration[] regs = (ServiceRegistration[]) m_regsMap.get(bundle);
+ ServiceRegistration<?>[] regs = m_regsMap.get(bundle);
m_regsMap.put(bundle, removeServiceRegistration(regs, reg));
m_regCapSet.removeCapability((BundleCapabilityImpl) reg.getReference());
}
@@ -155,20 +167,32 @@ public class ServiceRegistry
}
// Now forcibly unget the service object for all stubborn clients.
- ServiceReference ref = reg.getReference();
+ ServiceReference<?> ref = reg.getReference();
Bundle[] clients = getUsingBundles(ref);
for (int i = 0; (clients != null) && (i < clients.length); i++)
{
- while (ungetService(clients[i], reg.getReference()))
- ; // Keep removing until it is no longer possible
+ UsageCount[] usages = m_inUseMap.get(clients[i]);
+ for (int x = 0; (usages != null) && (x < usages.length); x++)
+ {
+ if (usages[x].m_ref.equals(ref))
+ {
+ ungetService(clients[i], ref, (usages[x].m_prototype ? usages[x].m_svcObj : null));
+ }
+ }
}
// Invalidate registration
((ServiceRegistrationImpl) reg).invalidate();
// Bundles are allowed to get a reference while unregistering
for (int i = 0; (clients != null) && (i < clients.length); i++)
{
- while (ungetService(clients[i], ref))
- ; // Keep removing until it is no longer possible
+ UsageCount[] usages = m_inUseMap.get(clients[i]);
+ for (int x = 0; (usages != null) && (x < usages.length); x++)
+ {
+ if (usages[x].m_ref.equals(ref))
+ {
+ ungetService(clients[i], ref, (usages[x].m_prototype ? usages[x].m_svcObj : null));
+ }
+ }
}
}
@@ -182,10 +206,10 @@ public class ServiceRegistry
public void unregisterServices(Bundle bundle)
{
// Simply remove all service registrations for the bundle.
- ServiceRegistration[] regs = null;
+ ServiceRegistration<?>[] regs = null;
synchronized (this)
{
- regs = (ServiceRegistration[]) m_regsMap.get(bundle);
+ regs = m_regsMap.get(bundle);
}
// Note, there is no race condition here with respect to the
@@ -216,12 +240,12 @@ public class ServiceRegistry
}
}
- public synchronized List getServiceReferences(String className, SimpleFilter filter)
+ public synchronized Collection getServiceReferences(String className, SimpleFilter filter)
{
if ((className == null) && (filter == null))
{
// Return all services.
- filter = new SimpleFilter(Constants.OBJECTCLASS, "*", SimpleFilter.PRESENT);
+ filter = new SimpleFilter(null, null, SimpleFilter.MATCH_ALL);
}
else if ((className != null) && (filter == null))
{
@@ -231,24 +255,22 @@ public class ServiceRegistry
else if ((className != null) && (filter != null))
{
// Return services matching the class name and filter.
- List filters = new ArrayList(2);
+ List<SimpleFilter> filters = new ArrayList<SimpleFilter>(2);
filters.add(new SimpleFilter(Constants.OBJECTCLASS, className, SimpleFilter.EQ));
filters.add(filter);
filter = new SimpleFilter(null, filters, SimpleFilter.AND);
}
// else just use the specified filter.
- Set<BundleCapability> matches = m_regCapSet.match(filter, false);
-
- return new ArrayList(matches);
+ return m_regCapSet.match(filter, false);
}
- public synchronized ServiceReference[] getServicesInUse(Bundle bundle)
+ public synchronized ServiceReference<?>[] getServicesInUse(Bundle bundle)
{
- UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+ UsageCount[] usages = m_inUseMap.get(bundle);
if (usages != null)
{
- ServiceReference[] refs = new ServiceReference[usages.length];
+ ServiceReference<?>[] refs = new ServiceReference[usages.length];
for (int i = 0; i < refs.length; i++)
{
refs[i] = usages[i].m_ref;
@@ -258,7 +280,8 @@ public class ServiceRegistry
return null;
}
- public <S> S getService(Bundle bundle, ServiceReference<S> ref)
+ @SuppressWarnings("unchecked")
+ public <S> S getService(Bundle bundle, ServiceReference<S> ref, boolean isPrototype)
{
UsageCount usage = null;
Object svcObj = null;
@@ -299,14 +322,15 @@ public class ServiceRegistry
if (reg.isValid())
{
// Get the usage count, if any.
- usage = getUsageCount(bundle, ref);
+ // if prototype, we always create a new usage
+ usage = isPrototype ? null : getUsageCount(bundle, ref, null);
// If we don't have a usage count, then create one and
// since the spec says we increment usage count before
// actually getting the service object.
if (usage == null)
{
- usage = addUsageCount(bundle, ref);
+ usage = addUsageCount(bundle, ref, isPrototype);
}
// Increment the usage count and grab the already retrieved
@@ -340,7 +364,7 @@ public class ServiceRegistry
// unregistered while we didn't hold the lock.
if (!reg.isValid() || (svcObj == null))
{
- flushUsageCount(bundle, ref);
+ flushUsageCount(bundle, ref, usage);
}
else
{
@@ -354,7 +378,7 @@ public class ServiceRegistry
return (S) svcObj;
}
- public boolean ungetService(Bundle bundle, ServiceReference ref)
+ public boolean ungetService(Bundle bundle, ServiceReference<?> ref, Object svcObj)
{
UsageCount usage = null;
ServiceRegistrationImpl reg =
@@ -384,7 +408,7 @@ public class ServiceRegistry
}
// Get the usage count.
- usage = getUsageCount(bundle, ref);
+ usage = getUsageCount(bundle, ref, svcObj);
// If there is no cached services, then just return immediately.
if (usage == null)
{
@@ -424,7 +448,7 @@ public class ServiceRegistry
if (!reg.isValid() || (usage.m_count <= 0))
{
usage.m_svcObj = null;
- flushUsageCount(bundle, ref);
+ flushUsageCount(bundle, ref, usage);
}
// Release the registration lock so any waiting threads can
@@ -448,7 +472,7 @@ public class ServiceRegistry
UsageCount[] usages;
synchronized (this)
{
- usages = (UsageCount[]) m_inUseMap.get(bundle);
+ usages = m_inUseMap.get(bundle);
}
if (usages == null)
@@ -466,21 +490,21 @@ public class ServiceRegistry
for (int i = 0; i < usages.length; i++)
{
// Keep ungetting until all usage count is zero.
- while (ungetService(bundle, usages[i].m_ref))
+ while (ungetService(bundle, usages[i].m_ref, usages[i].m_prototype ? usages[i].m_svcObj : null))
{
// Empty loop body.
}
}
}
- public synchronized Bundle[] getUsingBundles(ServiceReference ref)
+ public synchronized Bundle[] getUsingBundles(ServiceReference<?> ref)
{
Bundle[] bundles = null;
- for (Iterator iter = m_inUseMap.entrySet().iterator(); iter.hasNext(); )
+ for (Iterator<Map.Entry<Bundle, UsageCount[]>> iter = m_inUseMap.entrySet().iterator(); iter.hasNext(); )
{
- Map.Entry entry = (Map.Entry) iter.next();
- Bundle bundle = (Bundle) entry.getKey();
- UsageCount[] usages = (UsageCount[]) entry.getValue();
+ Map.Entry<Bundle, UsageCount[]> entry = iter.next();
+ Bundle bundle = entry.getKey();
+ UsageCount[] usages = entry.getValue();
for (int useIdx = 0; useIdx < usages.length; useIdx++)
{
if (usages[useIdx].m_ref.equals(ref))
@@ -503,7 +527,7 @@ public class ServiceRegistry
return bundles;
}
- void servicePropertiesModified(ServiceRegistration reg, Dictionary oldProps)
+ void servicePropertiesModified(ServiceRegistration<?> reg, Dictionary oldProps)
{
updateHook(reg.getReference());
if (m_callbacks != null)
@@ -518,8 +542,8 @@ public class ServiceRegistry
return m_logger;
}
- private static ServiceRegistration[] addServiceRegistration(
- ServiceRegistration[] regs, ServiceRegistration reg)
+ private static ServiceRegistration<?>[] addServiceRegistration(
+ ServiceRegistration<?>[] regs, ServiceRegistration<?> reg)
{
if (regs == null)
{
@@ -527,7 +551,7 @@ public class ServiceRegistry
}
else
{
- ServiceRegistration[] newRegs = new ServiceRegistration[regs.length + 1];
+ ServiceRegistration<?>[] newRegs = new ServiceRegistration[regs.length + 1];
System.arraycopy(regs, 0, newRegs, 0, regs.length);
newRegs[regs.length] = reg;
regs = newRegs;
@@ -535,8 +559,8 @@ public class ServiceRegistry
return regs;
}
- private static ServiceRegistration[] removeServiceRegistration(
- ServiceRegistration[] regs, ServiceRegistration reg)
+ private static ServiceRegistration<?>[] removeServiceRegistration(
+ ServiceRegistration<?>[] regs, ServiceRegistration<?> reg)
{
for (int i = 0; (regs != null) && (i < regs.length); i++)
{
@@ -550,7 +574,7 @@ public class ServiceRegistry
// Otherwise, we need to do some array copying.
else
{
- ServiceRegistration[] newRegs = new ServiceRegistration[regs.length - 1];
+ ServiceRegistration<?>[] newRegs = new ServiceRegistration[regs.length - 1];
System.arraycopy(regs, 0, newRegs, 0, i);
if (i < newRegs.length)
{
@@ -571,12 +595,14 @@ public class ServiceRegistry
* @param ref The service reference to find in the bundle's usage counts.
* @return The associated usage count or null if not found.
**/
- private UsageCount getUsageCount(Bundle bundle, ServiceReference ref)
+ private UsageCount getUsageCount(Bundle bundle, ServiceReference<?> ref, final Object svcObj)
{
- UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+ UsageCount[] usages = m_inUseMap.get(bundle);
for (int i = 0; (usages != null) && (i < usages.length); i++)
{
- if (usages[i].m_ref.equals(ref))
+ if (usages[i].m_ref.equals(ref)
+ && ((svcObj == null && !usages[i].m_prototype)
+ || (usages[i].m_svcObj == svcObj && usages[i].m_prototype)))
{
return usages[i];
}
@@ -594,12 +620,13 @@ public class ServiceRegistry
* @param ref The service reference of the acquired service.
* @param svcObj The service object of the acquired service.
**/
- private UsageCount addUsageCount(Bundle bundle, ServiceReference ref)
+ private UsageCount addUsageCount(Bundle bundle, ServiceReference<?> ref, boolean isPrototype)
{
- UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+ UsageCount[] usages = m_inUseMap.get(bundle);
UsageCount usage = new UsageCount();
usage.m_ref = ref;
+ usage.m_prototype = isPrototype;
if (usages == null)
{
@@ -630,12 +657,12 @@ public class ServiceRegistry
* @param bundle The bundle whose usage count should be removed.
* @param ref The service reference whose usage count should be removed.
**/
- private void flushUsageCount(Bundle bundle, ServiceReference ref)
+ private void flushUsageCount(Bundle bundle, ServiceReference<?> ref, UsageCount uc)
{
- UsageCount[] usages = (UsageCount[]) m_inUseMap.get(bundle);
+ UsageCount[] usages = m_inUseMap.get(bundle);
for (int i = 0; (usages != null) && (i < usages.length); i++)
{
- if (usages[i].m_ref.equals(ref))
+ if ((uc == null && usages[i].m_ref.equals(ref)) || (uc == usages[i]))
{
// If this is the only usage, then point to empty list.
if ((usages.length - 1) == 0)
@@ -653,6 +680,7 @@ public class ServiceRegistry
usages, i + 1, newUsages, i, newUsages.length - i);
}
usages = newUsages;
+ i--;
}
}
}
@@ -671,12 +699,12 @@ public class ServiceRegistry
// Hook-related methods.
//
- boolean isHookBlackListed(ServiceReference sr)
+ boolean isHookBlackListed(ServiceReference<?> sr)
{
return m_blackList.containsKey(sr);
}
- void blackListHook(ServiceReference sr)
+ void blackListHook(ServiceReference<?> sr)
{
m_blackList.put(sr, sr);
}
@@ -731,7 +759,7 @@ public class ServiceRegistry
}
}
- private void updateHook(ServiceReference ref)
+ private void updateHook(ServiceReference<?> ref)
{
// We maintain the hooks sorted, so if ranking has changed for example,
// we need to ensure the order remains correct by resorting the hooks.
@@ -757,7 +785,7 @@ public class ServiceRegistry
}
}
- private void removeHook(ServiceReference ref)
+ private void removeHook(ServiceReference<?> ref)
{
Object svcObj = ((ServiceRegistrationImpl.ServiceReferenceImpl) ref)
.getRegistration().getService();
@@ -790,25 +818,26 @@ public class ServiceRegistry
Set<ServiceReference<?>> hooks = m_allHooks.get(hookClass);
if (hooks != null)
{
- SortedSet sorted = new TreeSet<ServiceReference<?>>(Collections.reverseOrder());
+ SortedSet<ServiceReference<?>> sorted = new TreeSet<ServiceReference<?>>(Collections.reverseOrder());
sorted.addAll(hooks);
return asTypedSortedSet(sorted);
}
- return Collections.EMPTY_SET;
+ return Collections.emptySet();
}
}
private static <S> SortedSet<ServiceReference<S>> asTypedSortedSet(
SortedSet<ServiceReference<?>> ss)
{
- return (SortedSet<ServiceReference<S>>) (SortedSet) ss;
+ return (SortedSet) ss;
}
private static class UsageCount
{
- public int m_count = 0;
- public ServiceReference m_ref = null;
- public Object m_svcObj = null;
+ public int m_count;
+ public ServiceReference<?> m_ref;
+ public Object m_svcObj;
+ public boolean m_prototype;
}
public interface ServiceRegistryCallbacks
diff --git a/src/main/java/org/apache/felix/framework/StatefulResolver.java b/src/main/java/org/apache/felix/framework/StatefulResolver.java
index 6c6e75f..11464a1 100644
--- a/src/main/java/org/apache/felix/framework/StatefulResolver.java
+++ b/src/main/java/org/apache/felix/framework/StatefulResolver.java
@@ -31,6 +31,7 @@ import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.StringTokenizer;
+
import org.apache.felix.framework.capabilityset.CapabilitySet;
import org.apache.felix.framework.capabilityset.SimpleFilter;
import org.apache.felix.framework.resolver.CandidateComparator;
@@ -40,8 +41,7 @@ import org.apache.felix.framework.resolver.ResolverImpl;
import org.apache.felix.framework.resolver.ResolverWire;
import org.apache.felix.framework.util.ShrinkableCollection;
import org.apache.felix.framework.util.Util;
-import org.apache.felix.framework.util.manifestparser.R4Library;
-import org.apache.felix.framework.wiring.BundleCapabilityImpl;
+import org.apache.felix.framework.util.manifestparser.NativeLibrary;
import org.apache.felix.framework.wiring.BundleRequirementImpl;
import org.apache.felix.framework.wiring.BundleWireImpl;
import org.osgi.framework.Bundle;
@@ -59,6 +59,7 @@ import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWire;
import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.resource.Requirement;
class StatefulResolver
{
@@ -175,11 +176,14 @@ class StatefulResolver
{
ResolverHookRecord record = new ResolverHookRecord(
Collections.<ServiceReference<ResolverHookFactory>, ResolverHook>emptyMap(), null);
- return findProvidersInternal(record, req, obeyMandatory);
+ return findProvidersInternal(record, req, obeyMandatory, true);
}
synchronized List<BundleCapability> findProvidersInternal(
- ResolverHookRecord record, BundleRequirement req, boolean obeyMandatory)
+ final ResolverHookRecord record,
+ final Requirement req,
+ final boolean obeyMandatory,
+ final boolean invokeHooksAndSecurity)
{
List<BundleCapability> result = new ArrayList<BundleCapability>();
@@ -213,7 +217,7 @@ class StatefulResolver
for (BundleCapability cap : matches)
{
// Filter according to security.
- if (filteredBySecurity(req, cap))
+ if (invokeHooksAndSecurity && filteredBySecurity((BundleRequirement)req, cap))
{
continue;
}
@@ -229,36 +233,39 @@ class StatefulResolver
}
}
- // If we have resolver hooks, then we may need to filter our results
- // based on a whitelist and/or fine-grained candidate filtering.
- if (!result.isEmpty() && !record.getResolverHookRefs().isEmpty())
+ if ( invokeHooksAndSecurity )
{
- // It we have a whitelist, then first filter out candidates
- // from disallowed revisions.
- if (record.getBundleRevisionWhitelist() != null)
+ // If we have resolver hooks, then we may need to filter our results
+ // based on a whitelist and/or fine-grained candidate filtering.
+ if (!result.isEmpty() && !record.getResolverHookRefs().isEmpty())
{
- for (Iterator<BundleCapability> it = result.iterator(); it.hasNext(); )
+ // It we have a whitelist, then first filter out candidates
+ // from disallowed revisions.
+ if (record.getBundleRevisionWhitelist() != null)
{
- if (!record.getBundleRevisionWhitelist().contains(it.next().getRevision()))
+ for (Iterator<BundleCapability> it = result.iterator(); it.hasNext(); )
{
- it.remove();
+ if (!record.getBundleRevisionWhitelist().contains(it.next().getRevision()))
+ {
+ it.remove();
+ }
}
}
- }
- // Now give the hooks a chance to do fine-grained filtering.
- ShrinkableCollection<BundleCapability> shrinkable =
- new ShrinkableCollection<BundleCapability>(result);
- for (ResolverHook hook : record.getResolverHooks())
- {
- try
+ // Now give the hooks a chance to do fine-grained filtering.
+ ShrinkableCollection<BundleCapability> shrinkable =
+ new ShrinkableCollection<BundleCapability>(result);
+ for (ResolverHook hook : record.getResolverHooks())
{
- Felix.m_secureAction
- .invokeResolverHookMatches(hook, req, shrinkable);
- }
- catch (Throwable th)
- {
- m_logger.log(Logger.LOG_WARNING, "Resolver hook exception.", th);
+ try
+ {
+ Felix.m_secureAction
+ .invokeResolverHookMatches(hook, (BundleRequirement)req, shrinkable);
+ }
+ catch (Throwable th)
+ {
+ m_logger.log(Logger.LOG_WARNING, "Resolver hook exception.", th);
+ }
}
}
}
@@ -566,7 +573,7 @@ class StatefulResolver
throws BundleException
{
// This map maps the hook factory service to the actual hook objects. It
- // needs to be a map that preserves insertion order to ensure that we call
+ // needs to be a map that preserves insertion order to ensure that we call
// hooks in the correct order.
// The hooks are added in the order that m_felix.getHooks() returns them which
// is also the order in which they should be called.
@@ -595,13 +602,13 @@ class StatefulResolver
triggers = Collections.unmodifiableSet(triggers);
BundleException rethrow = null;
-
+
// Create resolver hook objects by calling begin() on factory.
for (ServiceReference<ResolverHookFactory> ref : hookRefs)
{
try
{
- ResolverHookFactory rhf = m_felix.getService(m_felix, ref);
+ ResolverHookFactory rhf = m_felix.getService(m_felix, ref, false);
if (rhf != null)
{
ResolverHook hook =
@@ -621,7 +628,7 @@ class StatefulResolver
ex);
// Resolver hook spec: if there is an exception during the resolve operation; abort.
// So we break here to make sure that no further resolver hooks are created.
- break;
+ break;
}
}
@@ -663,7 +670,7 @@ class StatefulResolver
ex);
// Resolver hook spec: if there is an exception during the resolve operation; abort.
// So we break here to make sure that no further resolver operations are executed.
- break;
+ break;
}
}
@@ -751,7 +758,7 @@ class StatefulResolver
{
invalid = true;
}
- m_felix.ungetService(m_felix, ref);
+ m_felix.ungetService(m_felix, ref, null);
}
if (invalid)
{
@@ -824,7 +831,7 @@ class StatefulResolver
{
BundleCapability cap = itCand.next();
if (CapabilitySet.matches(
- (BundleCapabilityImpl) cap,
+ cap,
((BundleRequirementImpl) dynamics.get(dynIdx)).getFilter()))
{
dynReq = (BundleRequirementImpl) dynamics.get(dynIdx);
@@ -841,7 +848,7 @@ class StatefulResolver
{
BundleCapability cap = itCand.next();
if (!CapabilitySet.matches(
- (BundleCapabilityImpl) cap, dynReq.getFilter()))
+ cap, dynReq.getFilter()))
{
itCand.remove();
}
@@ -1475,7 +1482,7 @@ class StatefulResolver
{
// Next, try to resolve any native code, since the revision is
// not resolvable if its native code cannot be loaded.
- List<R4Library> libs = ((BundleRevisionImpl) revision).getDeclaredNativeLibraries();
+ List<NativeLibrary> libs = ((BundleRevisionImpl) revision).getDeclaredNativeLibraries();
if (libs != null)
{
String msg = null;
@@ -1570,7 +1577,7 @@ class StatefulResolver
{
final Map<ServiceReference<ResolverHookFactory>, ResolverHook> m_resolveHookMap;
final Collection<BundleRevision> m_brWhitelist;
-
+
/** The map passed in must be of an ordered type, so that the iteration order over the values
* is predictable.
*/
@@ -1580,8 +1587,8 @@ class StatefulResolver
m_resolveHookMap = resolveHookMap;
m_brWhitelist = brWhiteList;
}
-
- Collection<BundleRevision> getBundleRevisionWhitelist()
+
+ Collection<BundleRevision> getBundleRevisionWhitelist()
{
return m_brWhitelist;
}
diff --git a/src/main/java/org/apache/felix/framework/URLHandlers.java b/src/main/java/org/apache/felix/framework/URLHandlers.java
index dfe0828..c8fd75a 100644
--- a/src/main/java/org/apache/felix/framework/URLHandlers.java
+++ b/src/main/java/org/apache/felix/framework/URLHandlers.java
@@ -87,7 +87,7 @@ class URLHandlers implements URLStreamHandlerFactory, ContentHandlerFactory
// This maps classloaders of URLHandlers in other classloaders to lists of
// their frameworks.
- private static Map m_classloaderToFrameworkLists = new HashMap();
+ private final static Map m_classloaderToFrameworkLists = new HashMap();
// The list to hold all enabled frameworks registered with this handlers
private static final List m_frameworks = new ArrayList();
@@ -586,6 +586,7 @@ class URLHandlers implements URLStreamHandlerFactory, ContentHandlerFactory
**/
public static void registerFrameworkInstance(Object framework, boolean enable)
{
+ boolean register = false;
synchronized (m_frameworks)
{
// If the URL Handlers service is not going to be enabled,
@@ -595,13 +596,38 @@ class URLHandlers implements URLStreamHandlerFactory, ContentHandlerFactory
// We need to create an instance if this is the first
// time this method is called, which will set the handler
// factories.
- if (m_handler == null)
+ if (m_handler == null )
{
- m_handler = new URLHandlers();
+ register = true;
+ }
+ else
+ {
+ m_frameworks.add(framework);
+ m_counter++;
+ }
+ }
+ else
+ {
+ m_counter++;
+ }
+ }
+ if (register)
+ {
+ synchronized (URL.class)
+ {
+ synchronized (m_classloaderToFrameworkLists)
+ {
+ synchronized (m_frameworks)
+ {
+ if (m_handler == null )
+ {
+ m_handler = new URLHandlers();
+ }
+ m_frameworks.add(framework);
+ m_counter++;
+ }
}
- m_frameworks.add(framework);
}
- m_counter++;
}
}
@@ -618,32 +644,55 @@ class URLHandlers implements URLStreamHandlerFactory, ContentHandlerFactory
boolean unregister = false;
synchronized (m_frameworks)
{
- m_counter--;
- if (m_frameworks.remove(framework))
+ if (m_frameworks.contains(framework))
{
- if (m_frameworks.isEmpty())
+ if (m_frameworks.size() == 1 && m_handler != null)
{
unregister = true;
- m_handler = null;
+ }
+ else
+ {
+ m_frameworks.remove(framework);
+ m_counter--;
}
}
+ else
+ {
+ m_counter--;
+ }
}
if (unregister)
{
- try
- {
- m_secureAction.invoke(m_secureAction.getDeclaredMethod(
- m_rootURLHandlers.getClass(),
- "unregisterFrameworkListsForContextSearch",
- new Class[]{ ClassLoader.class}),
- m_rootURLHandlers,
- new Object[] {URLHANDLERS_CLASS.getClassLoader()});
- }
- catch (Exception e)
- {
- // This should not happen
- e.printStackTrace();
- }
+ synchronized (URL.class)
+ {
+ synchronized (m_classloaderToFrameworkLists)
+ {
+ synchronized (m_frameworks)
+ {
+ m_frameworks.remove(framework);
+ m_counter--;
+ if (m_frameworks.isEmpty() && m_handler != null)
+ {
+
+ m_handler = null;
+ try
+ {
+ m_secureAction.invoke(m_secureAction.getDeclaredMethod(
+ m_rootURLHandlers.getClass(),
+ "unregisterFrameworkListsForContextSearch",
+ new Class[]{ ClassLoader.class}),
+ m_rootURLHandlers,
+ new Object[] {URLHANDLERS_CLASS.getClassLoader()});
+ }
+ catch (Exception e)
+ {
+ // This should not happen
+ e.printStackTrace();
+ }
+ }
+ }
+ }
+ }
}
}
diff --git a/src/main/java/org/apache/felix/framework/URLHandlersActivator.java b/src/main/java/org/apache/felix/framework/URLHandlersActivator.java
index 4eca450..d8dea4a 100644
--- a/src/main/java/org/apache/felix/framework/URLHandlersActivator.java
+++ b/src/main/java/org/apache/felix/framework/URLHandlersActivator.java
@@ -19,8 +19,6 @@
package org.apache.felix.framework;
import java.net.ContentHandler;
-import java.util.Arrays;
-import java.util.Collections;
import java.util.Map;
import java.util.Set;
@@ -29,7 +27,6 @@ import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.url.URLStreamHandlerService;
-import org.osgi.util.tracker.ServiceTracker;
/**
* <p>
@@ -107,13 +104,13 @@ class URLHandlersActivator implements BundleActivator
{
if (value.equals(((String[]) values)[valueIdx]))
{
- return m_framework.getService(m_framework, ref);
+ return m_framework.getService(m_framework, ref, false);
}
}
}
else if (value.equals(values))
{
- return m_framework.getService(m_framework, ref);
+ return m_framework.getService(m_framework, ref, false);
}
}
}
diff --git a/src/main/java/org/apache/felix/framework/WovenClassImpl.java b/src/main/java/org/apache/felix/framework/WovenClassImpl.java
index 2f44e5a..9ae77a3 100644
--- a/src/main/java/org/apache/felix/framework/WovenClassImpl.java
+++ b/src/main/java/org/apache/felix/framework/WovenClassImpl.java
@@ -24,11 +24,14 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
+
import org.apache.felix.framework.util.ImmutableList;
import org.apache.felix.framework.util.manifestparser.ManifestParser;
import org.osgi.framework.AdminPermission;
+import org.osgi.framework.PackagePermission;
import org.osgi.framework.hooks.weaving.WovenClass;
import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.BundleWiring;
class WovenClassImpl implements WovenClass, List<String>
@@ -39,22 +42,34 @@ class WovenClassImpl implements WovenClass, List<String>
private List<String> m_imports = new ArrayList<String>();
private Class m_definedClass = null;
private boolean m_isComplete = false;
+ private int m_state;
- /* package */ WovenClassImpl(String className, BundleWiring wiring, byte[] bytes)
+ /* package */WovenClassImpl(String className, BundleWiring wiring,
+ byte[] bytes)
{
m_className = className;
m_wiring = wiring;
m_bytes = bytes;
+ m_state = TRANSFORMING;
}
- synchronized void complete(Class definedClass, byte[] bytes, List<String> imports)
+ synchronized void complete(Class definedClass, byte[] bytes,
+ List<String> imports)
{
- m_isComplete = true;
- m_definedClass = definedClass;
+ completeDefine(definedClass);
m_bytes = (bytes == null) ? m_bytes : bytes;
- m_imports = (imports == null)
- ? ImmutableList.newInstance(m_imports)
- : ImmutableList.newInstance(imports);
+ completeImports(imports);
+ }
+
+ synchronized void completeImports(List<String> imports)
+ {
+ m_imports = (imports == null) ? ImmutableList.newInstance(m_imports)
+ : ImmutableList.newInstance(imports);
+ }
+
+ synchronized void completeDefine(Class definedClass)
+ {
+ m_definedClass = definedClass;
}
public synchronized byte[] getBytes()
@@ -62,7 +77,8 @@ class WovenClassImpl implements WovenClass, List<String>
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+ sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
+ AdminPermission.WEAVE));
}
byte[] bytes = m_bytes;
if (m_isComplete)
@@ -78,14 +94,14 @@ class WovenClassImpl implements WovenClass, List<String>
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+ sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
+ AdminPermission.WEAVE));
}
- if (m_isComplete)
+ if (m_state >= TRANSFORMED)
{
throw new IllegalStateException(
- "Cannot change bytes after class weaving is completed.");
- }
- else
+ "Cannot change bytes after class weaving is completed.");
+ } else
{
m_bytes = bytes;
}
@@ -113,7 +129,8 @@ class WovenClassImpl implements WovenClass, List<String>
public ProtectionDomain getProtectionDomain()
{
- return ((BundleImpl) m_wiring.getRevision().getBundle()).getProtectionDomain();
+ return ((BundleImpl) m_wiring.getRevision().getBundle())
+ .getProtectionDomain();
}
public synchronized Class<?> getDefinedClass()
@@ -168,33 +185,45 @@ class WovenClassImpl implements WovenClass, List<String>
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+ sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
+ AdminPermission.WEAVE));
}
if (s != null)
{
try
{
- List<BundleRequirement> reqs =
- ManifestParser.parseDynamicImportHeader(null, null, s);
- }
- catch (Exception ex)
+ List<BundleRequirement> reqs = ManifestParser
+ .parseDynamicImportHeader(null, null, s);
+ } catch (Exception ex)
{
- RuntimeException re =
- new IllegalArgumentException("Unable to parse dynamic import.");
+ RuntimeException re = new IllegalArgumentException(
+ "Unable to parse dynamic import.");
re.initCause(ex);
throw re;
}
+ checkImport(s);
return m_imports.add(s);
}
return false;
}
+ private void checkImport(String s)
+ {
+ SecurityManager sm = System.getSecurityManager();
+
+ if (sm != null)
+ {
+ sm.checkPermission(new PackagePermission(s, PackagePermission.IMPORT));
+ }
+ }
+
public synchronized boolean remove(Object o)
{
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+ sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
+ AdminPermission.WEAVE));
}
return m_imports.remove(o);
}
@@ -209,47 +238,50 @@ class WovenClassImpl implements WovenClass, List<String>
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+ sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
+ AdminPermission.WEAVE));
}
for (String s : collection)
{
try
{
- List<BundleRequirement> reqs =
- ManifestParser.parseDynamicImportHeader(null, null, s);
- }
- catch (Exception ex)
+ List<BundleRequirement> reqs = ManifestParser
+ .parseDynamicImportHeader(null, null, s);
+ } catch (Exception ex)
{
- RuntimeException re =
- new IllegalArgumentException("Unable to parse dynamic import.");
+ RuntimeException re = new IllegalArgumentException(
+ "Unable to parse dynamic import.");
re.initCause(ex);
throw re;
}
+ checkImport(s);
}
return m_imports.addAll(collection);
}
- public synchronized boolean addAll(int i, Collection<? extends String> collection)
+ public synchronized boolean addAll(int i,
+ Collection<? extends String> collection)
{
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+ sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
+ AdminPermission.WEAVE));
}
for (String s : collection)
{
try
{
- List<BundleRequirement> reqs =
- ManifestParser.parseDynamicImportHeader(null, null, s);
- }
- catch (Exception ex)
+ List<BundleRequirement> reqs = ManifestParser
+ .parseDynamicImportHeader(null, null, s);
+ } catch (Exception ex)
{
- RuntimeException re =
- new IllegalArgumentException("Unable to parse dynamic import.");
+ RuntimeException re = new IllegalArgumentException(
+ "Unable to parse dynamic import.");
re.initCause(ex);
throw re;
}
+ checkImport(s);
}
return m_imports.addAll(i, collection);
}
@@ -259,7 +291,8 @@ class WovenClassImpl implements WovenClass, List<String>
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+ sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
+ AdminPermission.WEAVE));
}
return m_imports.removeAll(collection);
}
@@ -269,13 +302,20 @@ class WovenClassImpl implements WovenClass, List<String>
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+ sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
+ AdminPermission.WEAVE));
}
return m_imports.retainAll(collection);
}
public synchronized void clear()
{
+ SecurityManager sm = System.getSecurityManager();
+ if (sm != null)
+ {
+ sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
+ AdminPermission.WEAVE));
+ }
m_imports.clear();
}
@@ -289,20 +329,21 @@ class WovenClassImpl implements WovenClass, List<String>
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+ sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
+ AdminPermission.WEAVE));
}
try
{
- List<BundleRequirement> reqs =
- ManifestParser.parseDynamicImportHeader(null, null, s);
- }
- catch (Exception ex)
+ List<BundleRequirement> reqs = ManifestParser
+ .parseDynamicImportHeader(null, null, s);
+ } catch (Exception ex)
{
- RuntimeException re =
- new IllegalArgumentException("Unable to parse dynamic import.");
+ RuntimeException re = new IllegalArgumentException(
+ "Unable to parse dynamic import.");
re.initCause(ex);
throw re;
}
+ checkImport(s);
return m_imports.set(i, s);
}
@@ -311,20 +352,21 @@ class WovenClassImpl implements WovenClass, List<String>
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+ sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
+ AdminPermission.WEAVE));
}
try
{
- List<BundleRequirement> reqs =
- ManifestParser.parseDynamicImportHeader(null, null, s);
- }
- catch (Exception ex)
+ List<BundleRequirement> reqs = ManifestParser
+ .parseDynamicImportHeader(null, null, s);
+ } catch (Exception ex)
{
- RuntimeException re =
- new IllegalArgumentException("Unable to parse dynamic import.");
+ RuntimeException re = new IllegalArgumentException(
+ "Unable to parse dynamic import.");
re.initCause(ex);
throw re;
}
+ checkImport(s);
m_imports.add(i, s);
}
@@ -333,7 +375,8 @@ class WovenClassImpl implements WovenClass, List<String>
SecurityManager sm = System.getSecurityManager();
if (sm != null)
{
- sm.checkPermission(new AdminPermission(m_wiring.getBundle(), AdminPermission.WEAVE));
+ sm.checkPermission(new AdminPermission(m_wiring.getBundle(),
+ AdminPermission.WEAVE));
}
return m_imports.remove(i);
}
@@ -373,4 +416,40 @@ class WovenClassImpl implements WovenClass, List<String>
}
return bytes;
}
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.osgi.framework.hooks.weaving.WovenClass#getState()
+ */
+ public synchronized int getState()
+ {
+ return m_state;
+ }
+
+ public synchronized void setState(int state)
+ {
+ // Per 56.6.4.13 Weaving complete if state is DEFINED, DEFINE_FAILED, or
+ // TRANSFORMING_FAILED
+ if (!m_isComplete
+ && (state == DEFINED || state == DEFINE_FAILED || state == TRANSFORMING_FAILED))
+ {
+ m_isComplete = true;
+ if (state == DEFINED || state == DEFINE_FAILED)
+ {
+ BundleProtectionDomain pd = (BundleProtectionDomain)
+ ((BundleRevisionImpl) m_wiring.getRevision()).getProtectionDomain();
+ for (String s : m_imports)
+ {
+ pd.addWoven(s);
+ }
+ }
+ }
+ if(state == TRANSFORMED)
+ {
+ completeImports(null);
+ }
+ m_state = state;
+ }
+
}
\ No newline at end of file
diff --git a/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java b/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java
index 738652e..8f0c605 100644
--- a/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java
+++ b/src/main/java/org/apache/felix/framework/capabilityset/CapabilitySet.java
@@ -32,9 +32,12 @@ import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
+
import org.apache.felix.framework.util.SecureAction;
import org.apache.felix.framework.util.StringComparator;
+import org.apache.felix.framework.util.VersionRange;
import org.apache.felix.framework.wiring.BundleCapabilityImpl;
+import org.osgi.framework.Version;
import org.osgi.framework.wiring.BundleCapability;
public class CapabilitySet
@@ -236,7 +239,10 @@ public class CapabilitySet
if (existingCaps != null)
{
matches.addAll(existingCaps);
- matches.retainAll(caps);
+ if (caps != m_capSet)
+ {
+ matches.retainAll(caps);
+ }
}
}
else
@@ -385,6 +391,26 @@ public class CapabilitySet
return true;
}
+ //Need a special case here when lhs is a Version and rhs is a VersionRange
+ //Version is comparable so we need to check this first
+ if(lhs instanceof Version && op == SimpleFilter.EQ)
+ {
+ Object rhs = null;
+ try
+ {
+ rhs = coerceType(lhs, (String) rhsUnknown);
+ }
+ catch (Exception ex)
+ {
+ //Do nothing will check later if rhs is null
+ }
+
+ if(rhs != null && rhs instanceof VersionRange)
+ {
+ return ((VersionRange)rhs).isInRange((Version)lhs);
+ }
+ }
+
// If the type is comparable, then we can just return the
// result immediately.
if (lhs instanceof Comparable)
@@ -565,6 +591,10 @@ public class CapabilitySet
{
rhs = new Character(rhsString.charAt(0));
}
+ else if(lhs instanceof Version && rhsString.indexOf(',') >= 0)
+ {
+ rhs = VersionRange.parse(rhsString);
+ }
else
{
// Spec says we should trim number types.
diff --git a/src/main/java/org/apache/felix/framework/util/EventDispatcher.java b/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
index c5c264c..0435464 100644
--- a/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
+++ b/src/main/java/org/apache/felix/framework/util/EventDispatcher.java
@@ -197,6 +197,7 @@ public class EventDispatcher
catch (IllegalStateException ex)
{
// Bundle context is no longer valid, so just return.
+ return null;
}
Map<BundleContext, List<ListenerInfo>> listeners = null;
@@ -576,16 +577,32 @@ public class EventDispatcher
m_registry.getHooks(org.osgi.framework.hooks.service.EventListenerHook.class);
if ((elhs != null) && !elhs.isEmpty())
{
- // Create shrinkable map with shrinkable collections.
+ List<ListenerInfo> systemBundleListeners = null;
+
+ // The mutable map is used to keep the lists that underpin the shrinkable collections.
+ Map<BundleContext, List<ListenerInfo>> mutableMap =
+ new HashMap<BundleContext, List<ListenerInfo>>();
+ // Create map with shrinkable collections.
Map<BundleContext, Collection<ListenerHook.ListenerInfo>> shrinkableMap =
new HashMap<BundleContext, Collection<ListenerHook.ListenerInfo>>();
for (Entry<BundleContext, List<ListenerInfo>> entry : listeners.entrySet())
{
- Collection shrinkableCollection =
- new ShrinkableCollection(new ArrayList(entry.getValue()));
- shrinkableMap.put(
- entry.getKey(),
- (Collection<ListenerHook.ListenerInfo>) shrinkableCollection);
+ BundleContext bc = entry.getKey();
+ ArrayList<ListenerInfo> mutableList = new ArrayList<ListenerInfo>(entry.getValue());
+ mutableMap.put(bc, mutableList);
+
+ // We want to pass the list as a generic collection to Shrinkable Collection.
+ // Need to convert to raw type before we can do this...
+ ArrayList ml = mutableList;
+
+ Collection<ListenerHook.ListenerInfo> shrinkableCollection =
+ new ShrinkableCollection<ListenerHook.ListenerInfo>(ml);
+ shrinkableMap.put(bc, shrinkableCollection);
+
+ // Keep a copy of the System Bundle Listeners, as they might be removed by the hooks, but we
+ // actually need to keep them in the end.
+ if (bc == felix.getBundleContext())
+ systemBundleListeners = new ArrayList<ListenerInfo>(entry.getValue());
}
shrinkableMap =
new ShrinkableMap<BundleContext, Collection<ListenerHook.ListenerInfo>>
@@ -598,7 +615,7 @@ public class EventDispatcher
org.osgi.framework.hooks.service.EventListenerHook elh = null;
try
{
- elh = m_registry.getService(felix, sr);
+ elh = m_registry.getService(felix, sr, false);
}
catch (Exception ex)
{
@@ -618,23 +635,33 @@ public class EventDispatcher
}
finally
{
- m_registry.ungetService(felix, sr);
+ m_registry.ungetService(felix, sr, null);
}
}
}
}
+
// TODO: OSGi R4.3 - Should check and only do this if there was a change.
-// Also, it is inefficient to have to create new lists for the values.
+
+ // the listeners map should only contain List values, and not Shrinkable
+ // Collections. Therefore we create a new map from the lists that are
+ // the delegates for the Shrinkable Collections. Any changes made by the
+ // hooks will have propagated to these maps.
Map<BundleContext, List<ListenerInfo>> newMap =
new HashMap<BundleContext, List<ListenerInfo>>();
- for (Entry entry : shrinkableMap.entrySet())
+ for (Map.Entry<BundleContext, Collection<ListenerHook.ListenerInfo>> entry : shrinkableMap.entrySet())
{
- if (!((Collection) entry.getValue()).isEmpty())
+ if (!entry.getValue().isEmpty())
{
- newMap.put((BundleContext) entry.getKey(),
- new ArrayList<ListenerInfo>((Collection) entry.getValue()));
+ newMap.put(entry.getKey(), mutableMap.get(entry.getKey()));
}
}
+
+ // Put the system bundle listeners back, because they really need to be called
+ // regardless whether they were removed by the hooks or not.
+ if (systemBundleListeners != null)
+ newMap.put(felix.getBundleContext(), systemBundleListeners);
+
listeners = newMap;
}
@@ -652,16 +679,23 @@ public class EventDispatcher
Set<ServiceReference<T>> hooks = m_registry.getHooks(hookClass);
if ((hooks != null) && !hooks.isEmpty())
{
+ boolean systemBundleListener = false;
+ BundleContext systemBundleContext = felix.getBundleContext();
+
whitelist = new HashSet<BundleContext>();
for (Entry<BundleContext, List<ListenerInfo>> entry : listeners1.entrySet())
{
whitelist.add(entry.getKey());
+ if (entry.getKey() == systemBundleContext)
+ systemBundleListener = true;
}
if (listeners2 != null)
{
for (Entry<BundleContext, List<ListenerInfo>> entry : listeners2.entrySet())
{
whitelist.add(entry.getKey());
+ if (entry.getKey() == systemBundleContext)
+ systemBundleListener = true;
}
}
@@ -675,7 +709,7 @@ public class EventDispatcher
T eh = null;
try
{
- eh = m_registry.getService(felix, sr);
+ eh = m_registry.getService(felix, sr, false);
}
catch (Exception ex)
{
@@ -705,11 +739,21 @@ public class EventDispatcher
}
finally
{
- m_registry.ungetService(felix, sr);
+ m_registry.ungetService(felix, sr, null);
}
}
}
}
+
+ if (systemBundleListener && !whitelist.contains(systemBundleContext))
+ {
+ // The system bundle cannot be removed from the listeners, so if it was
+ // removed, add it back in. Note that this cannot be prevented by the shrinkable
+ // since the effect of removing the system bundle from the listeners must be
+ // visible between the event hooks.
+ whitelist.add(systemBundleContext);
+ }
+
// If the whitelist hasn't changed, then null it to avoid having
// to do whitelist lookups during event delivery.
if (originalSize == whitelist.size())
diff --git a/src/main/java/org/apache/felix/framework/util/FelixConstants.java b/src/main/java/org/apache/felix/framework/util/FelixConstants.java
index 511657c..0f2b4a4 100644
--- a/src/main/java/org/apache/felix/framework/util/FelixConstants.java
+++ b/src/main/java/org/apache/felix/framework/util/FelixConstants.java
@@ -22,7 +22,7 @@ public interface FelixConstants extends org.osgi.framework.Constants
{
String SYSTEM_BUNDLE_SYMBOLICNAME = "org.apache.felix.framework";
// Framework constants and values.
- String FRAMEWORK_VERSION_VALUE = "1.5";
+ String FRAMEWORK_VERSION_VALUE = "1.7";
String FRAMEWORK_VENDOR_VALUE = "Apache Software Foundation";
// Framework constants and values.
@@ -51,6 +51,8 @@ public interface FelixConstants extends org.osgi.framework.Constants
String IMPLICIT_BOOT_DELEGATION_PROP = "felix.bootdelegation.implicit";
String BOOT_CLASSLOADERS_PROP = "felix.bootdelegation.classloaders";
String USE_LOCALURLS_PROP = "felix.jarurls";
+ String NATIVE_OS_NAME_ALIAS_PREFIX = "felix.native.osname.alias";
+ String NATIVE_PROC_NAME_ALIAS_PREFIX = "felix.native.processor.alias";
// Missing OSGi constant for resolution directive.
String RESOLUTION_DYNAMIC = "dynamic";
@@ -65,4 +67,5 @@ public interface FelixConstants extends org.osgi.framework.Constants
String FAKE_URL_PROTOCOL_VALUE = "location:";
String FELIX_EXTENSION_ACTIVATOR = "Felix-Activator";
String SECURITY_DEFAULT_POLICY = "felix.security.defaultpolicy";
+ String FELIX_EXTENSIONS_DISABLE = "felix.extensions.disable";
}
diff --git a/src/main/java/org/apache/felix/framework/util/ImmutableList.java b/src/main/java/org/apache/felix/framework/util/ImmutableList.java
index f0a1a9c..ba1cc94 100644
--- a/src/main/java/org/apache/felix/framework/util/ImmutableList.java
+++ b/src/main/java/org/apache/felix/framework/util/ImmutableList.java
@@ -76,6 +76,18 @@ public class ImmutableList<E> extends AbstractList<E> implements RandomAccess
{
throw new UnsupportedOperationException();
}
+
+ @Override
+ public void clear()
+ {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean retainAll(java.util.Collection<?> c)
+ {
+ throw new UnsupportedOperationException();
+ }
@Override
public Iterator<E> iterator()
diff --git a/src/main/java/org/apache/felix/framework/util/SecureAction.java b/src/main/java/org/apache/felix/framework/util/SecureAction.java
index a6a2584..f7cf9b3 100644
--- a/src/main/java/org/apache/felix/framework/util/SecureAction.java
+++ b/src/main/java/org/apache/felix/framework/util/SecureAction.java
@@ -26,6 +26,7 @@ import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
+import java.util.jar.JarFile;
import java.util.zip.ZipFile;
import org.osgi.framework.Bundle;
@@ -573,6 +574,32 @@ public class SecureAction
}
}
+ public void deleteFileOnExit(File file)
+ throws IOException
+ {
+ if (System.getSecurityManager() != null)
+ {
+ try
+ {
+ Actions actions = (Actions) m_actions.get();
+ actions.set(Actions.DELETE_FILEONEXIT_ACTION, file);
+ AccessController.doPrivileged(actions, m_acc);
+ }
+ catch (PrivilegedActionException ex)
+ {
+ if (ex.getException() instanceof IOException)
+ {
+ throw (IOException) ex.getException();
+ }
+ throw (RuntimeException) ex.getException();
+ }
+ }
+ else
+ {
+ file.deleteOnExit();
+ }
+ }
+
public URLConnection openURLConnection(URL url) throws IOException
{
if (System.getSecurityManager() != null)
@@ -624,6 +651,31 @@ public class SecureAction
}
}
+ public JarFile openJarFile(File file) throws IOException
+ {
+ if (System.getSecurityManager() != null)
+ {
+ try
+ {
+ Actions actions = (Actions) m_actions.get();
+ actions.set(Actions.OPEN_JARFILE_ACTION, file);
+ return (JarFile) AccessController.doPrivileged(actions, m_acc);
+ }
+ catch (PrivilegedActionException ex)
+ {
+ if (ex.getException() instanceof IOException)
+ {
+ throw (IOException) ex.getException();
+ }
+ throw (RuntimeException) ex.getException();
+ }
+ }
+ else
+ {
+ return new JarFile(file);
+ }
+ }
+
public void startActivator(BundleActivator activator, BundleContext context)
throws Exception
{
@@ -1397,6 +1449,30 @@ public class SecureAction
}
}
+ public void invokeWovenClassListener(
+ org.osgi.framework.hooks.weaving.WovenClassListener wcl,
+ org.osgi.framework.hooks.weaving.WovenClass wc)
+ throws Exception
+ {
+ if (System.getSecurityManager() != null)
+ {
+ Actions actions = (Actions) m_actions.get();
+ actions.set(Actions.INVOKE_WOVEN_CLASS_LISTENER, wcl, wc);
+ try
+ {
+ AccessController.doPrivileged(actions, m_acc);
+ }
+ catch (PrivilegedActionException e)
+ {
+ throw e.getException();
+ }
+ }
+ else
+ {
+ wcl.modified(wc);
+ }
+ }
+
private static class Actions implements PrivilegedExceptionAction
{
public static final int INITIALIZE_CONTEXT_ACTION = 0;
@@ -1453,6 +1529,9 @@ public class SecureAction
public static final int INVOKE_RESOLVER_HOOK_MATCHES = 51;
public static final int INVOKE_RESOLVER_HOOK_END = 52;
public static final int INVOKE_BUNDLE_COLLISION_HOOK = 53;
+ public static final int OPEN_JARFILE_ACTION = 54;
+ public static final int DELETE_FILEONEXIT_ACTION = 55;
+ public static final int INVOKE_WOVEN_CLASS_LISTENER = 56;
private int m_action = -1;
private Object m_arg1 = null;
@@ -1702,6 +1781,15 @@ public class SecureAction
((org.osgi.framework.hooks.bundle.CollisionHook) arg1).filterCollisions((Integer) arg2,
(Bundle) arg3, (Collection<Bundle>) arg4);
return null;
+ case OPEN_JARFILE_ACTION:
+ return new JarFile((File) arg1);
+ case DELETE_FILEONEXIT_ACTION:
+ ((File) arg1).deleteOnExit();
+ return null;
+ case INVOKE_WOVEN_CLASS_LISTENER:
+ ((org.osgi.framework.hooks.weaving.WovenClassListener) arg1).modified(
+ (org.osgi.framework.hooks.weaving.WovenClass) arg2);
+ return null;
}
return null;
diff --git a/src/main/java/org/apache/felix/framework/util/Util.java b/src/main/java/org/apache/felix/framework/util/Util.java
index ac9500b..8128aa1 100644
--- a/src/main/java/org/apache/felix/framework/util/Util.java
+++ b/src/main/java/org/apache/felix/framework/util/Util.java
@@ -20,7 +20,6 @@ package org.apache.felix.framework.util;
import java.io.*;
import java.net.URL;
-
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
@@ -29,11 +28,12 @@ import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
+import java.util.Set;
+
import org.apache.felix.framework.Logger;
import org.apache.felix.framework.capabilityset.CapabilitySet;
import org.apache.felix.framework.wiring.BundleCapabilityImpl;
import org.apache.felix.framework.wiring.BundleRequirementImpl;
-
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
@@ -50,10 +50,9 @@ public class Util
**/
private static final String DEFAULT_PROPERTIES_FILE = "default.properties";
- public static String getDefaultProperty(Logger logger, String name)
+ public static Properties loadDefaultProperties(Logger logger)
{
- String value = null;
-
+ Properties defaultProperties = new Properties();
URL propURL = Util.class.getClassLoader().getResource(DEFAULT_PROPERTIES_FILE);
if (propURL != null)
{
@@ -62,14 +61,8 @@ public class Util
{
// Load properties from URL.
is = propURL.openConnection().getInputStream();
- Properties props = new Properties();
- props.load(is);
+ defaultProperties.load(is);
is.close();
- // Perform variable substitution for property.
- value = props.getProperty(name);
- value = (value != null)
- ? Util.substVars(value, name, null, props)
- : null;
}
catch (Exception ex)
{
@@ -87,9 +80,51 @@ public class Util
Logger.LOG_ERROR, "Unable to load any configuration properties.", ex);
}
}
+ return defaultProperties;
+ }
+
+ public static String getDefaultProperty(Logger logger, String name)
+ {
+ Properties props = loadDefaultProperties(logger);
+ // Perform variable substitution for property.
+ return getPropertyWithSubs(props, name);
+ }
+
+ public static String getPropertyWithSubs(Properties props, String name)
+ {
+ // Perform variable substitution for property.
+ String value = props.getProperty(name);
+ value = (value != null)
+ ? Util.substVars(value, name, null, props): null;
return value;
}
+ public static Map<String, String> getDefaultPropertiesWithPrefix(Logger logger, String prefix)
+ {
+ Properties props = loadDefaultProperties(logger);
+ return getDefaultPropertiesWithPrefix(props, prefix);
+ }
+
+ public static Map<String, String> getDefaultPropertiesWithPrefix(Properties props, String prefix)
+ {
+ Map<String, String> result = new HashMap<String, String>();
+
+ Set<String> propertySet = props.stringPropertyNames();
+
+ for(String currentPropertyKey: propertySet)
+ {
+ if(currentPropertyKey.startsWith(prefix))
+ {
+ String value = props.getProperty(currentPropertyKey);
+ // Perform variable substitution for property.
+ value = (value != null)
+ ? Util.substVars(value, currentPropertyKey, null, props): null;
+ result.put(currentPropertyKey, value);
+ }
+ }
+ return result;
+ }
+
/**
* Converts a revision identifier to a bundle identifier. Revision IDs
* are typically <tt><bundle-id>.<revision></tt>; this
diff --git a/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java b/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
index 672fd2f..47e80a2 100644
--- a/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
+++ b/src/main/java/org/apache/felix/framework/util/manifestparser/ManifestParser.java
@@ -19,6 +19,7 @@
package org.apache.felix.framework.util.manifestparser;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -41,6 +42,7 @@ import org.osgi.framework.Version;
import org.osgi.framework.namespace.BundleNamespace;
import org.osgi.framework.namespace.ExecutionEnvironmentNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.namespace.NativeNamespace;
import org.osgi.framework.wiring.BundleCapability;
import org.osgi.framework.wiring.BundleRequirement;
import org.osgi.framework.wiring.BundleRevision;
@@ -60,7 +62,7 @@ public class ManifestParser
private volatile Version m_bundleVersion;
private volatile List<BundleCapability> m_capabilities;
private volatile List<BundleRequirement> m_requirements;
- private volatile List<R4LibraryClause> m_libraryClauses;
+ private volatile List<NativeLibraryClause> m_libraryClauses;
private volatile boolean m_libraryHeadersOptional = false;
public ManifestParser(Logger logger, Map configMap, BundleRevision owner, Map headerMap)
@@ -243,24 +245,6 @@ public class ManifestParser
exportCaps = calculateImplicitUses(exportCaps, allImportClauses);
}
- // Combine all capabilities.
- m_capabilities = new ArrayList(
- capList.size() + exportCaps.size() + provideCaps.size());
- m_capabilities.addAll(capList);
- m_capabilities.addAll(exportCaps);
- m_capabilities.addAll(provideCaps);
-
- // Combine all requirements.
- m_requirements = new ArrayList(
- hostReqs.size() + importReqs.size() + rbReqs.size()
- + requireReqs.size() + dynamicReqs.size() + breeReqs.size());
- m_requirements.addAll(hostReqs);
- m_requirements.addAll(importReqs);
- m_requirements.addAll(rbReqs);
- m_requirements.addAll(requireReqs);
- m_requirements.addAll(dynamicReqs);
- m_requirements.addAll(breeReqs);
-
//
// Parse Bundle-NativeCode.
//
@@ -279,6 +263,27 @@ public class ManifestParser
m_libraryHeadersOptional = true;
m_libraryClauses.remove(m_libraryClauses.size() - 1);
}
+
+ List<BundleRequirement> nativeCodeReqs = convertNativeCode(owner, m_libraryClauses, m_libraryHeadersOptional);
+
+ // Combine all requirements.
+ m_requirements = new ArrayList(
+ hostReqs.size() + importReqs.size() + rbReqs.size()
+ + requireReqs.size() + dynamicReqs.size() + breeReqs.size());
+ m_requirements.addAll(hostReqs);
+ m_requirements.addAll(importReqs);
+ m_requirements.addAll(rbReqs);
+ m_requirements.addAll(requireReqs);
+ m_requirements.addAll(dynamicReqs);
+ m_requirements.addAll(breeReqs);
+ m_requirements.addAll(nativeCodeReqs);
+
+ // Combine all capabilities.
+ m_capabilities = new ArrayList(
+ capList.size() + exportCaps.size() + provideCaps.size());
+ m_capabilities.addAll(capList);
+ m_capabilities.addAll(exportCaps);
+ m_capabilities.addAll(provideCaps);
//
// Parse activation policy.
@@ -601,6 +606,123 @@ public class ManifestParser
return reqList;
}
+
+ static List<BundleRequirement> convertNativeCode(BundleRevision owner, List<NativeLibraryClause> nativeLibraryClauses, boolean hasOptionalLibraryDirective)
+ {
+ List<BundleRequirement> result = new ArrayList<BundleRequirement>();
+
+ List<SimpleFilter> nativeFilterClauseList = new ArrayList<SimpleFilter>();
+
+ if(nativeLibraryClauses != null)
+ {
+ for(NativeLibraryClause clause: nativeLibraryClauses)
+ {
+ String[] osNameArray = clause.getOSNames();
+ String[] osVersionArray = clause.getOSVersions();
+ String[] processorArray = clause.getProcessors();
+ String[] languageArray = clause.getLanguages();
+
+ String currentSelectionFilter = clause.getSelectionFilter();
+
+ List<SimpleFilter> nativeFilterList = new ArrayList<SimpleFilter>();
+ if(osNameArray != null && osNameArray.length > 0)
+ {
+ nativeFilterList.add(buildFilterFromArray(NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE, osNameArray, SimpleFilter.APPROX));
+ }
+
+ if(osVersionArray != null && osVersionArray.length > 0)
+ {
+ nativeFilterList.add(buildFilterFromArray(NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE, osVersionArray, SimpleFilter.EQ));
+ }
+
+ if(processorArray != null && processorArray.length > 0)
+ {
+ nativeFilterList.add(buildFilterFromArray(NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE, processorArray, SimpleFilter.APPROX));
+ }
+
+ if(languageArray != null && languageArray.length > 0)
+ {
+ nativeFilterList.add(buildFilterFromArray(NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE, languageArray, SimpleFilter.APPROX));
+ }
+
+ if(currentSelectionFilter != null)
+ {
+ nativeFilterList.add(SimpleFilter.parse(currentSelectionFilter));
+ }
+
+ if(!nativeFilterList.isEmpty())
+ {
+ SimpleFilter nativeClauseFilter = new SimpleFilter(null, nativeFilterList, SimpleFilter.AND);
+ nativeFilterClauseList.add(nativeClauseFilter);
+ }
+ }
+
+ Map<String, String> requirementDirectives = new HashMap<String, String>();
+
+ SimpleFilter consolidatedNativeFilter = null;
+
+ if(hasOptionalLibraryDirective)
+ {
+ requirementDirectives.put(NativeNamespace.REQUIREMENT_RESOLUTION_DIRECTIVE, NativeNamespace.RESOLUTION_OPTIONAL);
+ }
+
+ if(nativeFilterClauseList.size() > 1)
+ {
+ consolidatedNativeFilter = new SimpleFilter(null, nativeFilterClauseList, SimpleFilter.OR);
+
+ requirementDirectives.put(NativeNamespace.REQUIREMENT_FILTER_DIRECTIVE, consolidatedNativeFilter.toString());
+ }
+ else if(nativeFilterClauseList.size() == 1)
+ {
+ consolidatedNativeFilter = nativeFilterClauseList.get(0);
+
+ requirementDirectives.put(NativeNamespace.REQUIREMENT_FILTER_DIRECTIVE, consolidatedNativeFilter.toString());
+ }
+
+ if(requirementDirectives.size() > 0)
+ {
+ result.add(new BundleRequirementImpl(owner, NativeNamespace.NATIVE_NAMESPACE, requirementDirectives,
+ Collections.<String, Object>emptyMap(),
+ consolidatedNativeFilter));
+ }
+
+ }
+
+ return result;
+ }
+
+ private static SimpleFilter buildFilterFromArray(String attributeName, String[] stringArray, int operation)
+ {
+ SimpleFilter result = null;
+ List<SimpleFilter> filterSet = new ArrayList<SimpleFilter>();
+
+ if(stringArray != null)
+ {
+ for(String currentValue : stringArray)
+ {
+ filterSet.add(new SimpleFilter(attributeName, currentValue.toLowerCase(), operation));
+ }
+
+ if(filterSet.size() == 1)
+ {
+ result = filterSet.get(0);
+ }
+ else
+ {
+ result = new SimpleFilter(null, filterSet, SimpleFilter.OR);
+ }
+ }
+
+ return result;
+ }
+
+ private static void addStringArrayToSet(String[] array, Set<String> set)
+ {
+ if(array != null)
+ {
+ set.addAll(Arrays.asList(array));
+ }
+ }
private static List<ParsedHeaderClause> normalizeProvideCapabilityClauses(
Logger logger, List<ParsedHeaderClause> clauses, String mv)
@@ -722,6 +844,14 @@ public class ManifestParser
+ path
+ "' namespace.");
}
+
+ if(path.startsWith(NativeNamespace.NATIVE_NAMESPACE) && (owner == null ||
+ !FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME.equals(owner.getSymbolicName())))
+ {
+ throw new BundleException("Only System Bundle can use Provide-Capability for '"
+ + path
+ + "' namespace.", BundleException.MANIFEST_ERROR);
+ }
// Create package capability and add to capability list.
capList.add(
@@ -941,7 +1071,7 @@ public class ManifestParser
return m_requirements;
}
- public List<R4LibraryClause> getLibraryClauses()
+ public List<NativeLibraryClause> getLibraryClauses()
{
return m_libraryClauses;
}
@@ -963,25 +1093,25 @@ public class ManifestParser
* <li><tt>null</tt> - if the are no native libraries for this module;
* this may also indicate the native libraries are optional and
* did not match the current platform.</li>
- * <li>Zero-length <tt>R4Library</tt> array - if no matching native library
+ * <li>Zero-length <tt>NativeLibrary</tt> array - if no matching native library
* clause was found; this bundle should not resolve.</li>
- * <li>Nonzero-length <tt>R4Library</tt> array - the native libraries
+ * <li>Nonzero-length <tt>NativeLibrary</tt> array - the native libraries
* associated with the matching native library clause.</li>
* </ul>
*
* @return <tt>null</tt> if there are no native libraries, a zero-length
* array if no libraries matched, or an array of selected libraries.
**/
- public List<R4Library> getLibraries()
+ public List<NativeLibrary> getLibraries()
{
- ArrayList<R4Library> libs = null;
+ ArrayList<NativeLibrary> libs = null;
try
{
- R4LibraryClause clause = getSelectedLibraryClause();
+ NativeLibraryClause clause = getSelectedLibraryClause();
if (clause != null)
{
String[] entries = clause.getLibraryEntries();
- libs = new ArrayList<R4Library>(entries.length);
+ libs = new ArrayList<NativeLibrary>(entries.length);
int current = 0;
for (int i = 0; i < entries.length; i++)
{
@@ -993,7 +1123,7 @@ public class ManifestParser
}
if (!found)
{
- libs.add(new R4Library(
+ libs.add(new NativeLibrary(
clause.getLibraryEntries()[i],
clause.getOSNames(), clause.getProcessors(), clause.getOSVersions(),
clause.getLanguages(), clause.getSelectionFilter()));
@@ -1004,7 +1134,7 @@ public class ManifestParser
}
catch (Exception ex)
{
- libs = new ArrayList<R4Library>(0);
+ libs = new ArrayList<NativeLibrary>(0);
}
return libs;
}
@@ -1019,14 +1149,14 @@ public class ManifestParser
return path;
}
- private R4LibraryClause getSelectedLibraryClause() throws BundleException
+ private NativeLibraryClause getSelectedLibraryClause() throws BundleException
{
if ((m_libraryClauses != null) && (m_libraryClauses.size() > 0))
{
List clauseList = new ArrayList();
// Search for matching native clauses.
- for (R4LibraryClause libraryClause : m_libraryClauses)
+ for (NativeLibraryClause libraryClause : m_libraryClauses)
{
if (libraryClause.match(m_configMap))
{
@@ -1056,13 +1186,13 @@ public class ManifestParser
{
selected = firstSortedClause(clauseList);
}
- return ((R4LibraryClause) clauseList.get(selected));
+ return ((NativeLibraryClause) clauseList.get(selected));
}
return null;
}
- private int firstSortedClause(List<R4LibraryClause> clauseList)
+ private int firstSortedClause(List<NativeLibraryClause> clauseList)
{
ArrayList indexList = new ArrayList();
ArrayList selection = new ArrayList();
@@ -1079,7 +1209,7 @@ public class ManifestParser
for (int i = 0; i < indexList.size(); i++)
{
int index = Integer.parseInt(indexList.get(i).toString());
- String[] osversions = ((R4LibraryClause) clauseList.get(index)).getOSVersions();
+ String[] osversions = ((NativeLibraryClause) clauseList.get(index)).getOSVersions();
if (osversions != null)
{
selection.add("" + indexList.get(i));
@@ -1107,7 +1237,7 @@ public class ManifestParser
for (int i = 0; i < indexList.size(); i++)
{
int index = Integer.parseInt(indexList.get(i).toString());
- String[] osversions = ((R4LibraryClause) clauseList.get(index)).getOSVersions();
+ String[] osversions = ((NativeLibraryClause) clauseList.get(index)).getOSVersions();
for (int k = 0; k < osversions.length; k++)
{
VersionRange range = VersionRange.parse(osversions[k]);
@@ -1143,7 +1273,7 @@ public class ManifestParser
for (int i = 0; i < indexList.size(); i++)
{
int index = Integer.parseInt(indexList.get(i).toString());
- if (((R4LibraryClause) clauseList.get(index)).getLanguages() != null)
+ if (((NativeLibraryClause) clauseList.get(index)).getLanguages() != null)
{
selection.add("" + indexList.get(i));
}
@@ -2034,20 +2164,20 @@ public class ManifestParser
* @return an array of <tt>LibraryInfo</tt> objects for the
* passed in strings.
**/
- private static List<R4LibraryClause> parseLibraryStrings(
+ private static List<NativeLibraryClause> parseLibraryStrings(
Logger logger, List<String> libStrs)
throws IllegalArgumentException
{
if (libStrs == null)
{
- return new ArrayList<R4LibraryClause>(0);
+ return new ArrayList<NativeLibraryClause>(0);
}
- List<R4LibraryClause> libList = new ArrayList(libStrs.size());
+ List<NativeLibraryClause> libList = new ArrayList(libStrs.size());
for (int i = 0; i < libStrs.size(); i++)
{
- R4LibraryClause clause = R4LibraryClause.parse(logger, libStrs.get(i));
+ NativeLibraryClause clause = NativeLibraryClause.parse(logger, libStrs.get(i));
libList.add(clause);
}
diff --git a/src/main/java/org/apache/felix/framework/util/manifestparser/R4Library.java b/src/main/java/org/apache/felix/framework/util/manifestparser/NativeLibrary.java
similarity index 99%
rename from src/main/java/org/apache/felix/framework/util/manifestparser/R4Library.java
rename to src/main/java/org/apache/felix/framework/util/manifestparser/NativeLibrary.java
index e82c2a1..fbb3a1e 100644
--- a/src/main/java/org/apache/felix/framework/util/manifestparser/R4Library.java
+++ b/src/main/java/org/apache/felix/framework/util/manifestparser/NativeLibrary.java
@@ -23,7 +23,7 @@ import java.util.List;
import java.util.Map;
import org.osgi.framework.Constants;
-public class R4Library
+public class NativeLibrary
{
private String m_libraryFile;
private String[] m_osnames;
@@ -32,7 +32,7 @@ public class R4Library
private String[] m_languages;
private String m_selectionFilter;
- public R4Library(
+ public NativeLibrary(
String libraryFile, String[] osnames, String[] processors, String[] osversions,
String[] languages, String selectionFilter) throws Exception
{
diff --git a/src/main/java/org/apache/felix/framework/util/manifestparser/NativeLibraryClause.java b/src/main/java/org/apache/felix/framework/util/manifestparser/NativeLibraryClause.java
new file mode 100644
index 0000000..92b30dd
--- /dev/null
+++ b/src/main/java/org/apache/felix/framework/util/manifestparser/NativeLibraryClause.java
@@ -0,0 +1,758 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework.util.manifestparser;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.felix.framework.Logger;
+import org.apache.felix.framework.util.FelixConstants;
+import org.apache.felix.framework.util.VersionRange;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.Version;
+
+public class NativeLibraryClause
+{
+ private static final String OS_AIX = "aix";
+ private static final String OS_DIGITALUNIX = "digitalunix";
+ private static final String OS_EPOC = "epoc32";
+ private static final String OS_HPUX = "hpux";
+ private static final String OS_IRIX = "irix";
+ private static final String OS_LINUX = "linux";
+ private static final String OS_MACOS = "macos";
+ private static final String OS_MACOSX = "macosx";
+ private static final String OS_NETBSD = "netbsd";
+ private static final String OS_NETWARE = "netware";
+ private static final String OS_OPENBSD = "openbsd";
+ private static final String OS_OS2 = "os2";
+ private static final String OS_QNX = "qnx";
+ private static final String OS_SOLARIS = "solaris";
+ private static final String OS_SUNOS = "sunos";
+ private static final String OS_VXWORKS = "vxworks";
+ private static final String OS_WINDOWS_2000 = "windows2000";
+ private static final String OS_WINDOWS_2003 = "windows2003";
+ private static final String OS_WINDOWS_7 = "windows7";
+ private static final String OS_WINDOWS_8 = "windows8";
+ private static final String OS_WINDOWS_9 = "windows9";
+ private static final String OS_WINDOWS_95 = "windows95";
+ private static final String OS_WINDOWS_98 = "windows98";
+ private static final String OS_WINDOWS_CE = "windowsce";
+ private static final String OS_WINDOWS_NT = "windowsnt";
+ private static final String OS_WINDOWS_SERVER_2008 = "windowsserver2008";
+ private static final String OS_WINDOWS_SERVER_2012 = "windowsserver2012";
+ private static final String OS_WINDOWS_VISTA = "windowsvista";
+ private static final String OS_WINDOWS_XP = "windowsxp";
+ private static final String OS_WIN_32 = "win32";
+
+ private static final String PROC_X86_64 = "x86-64";
+ private static final String PROC_X86 = "x86";
+ private static final String PROC_68K = "68k";
+ private static final String PROC_ARM_LE = "arm_le";
+ private static final String PROC_ARM_BE = "arm_be";
+ private static final String PROC_ARM = "arm";
+ private static final String PROC_ALPHA = "alpha";
+ private static final String PROC_IGNITE = "ignite";
+ private static final String PROC_MIPS = "mips";
+ private static final String PROC_PARISC = "parisc";
+ private static final String PROC_POWER_PC = "powerpc";
+ private static final String PROC_SPARC = "sparc";
+
+
+ private static final Map<String, List<String>> OS_ALIASES = new HashMap<String, List<String>>();
+
+ private static final Map<String, List<String>> PROC_ALIASES = new HashMap<String, List<String>>();
+
+ private final String[] m_libraryEntries;
+ private final String[] m_osnames;
+ private final String[] m_processors;
+ private final String[] m_osversions;
+ private final String[] m_languages;
+ private final String m_selectionFilter;
+
+ public NativeLibraryClause(String[] libraryEntries, String[] osnames,
+ String[] processors, String[] osversions, String[] languages,
+ String selectionFilter)
+ {
+ m_libraryEntries = libraryEntries;
+ m_osnames = osnames;
+ m_processors = processors;
+ m_osversions = osversions;
+ m_languages = languages;
+ m_selectionFilter = selectionFilter;
+ }
+
+ public NativeLibraryClause(NativeLibraryClause library)
+ {
+ this(library.m_libraryEntries, library.m_osnames, library.m_osversions,
+ library.m_processors, library.m_languages,
+ library.m_selectionFilter);
+ }
+
+ /**
+ * Initialize the processor and os name aliases from Felix Config.
+ *
+ * @param config
+ */
+ public static synchronized void initializeNativeAliases(Map configMap)
+ {
+ Map<String, String> osNameKeyMap = getAllKeysWithPrefix(FelixConstants.NATIVE_OS_NAME_ALIAS_PREFIX, configMap);
+
+ Map<String, String> processorKeyMap = getAllKeysWithPrefix(FelixConstants.NATIVE_PROC_NAME_ALIAS_PREFIX, configMap);
+
+ parseNativeAliases(osNameKeyMap, OS_ALIASES);
+ parseNativeAliases(processorKeyMap, PROC_ALIASES);
+ }
+
+ private static void parseNativeAliases(Map<String, String> aliasStringMap, Map<String, List<String>> aliasMap)
+ {
+ for(Map.Entry<String, String> aliasEntryString: aliasStringMap.entrySet())
+ {
+ String currentAliasKey = aliasEntryString.getKey();
+
+ String currentNormalizedName = currentAliasKey.substring(currentAliasKey.lastIndexOf(".")+1);
+
+ String currentAliasesString = aliasEntryString.getValue();
+
+ if(currentAliasesString != null)
+ {
+ String[] aliases = currentAliasesString.split(",");
+ List<String> fullAliasList = new ArrayList<String>();
+ //normalized name is always first.
+ fullAliasList.add(currentNormalizedName);
+ fullAliasList.addAll(Arrays.asList(aliases));
+ aliasMap.put(currentNormalizedName, fullAliasList);
+ for(String currentAlias: aliases)
+ {
+ List<String> aliasList = aliasMap.get(currentAlias);
+ if(aliasList == null)
+ {
+ aliasMap.put(currentAlias, fullAliasList);
+ }
+ else
+ {
+ for(String newAliases: aliases)
+ {
+ if(!aliasList.contains(newAliases))
+ {
+ aliasList.add(newAliases);
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ List<String> aliasList = aliasMap.get(currentNormalizedName);
+ if(aliasList == null)
+ {
+ aliasMap.put(currentNormalizedName, new ArrayList<String>(Collections.singletonList(currentNormalizedName)));
+ }
+ else
+ {
+ //if the alias is also a normalized name make sure it's first
+ aliasList.add(0, currentNormalizedName);
+ }
+ }
+ }
+ }
+
+ private static Map<String, String> getAllKeysWithPrefix(String prefix, Map<String, String> configMap)
+ {
+ Map<String, String> keysWithPrefix = new HashMap<String, String>();
+ for(Map.Entry<String, String> currentEntry: configMap.entrySet())
+ {
+ if(currentEntry.getKey().startsWith(prefix))
+ {
+ keysWithPrefix.put(currentEntry.getKey(), currentEntry.getValue());
+ }
+ }
+ return keysWithPrefix;
+ }
+
+ public String[] getLibraryEntries()
+ {
+ return m_libraryEntries;
+ }
+
+ public String[] getOSNames()
+ {
+ return m_osnames;
+ }
+
+ public String[] getProcessors()
+ {
+ return m_processors;
+ }
+
+ public String[] getOSVersions()
+ {
+ return m_osversions;
+ }
+
+ public String[] getLanguages()
+ {
+ return m_languages;
+ }
+
+ public String getSelectionFilter()
+ {
+ return m_selectionFilter;
+ }
+
+ public boolean match(Map configMap) throws BundleException
+ {
+ String osName = (String) configMap.get(FelixConstants.FRAMEWORK_OS_NAME);
+ String processorName = (String) configMap.get(FelixConstants.FRAMEWORK_PROCESSOR);
+ String osVersion = (String) configMap.get(FelixConstants.FRAMEWORK_OS_VERSION);
+ String language = (String) configMap.get(FelixConstants.FRAMEWORK_LANGUAGE);
+
+ // Check library's osname.
+ if (!checkOSNames(osName, getOSNames()))
+ {
+ return false;
+ }
+
+ // Check library's processor.
+ if (!checkProcessors(processorName, getProcessors()))
+ {
+ return false;
+ }
+
+ // Check library's osversion if specified.
+ if ((getOSVersions() != null) &&
+ (getOSVersions().length > 0) &&
+ !checkOSVersions(osVersion, getOSVersions()))
+ {
+ return false;
+ }
+
+ // Check library's language if specified.
+ if ((getLanguages() != null) &&
+ (getLanguages().length > 0) &&
+ !checkLanguages(language, getLanguages()))
+ {
+ return false;
+ }
+
+ // Check library's selection-filter if specified.
+ if ((getSelectionFilter() != null) &&
+ (getSelectionFilter().length() >= 0) &&
+ !checkSelectionFilter(configMap, getSelectionFilter()))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ private boolean checkOSNames(String osName, String[] osnames)
+ {
+ List<String> capabilityOsNames = getOsNameWithAliases(osName);
+ if (capabilityOsNames != null && osnames != null)
+ {
+ for (String curOsName : osnames)
+ {
+ if (capabilityOsNames.contains(curOsName))
+ {
+ return true;
+ }
+
+ }
+ }
+ return false;
+ }
+
+ private boolean checkProcessors(String processorName, String[] processors)
+ {
+ List<String> capabilitiesProcessors = getProcessorWithAliases(processorName);
+ if (capabilitiesProcessors != null && processors != null)
+ {
+ for (String currentProcessor : processors)
+ {
+ if (capabilitiesProcessors.contains(currentProcessor))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private boolean checkOSVersions(String osVersion, String[] osversions)
+ throws BundleException
+ {
+ Version currentOSVersion = Version.parseVersion(formatOSVersion(osVersion));
+ for (int i = 0; (osversions != null) && (i < osversions.length); i++)
+ {
+ try
+ {
+ VersionRange range = VersionRange.parse(osversions[i]);
+ if (range.isInRange(currentOSVersion))
+ {
+ return true;
+ }
+ }
+ catch (Exception ex)
+ {
+ throw new BundleException(
+ "Error evaluating osversion: " + osversions[i], ex);
+ }
+ }
+ return false;
+ }
+
+ private boolean checkLanguages(String currentLanguage, String[] languages)
+ {
+ for (int i = 0; (languages != null) && (i < languages.length); i++)
+ {
+ if (languages[i].equals(currentLanguage))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean checkSelectionFilter(Map configMap, String expr)
+ throws BundleException
+ {
+ // Get all framework properties
+ Dictionary dict = new Hashtable();
+ for (Iterator i = configMap.keySet().iterator(); i.hasNext(); )
+ {
+ Object key = i.next();
+ dict.put(key, configMap.get(key));
+ }
+ // Compute expression
+ try
+ {
+ Filter filter = FrameworkUtil.createFilter(expr);
+ return filter.match(dict);
+ }
+ catch (Exception ex)
+ {
+ throw new BundleException(
+ "Error evaluating filter expression: " + expr, ex);
+ }
+ }
+
+ public static NativeLibraryClause parse(Logger logger, String s)
+ {
+ try
+ {
+ if ((s == null) || (s.length() == 0))
+ {
+ return null;
+ }
+
+ s = s.trim();
+ if (s.equals(FelixConstants.BUNDLE_NATIVECODE_OPTIONAL))
+ {
+ return new NativeLibraryClause(null, null, null, null, null, null);
+ }
+
+ // The tokens are separated by semicolons and may include
+ // any number of libraries along with one set of associated
+ // properties.
+ StringTokenizer st = new StringTokenizer(s, ";");
+ String[] libEntries = new String[st.countTokens()];
+ List osNameList = new ArrayList();
+ List osVersionList = new ArrayList();
+ List processorList = new ArrayList();
+ List languageList = new ArrayList();
+ String selectionFilter = null;
+ int libCount = 0;
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken().trim();
+ if (token.indexOf('=') < 0)
+ {
+ // Remove the slash, if necessary.
+ libEntries[libCount] = (token.charAt(0) == '/')
+ ? token.substring(1)
+ : token;
+ libCount++;
+ }
+ else
+ {
+ // Check for valid native library properties; defined as
+ // a property name, an equal sign, and a value.
+ // NOTE: StringTokenizer can not be used here because
+ // a value can contain one or more "=" too, e.g.,
+ // selection-filter="(org.osgi.framework.windowing.system=gtk)"
+ String property = null;
+ String value = null;
+ if (!(token.indexOf("=") > 1))
+ {
+ throw new IllegalArgumentException(
+ "Bundle manifest native library entry malformed: " + token);
+ }
+ else
+ {
+ property = (token.substring(0, token.indexOf("=")))
+ .trim().toLowerCase();
+ value = (token.substring(token.indexOf("=") + 1, token
+ .length())).trim();
+ }
+
+ // Values may be quoted, so remove quotes if present.
+ if (value.charAt(0) == '"')
+ {
+ // This should always be true, otherwise the
+ // value wouldn't be properly quoted, but we
+ // will check for safety.
+ if (value.charAt(value.length() - 1) == '"')
+ {
+ value = value.substring(1, value.length() - 1);
+ }
+ else
+ {
+ value = value.substring(1);
+ }
+ }
+
+ if (value != null)
+ {
+ value = value.toLowerCase();
+ }
+
+ // Add the value to its corresponding property list.
+ if (property.equals(Constants.BUNDLE_NATIVECODE_OSNAME))
+ {
+ osNameList.add(value);
+ }
+ else if (property.equals(Constants.BUNDLE_NATIVECODE_OSVERSION))
+ {
+ osVersionList.add(normalizeOSVersion(value));
+ }
+ else if (property.equals(Constants.BUNDLE_NATIVECODE_PROCESSOR))
+ {
+ processorList.add(value);
+ }
+ else if (property.equals(Constants.BUNDLE_NATIVECODE_LANGUAGE))
+ {
+ languageList.add(value);
+ }
+ else if (property.equals(Constants.SELECTION_FILTER_ATTRIBUTE))
+ {
+ // TODO: NATIVE - I believe we can have multiple selection filters too.
+ selectionFilter = value;
+ }
+ }
+ }
+
+ if (libCount == 0)
+ {
+ return null;
+ }
+
+ // Shrink lib file array.
+ String[] actualLibEntries = new String[libCount];
+ System.arraycopy(libEntries, 0, actualLibEntries, 0, libCount);
+ return new NativeLibraryClause(
+ actualLibEntries,
+ (String[]) osNameList.toArray(new String[osNameList.size()]),
+ (String[]) processorList.toArray(new String[processorList.size()]),
+ (String[]) osVersionList.toArray(new String[osVersionList.size()]),
+ (String[]) languageList.toArray(new String[languageList.size()]),
+ selectionFilter);
+ }
+ catch (RuntimeException ex)
+ {
+ logger.log(Logger.LOG_ERROR,
+ "Error parsing native library header.", ex);
+ throw ex;
+ }
+ }
+
+ public static String formatOSVersion(String value)
+ {
+ // Header: 'Bundle-NativeCode', Parameter: 'osversion'
+ // Standardized 'osversion': major.minor.micro, only digits
+ try
+ {
+ Pattern versionPattern = Pattern.compile("\\d+\\.?\\d*\\.?\\d*");
+ Matcher matcher = versionPattern.matcher(value);
+ if (matcher.find())
+ {
+ value = matcher.group();
+ }
+ return Version.parseVersion(value).toString();
+ }
+ catch (Exception ex)
+ {
+ return Version.emptyVersion.toString();
+ }
+ }
+
+ public static List<String> getOsNameWithAliases(String osName)
+ {
+ //Can't assume this has been normalized
+ osName = normalizeOSName(osName);
+
+ List<String> result = OS_ALIASES.get(osName);
+
+ if(result == null)
+ {
+ result = Collections.singletonList(osName);
+ }
+
+ return Collections.unmodifiableList(result);
+ }
+
+ public static List<String> getProcessorWithAliases(String processor)
+ {
+ //Can't assume this has been normalized
+ processor = normalizeProcessor(processor);
+
+ List<String> result = PROC_ALIASES.get(processor);
+
+ if(result == null)
+ {
+ result = Collections.singletonList(processor);
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ public static String normalizeOSName(String value)
+ {
+ value = value.toLowerCase();
+
+ if (OS_ALIASES.containsKey(value))
+ {
+ // we found an alias match return the first value which is the normalized name
+ return OS_ALIASES.get(value).get(0);
+ }
+
+ //If we don't find a match do it the old way for compatibility
+ if (value.startsWith("win"))
+ {
+ String os = "win";
+ if (value.indexOf("32") >= 0 || value.indexOf("*") >= 0)
+ {
+ os = OS_WIN_32;
+ }
+ else if (value.indexOf("95") >= 0)
+ {
+ os = OS_WINDOWS_95;
+ }
+ else if (value.indexOf("98") >= 0)
+ {
+ os = OS_WINDOWS_98;
+ }
+ else if (value.indexOf("nt") >= 0)
+ {
+ os = OS_WINDOWS_NT;
+ }
+ else if (value.indexOf("2000") >= 0)
+ {
+ os = OS_WINDOWS_2000;
+ }
+ else if (value.indexOf("2003") >= 0)
+ {
+ os = OS_WINDOWS_2003;
+ }
+ else if (value.indexOf("2008") >= 0)
+ {
+ os = OS_WINDOWS_SERVER_2008;
+ }
+ else if (value.indexOf("2012") >= 0)
+ {
+ os = OS_WINDOWS_SERVER_2012;
+ }
+ else if (value.indexOf("xp") >= 0)
+ {
+ os = OS_WINDOWS_XP;
+ }
+ else if (value.indexOf("ce") >= 0)
+ {
+ os = OS_WINDOWS_CE;
+ }
+ else if (value.indexOf("vista") >= 0)
+ {
+ os = OS_WINDOWS_VISTA;
+ }
+ else if ((value.indexOf(" 7") >= 0) || value.equals("win7"))
+ {
+ os = OS_WINDOWS_7;
+ }
+ else if ((value.indexOf(" 8") >= 0) || value.equals("win8"))
+ {
+ os = OS_WINDOWS_8;
+ }
+ else if ((value.indexOf(" 9") >= 0) || value.equals("win9"))
+ {
+ os = OS_WINDOWS_9;
+ }
+ return os;
+ }
+ else if (value.startsWith(OS_LINUX))
+ {
+ return OS_LINUX;
+ }
+ else if (value.startsWith(OS_AIX))
+ {
+ return OS_AIX;
+ }
+ else if (value.startsWith(OS_DIGITALUNIX))
+ {
+ return OS_DIGITALUNIX;
+ }
+ else if (value.startsWith(OS_HPUX))
+ {
+ return OS_HPUX;
+ }
+ else if (value.startsWith(OS_IRIX))
+ {
+ return OS_IRIX;
+ }
+ else if (value.startsWith(OS_MACOSX) || value.startsWith("mac os x"))
+ {
+ return OS_MACOSX;
+ }
+ else if (value.startsWith(OS_MACOS) || value.startsWith("mac os"))
+ {
+ return OS_MACOS;
+ }
+ else if (value.startsWith(OS_NETWARE))
+ {
+ return OS_NETWARE;
+ }
+ else if (value.startsWith(OS_OPENBSD))
+ {
+ return OS_OPENBSD;
+ }
+ else if (value.startsWith(OS_NETBSD))
+ {
+ return OS_NETBSD;
+ }
+ else if (value.startsWith(OS_OS2) || value.startsWith("os/2"))
+ {
+ return OS_OS2;
+ }
+ else if (value.startsWith(OS_QNX) || value.startsWith("procnto"))
+ {
+ return OS_QNX;
+ }
+ else if (value.startsWith(OS_SOLARIS))
+ {
+ return OS_SOLARIS;
+ }
+ else if (value.startsWith(OS_SUNOS))
+ {
+ return OS_SUNOS;
+ }
+ else if (value.startsWith(OS_VXWORKS))
+ {
+ return OS_VXWORKS;
+ }
+ return value;
+ }
+
+ public static String normalizeProcessor(String value)
+ {
+ value = value.toLowerCase();
+
+ if(PROC_ALIASES.containsKey(value))
+ {
+ return PROC_ALIASES.get(value).get(0);
+ }
+
+ if (value.startsWith(PROC_X86_64) || value.startsWith("amd64") ||
+ value.startsWith("em64") || value.startsWith("x86_64"))
+ {
+ return PROC_X86_64;
+ }
+ else if (value.startsWith(PROC_X86) || value.startsWith("pentium")
+ || value.startsWith("i386") || value.startsWith("i486")
+ || value.startsWith("i586") || value.startsWith("i686"))
+ {
+ return PROC_X86;
+ }
+ else if (value.startsWith(PROC_68K))
+ {
+ return PROC_68K;
+ }
+ else if (value.startsWith(PROC_ARM_LE))
+ {
+ return PROC_ARM_LE;
+ }
+ else if (value.startsWith(PROC_ARM_BE))
+ {
+ return PROC_ARM_BE;
+ }
+ else if (value.startsWith(PROC_ARM))
+ {
+ return PROC_ARM;
+ }
+ else if (value.startsWith(PROC_ALPHA))
+ {
+ return PROC_ALPHA;
+ }
+ else if (value.startsWith(PROC_IGNITE) || value.startsWith("psc1k"))
+ {
+ return PROC_IGNITE;
+ }
+ else if (value.startsWith(PROC_MIPS))
+ {
+ return PROC_MIPS;
+ }
+ else if (value.startsWith(PROC_PARISC))
+ {
+ return PROC_PARISC;
+ }
+ else if (value.startsWith(PROC_POWER_PC) || value.startsWith("power")
+ || value.startsWith("ppc"))
+ {
+ return PROC_POWER_PC;
+ }
+ else if (value.startsWith(PROC_SPARC))
+ {
+ return PROC_SPARC;
+ }
+ return value;
+ }
+
+ public static String normalizeOSVersion(String value)
+ {
+ // Header: 'Bundle-NativeCode', Parameter: 'osversion'
+ // Standardized 'osversion': major.minor.micro, only digits
+ try
+ {
+ return VersionRange.parse(value).toString();
+ }
+ catch (Exception ex)
+ {
+ return Version.emptyVersion.toString();
+ }
+ }
+}
diff --git a/src/main/java/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java b/src/main/java/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java
deleted file mode 100644
index 0299041..0000000
--- a/src/main/java/org/apache/felix/framework/util/manifestparser/R4LibraryClause.java
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.felix.framework.util.manifestparser;
-
-import java.util.*;
-
-import org.apache.felix.framework.Logger;
-import org.apache.felix.framework.util.FelixConstants;
-import org.apache.felix.framework.util.VersionRange;
-import org.osgi.framework.*;
-
-public class R4LibraryClause
-{
- private final String[] m_libraryEntries;
- private final String[] m_osnames;
- private final String[] m_processors;
- private final String[] m_osversions;
- private final String[] m_languages;
- private final String m_selectionFilter;
-
- public R4LibraryClause(String[] libraryEntries, String[] osnames,
- String[] processors, String[] osversions, String[] languages,
- String selectionFilter)
- {
- m_libraryEntries = libraryEntries;
- m_osnames = osnames;
- m_processors = processors;
- m_osversions = osversions;
- m_languages = languages;
- m_selectionFilter = selectionFilter;
- }
-
- public R4LibraryClause(R4LibraryClause library)
- {
- m_libraryEntries = library.m_libraryEntries;
- m_osnames = library.m_osnames;
- m_osversions = library.m_osversions;
- m_processors = library.m_processors;
- m_languages = library.m_languages;
- m_selectionFilter = library.m_selectionFilter;
- }
-
- public String[] getLibraryEntries()
- {
- return m_libraryEntries;
- }
-
- public String[] getOSNames()
- {
- return m_osnames;
- }
-
- public String[] getProcessors()
- {
- return m_processors;
- }
-
- public String[] getOSVersions()
- {
- return m_osversions;
- }
-
- public String[] getLanguages()
- {
- return m_languages;
- }
-
- public String getSelectionFilter()
- {
- return m_selectionFilter;
- }
-
- public boolean match(Map configMap) throws BundleException
- {
- String normal_osname = normalizeOSName((String) configMap.get(Constants.FRAMEWORK_OS_NAME));
- String normal_processor = normalizeProcessor((String) configMap.get(Constants.FRAMEWORK_PROCESSOR));
- String normal_osversion = normalizeOSVersion((String) configMap.get(Constants.FRAMEWORK_OS_VERSION));
- String normal_language = (String) configMap.get(Constants.FRAMEWORK_LANGUAGE);
-
- // Check library's osname.
- if (!checkOSNames(normal_osname, getOSNames()))
- {
- return false;
- }
-
- // Check library's processor.
- if (!checkProcessors(normal_processor, getProcessors()))
- {
- return false;
- }
-
- // Check library's osversion if specified.
- if ((getOSVersions() != null) &&
- (getOSVersions().length > 0) &&
- !checkOSVersions(normal_osversion, getOSVersions()))
- {
- return false;
- }
-
- // Check library's language if specified.
- if ((getLanguages() != null) &&
- (getLanguages().length > 0) &&
- !checkLanguages(normal_language, getLanguages()))
- {
- return false;
- }
-
- // Check library's selection-filter if specified.
- if ((getSelectionFilter() != null) &&
- (getSelectionFilter().length() >= 0) &&
- !checkSelectionFilter(configMap, getSelectionFilter()))
- {
- return false;
- }
-
- return true;
- }
-
- private boolean checkOSNames(String currentOSName, String[] osnames)
- {
- boolean win32 = currentOSName.startsWith("win") && !currentOSName.equals("windowsce");
-
- for (int i = 0; (osnames != null) && (i < osnames.length); i++)
- {
- if (osnames[i].equals(currentOSName) ||
- ("win32".equals(osnames[i]) && win32))
- {
- return true;
- }
- }
- return false;
- }
-
- private boolean checkProcessors(String currentProcessor, String[] processors)
- {
- for (int i = 0; (processors != null) && (i < processors.length); i++)
- {
- if (processors[i].equals(currentProcessor))
- {
- return true;
- }
- }
- return false;
- }
-
- private boolean checkOSVersions(String currentOSVersion, String[] osversions)
- throws BundleException
- {
- for (int i = 0; (osversions != null) && (i < osversions.length); i++)
- {
- try
- {
- VersionRange range = VersionRange.parse(osversions[i]);
- if (range.isInRange(new Version(currentOSVersion)))
- {
- return true;
- }
- }
- catch (Exception ex)
- {
- throw new BundleException(
- "Error evaluating osversion: " + osversions[i], ex);
- }
- }
- return false;
- }
-
- private boolean checkLanguages(String currentLanguage, String[] languages)
- {
- for (int i = 0; (languages != null) && (i < languages.length); i++)
- {
- if (languages[i].equals(currentLanguage))
- {
- return true;
- }
- }
- return false;
- }
-
- private boolean checkSelectionFilter(Map configMap, String expr)
- throws BundleException
- {
- // Get all framework properties
- Dictionary dict = new Hashtable();
- for (Iterator i = configMap.keySet().iterator(); i.hasNext(); )
- {
- Object key = i.next();
- dict.put(key, configMap.get(key));
- }
- // Compute expression
- try
- {
- Filter filter = FrameworkUtil.createFilter(expr);
- return filter.match(dict);
- }
- catch (Exception ex)
- {
- throw new BundleException(
- "Error evaluating filter expression: " + expr, ex);
- }
- }
-
- public static R4LibraryClause parse(Logger logger, String s)
- {
- try
- {
- if ((s == null) || (s.length() == 0))
- {
- return null;
- }
-
- if (s.equals(FelixConstants.BUNDLE_NATIVECODE_OPTIONAL))
- {
- return new R4LibraryClause(null, null, null, null, null, null);
- }
-
- // The tokens are separated by semicolons and may include
- // any number of libraries along with one set of associated
- // properties.
- StringTokenizer st = new StringTokenizer(s, ";");
- String[] libEntries = new String[st.countTokens()];
- List osNameList = new ArrayList();
- List osVersionList = new ArrayList();
- List processorList = new ArrayList();
- List languageList = new ArrayList();
- String selectionFilter = null;
- int libCount = 0;
- while (st.hasMoreTokens())
- {
- String token = st.nextToken().trim();
- if (token.indexOf('=') < 0)
- {
- // Remove the slash, if necessary.
- libEntries[libCount] = (token.charAt(0) == '/')
- ? token.substring(1)
- : token;
- libCount++;
- }
- else
- {
- // Check for valid native library properties; defined as
- // a property name, an equal sign, and a value.
- // NOTE: StringTokenizer can not be used here because
- // a value can contain one or more "=" too, e.g.,
- // selection-filter="(org.osgi.framework.windowing.system=gtk)"
- String property = null;
- String value = null;
- if (!(token.indexOf("=") > 1))
- {
- throw new IllegalArgumentException(
- "Bundle manifest native library entry malformed: " + token);
- }
- else
- {
- property = (token.substring(0, token.indexOf("=")))
- .trim().toLowerCase();
- value = (token.substring(token.indexOf("=") + 1, token
- .length())).trim();
- }
-
- // Values may be quoted, so remove quotes if present.
- if (value.charAt(0) == '"')
- {
- // This should always be true, otherwise the
- // value wouldn't be properly quoted, but we
- // will check for safety.
- if (value.charAt(value.length() - 1) == '"')
- {
- value = value.substring(1, value.length() - 1);
- }
- else
- {
- value = value.substring(1);
- }
- }
- // Add the value to its corresponding property list.
- if (property.equals(Constants.BUNDLE_NATIVECODE_OSNAME))
- {
- osNameList.add(normalizeOSName(value));
- }
- else if (property.equals(Constants.BUNDLE_NATIVECODE_OSVERSION))
- {
- osVersionList.add(normalizeOSVersion(value));
- }
- else if (property.equals(Constants.BUNDLE_NATIVECODE_PROCESSOR))
- {
- processorList.add(normalizeProcessor(value));
- }
- else if (property.equals(Constants.BUNDLE_NATIVECODE_LANGUAGE))
- {
- languageList.add(value);
- }
- else if (property.equals(Constants.SELECTION_FILTER_ATTRIBUTE))
- {
-// TODO: NATIVE - I believe we can have multiple selection filters too.
- selectionFilter = value;
- }
- }
- }
-
- if (libCount == 0)
- {
- return null;
- }
-
- // Shrink lib file array.
- String[] actualLibEntries = new String[libCount];
- System.arraycopy(libEntries, 0, actualLibEntries, 0, libCount);
- return new R4LibraryClause(
- actualLibEntries,
- (String[]) osNameList.toArray(new String[osNameList.size()]),
- (String[]) processorList.toArray(new String[processorList.size()]),
- (String[]) osVersionList.toArray(new String[osVersionList.size()]),
- (String[]) languageList.toArray(new String[languageList.size()]),
- selectionFilter);
- }
- catch (RuntimeException ex)
- {
- logger.log(Logger.LOG_ERROR,
- "Error parsing native library header.", ex);
- throw ex;
- }
- }
-
- public static String normalizeOSName(String value)
- {
- value = value.toLowerCase();
-
- if (value.startsWith("win"))
- {
- String os = "win";
- if (value.indexOf("32") >= 0 || value.indexOf("*") >= 0)
- {
- os = "win32";
- }
- else if (value.indexOf("95") >= 0)
- {
- os = "windows95";
- }
- else if (value.indexOf("98") >= 0)
- {
- os = "windows98";
- }
- else if (value.indexOf("nt") >= 0)
- {
- os = "windowsnt";
- }
- else if (value.indexOf("2000") >= 0)
- {
- os = "windows2000";
- }
- else if (value.indexOf("2003") >= 0)
- {
- os = "windows2003";
- }
- else if (value.indexOf("2008") >= 0)
- {
- os = "windowsserver2008";
- }
- else if (value.indexOf("2012") >= 0)
- {
- os = "windowsserver2012";
- }
- else if (value.indexOf("xp") >= 0)
- {
- os = "windowsxp";
- }
- else if (value.indexOf("ce") >= 0)
- {
- os = "windowsce";
- }
- else if (value.indexOf("vista") >= 0)
- {
- os = "windowsvista";
- }
- else if ((value.indexOf(" 7") >= 0) || value.equals("win7"))
- {
- os = "windows7";
- }
- else if ((value.indexOf(" 8") >= 0) || value.equals("win8"))
- {
- os = "windows8";
- }
- else if ((value.indexOf(" 9") >= 0) || value.equals("win9"))
- {
- os = "windows9";
- }
- return os;
- }
- else if (value.startsWith("linux"))
- {
- return "linux";
- }
- else if (value.startsWith("aix"))
- {
- return "aix";
- }
- else if (value.startsWith("digitalunix"))
- {
- return "digitalunix";
- }
- else if (value.startsWith("hpux"))
- {
- return "hpux";
- }
- else if (value.startsWith("irix"))
- {
- return "irix";
- }
- else if (value.startsWith("macos") || value.startsWith("mac os"))
- {
- return "macos";
- }
- else if (value.startsWith("netware"))
- {
- return "netware";
- }
- else if (value.startsWith("openbsd"))
- {
- return "openbsd";
- }
- else if (value.startsWith("netbsd"))
- {
- return "netbsd";
- }
- else if (value.startsWith("os2") || value.startsWith("os/2"))
- {
- return "os2";
- }
- else if (value.startsWith("qnx") || value.startsWith("procnto"))
- {
- return "qnx";
- }
- else if (value.startsWith("solaris"))
- {
- return "solaris";
- }
- else if (value.startsWith("sunos"))
- {
- return "sunos";
- }
- else if (value.startsWith("vxworks"))
- {
- return "vxworks";
- }
- return value;
- }
-
- public static String normalizeProcessor(String value)
- {
- value = value.toLowerCase();
-
- if (value.startsWith("x86-64") || value.startsWith("amd64") ||
- value.startsWith("em64") || value.startsWith("x86_64"))
- {
- return "x86-64";
- }
- else if (value.startsWith("x86") || value.startsWith("pentium")
- || value.startsWith("i386") || value.startsWith("i486")
- || value.startsWith("i586") || value.startsWith("i686"))
- {
- return "x86";
- }
- else if (value.startsWith("68k"))
- {
- return "68k";
- }
- else if (value.startsWith("arm"))
- {
- return "arm";
- }
- else if (value.startsWith("alpha"))
- {
- return "alpha";
- }
- else if (value.startsWith("ignite") || value.startsWith("psc1k"))
- {
- return "ignite";
- }
- else if (value.startsWith("mips"))
- {
- return "mips";
- }
- else if (value.startsWith("parisc"))
- {
- return "parisc";
- }
- else if (value.startsWith("powerpc") || value.startsWith("power")
- || value.startsWith("ppc"))
- {
- return "powerpc";
- }
- else if (value.startsWith("sparc"))
- {
- return "sparc";
- }
- return value;
- }
-
- public static String normalizeOSVersion(String value)
- {
- // Header: 'Bundle-NativeCode', Parameter: 'osversion'
- // Standardized 'osversion': major.minor.micro, only digits
- try
- {
- return VersionRange.parse(value).toString();
- }
- catch (Exception ex)
- {
- return Version.emptyVersion.toString();
- }
- }
-}
diff --git a/src/main/java/org/osgi/dto/DTO.java b/src/main/java/org/osgi/dto/DTO.java
new file mode 100644
index 0000000..cc76cab
--- /dev/null
+++ b/src/main/java/org/osgi/dto/DTO.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.dto;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Super type for Data Transfer Objects.
+ *
+ * <p>
+ * A Data Transfer Object (DTO) is easily serializable having only public fields
+ * of primitive types and their wrapper classes, Strings, and DTOs. List, Set,
+ * Map and array aggregates may also be used. The aggregates must only hold
+ * objects of the listed types or aggregates.
+ *
+ * <p>
+ * The object graph from a Data Transfer Object must be a tree to simplify
+ * serialization and deserialization.
+ *
+ * @author $Id: DTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public abstract class DTO {
+
+ /**
+ * Return a string representation of this DTO suitable for use when
+ * debugging.
+ *
+ * <p>
+ * The format of the string representation is not specified and subject to
+ * change.
+ *
+ * @return A string representation of this DTO suitable for use when
+ * debugging.
+ */
+ @Override
+ public String toString() {
+ return appendValue(new StringBuilder(), new IdentityHashMap<Object, String>(), "#", this).toString();
+ }
+
+ /**
+ * Append the specified DTO's string representation to the specified
+ * StringBuilder.
+ *
+ * @param result StringBuilder to which the string representation is
+ * appended.
+ * @param objectRefs References to "seen" objects.
+ * @param refpath The reference path of the specified DTO.
+ * @param dto The DTO whose string representation is to be appended.
+ * @return The specified StringBuilder.
+ */
+ private static StringBuilder appendDTO(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final DTO dto) {
+ result.append("{");
+ String delim = "";
+ for (Field field : dto.getClass().getFields()) {
+ if (Modifier.isStatic(field.getModifiers())) {
+ continue;
+ }
+ result.append(delim);
+ final String name = field.getName();
+ appendString(result, name);
+ result.append(":");
+ Object value = null;
+ try {
+ value = field.get(dto);
+ } catch (IllegalAccessException e) {
+ // use null value;
+ }
+ appendValue(result, objectRefs, refpath + "/" + name, value);
+ delim = ", ";
+ }
+ result.append("}");
+ return result;
+ }
+
+ /**
+ * Append the specified value's string representation to the specified
+ * StringBuilder.
+ *
+ * <p>
+ * This method handles cycles in the object graph, using path-based
+ * references, even though the specification requires the object graph from
+ * a DTO to be a tree.
+ *
+ * @param result StringBuilder to which the string representation is
+ * appended.
+ * @param objectRefs References to "seen" objects.
+ * @param refpath The reference path of the specified value.
+ * @param value The object whose string representation is to be appended.
+ * @return The specified StringBuilder.
+ */
+ private static StringBuilder appendValue(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final Object value) {
+ if (value == null) {
+ return result.append("null");
+ }
+ // Simple Java types
+ if (value instanceof String || value instanceof Character) {
+ return appendString(result, compress(value.toString()));
+ }
+ if (value instanceof Number || value instanceof Boolean) {
+ return result.append(value.toString());
+ }
+
+ // Complex types
+ final String path = objectRefs.get(value);
+ if (path != null) {
+ result.append("{\"$ref\":");
+ appendString(result, path);
+ result.append("}");
+ return result;
+ }
+ objectRefs.put(value, refpath);
+
+ if (value instanceof DTO) {
+ return appendDTO(result, objectRefs, refpath, (DTO) value);
+ }
+ if (value instanceof Map) {
+ return appendMap(result, objectRefs, refpath, (Map<?, ?>) value);
+ }
+ if (value instanceof List || value instanceof Set) {
+ return appendIterable(result, objectRefs, refpath, (Iterable<?>) value);
+ }
+ if (value.getClass().isArray()) {
+ return appendArray(result, objectRefs, refpath, value);
+ }
+ return appendString(result, compress(value.toString()));
+ }
+
+ /**
+ * Append the specified array's string representation to the specified
+ * StringBuilder.
+ *
+ * @param result StringBuilder to which the string representation is
+ * appended.
+ * @param objectRefs References to "seen" objects.
+ * @param refpath The reference path of the specified array.
+ * @param array The array whose string representation is to be appended.
+ * @return The specified StringBuilder.
+ */
+ private static StringBuilder appendArray(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final Object array) {
+ result.append("[");
+ final int length = Array.getLength(array);
+ for (int i = 0; i < length; i++) {
+ if (i > 0) {
+ result.append(",");
+ }
+ appendValue(result, objectRefs, refpath + "/" + i, Array.get(array, i));
+ }
+ result.append("]");
+ return result;
+ }
+
+ /**
+ * Append the specified iterable's string representation to the specified
+ * StringBuilder.
+ *
+ * @param result StringBuilder to which the string representation is
+ * appended.
+ * @param objectRefs References to "seen" objects.
+ * @param refpath The reference path of the specified list.
+ * @param iterable The iterable whose string representation is to be
+ * appended.
+ * @return The specified StringBuilder.
+ */
+ private static StringBuilder appendIterable(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final Iterable<?> iterable) {
+ result.append("[");
+ int i = 0;
+ for (Object item : iterable) {
+ if (i > 0) {
+ result.append(",");
+ }
+ appendValue(result, objectRefs, refpath + "/" + i, item);
+ i++;
+ }
+ result.append("]");
+ return result;
+ }
+
+ /**
+ * Append the specified map's string representation to the specified
+ * StringBuilder.
+ *
+ * @param result StringBuilder to which the string representation is
+ * appended.
+ * @param objectRefs References to "seen" objects.
+ * @param refpath The reference path of the specified map.
+ * @param map The map whose string representation is to be appended.
+ * @return The specified StringBuilder.
+ */
+ private static StringBuilder appendMap(final StringBuilder result, final Map<Object, String> objectRefs, final String refpath, final Map<?, ?> map) {
+ result.append("{");
+ String delim = "";
+ for (Map.Entry<?, ?> entry : map.entrySet()) {
+ result.append(delim);
+ final String name = String.valueOf(entry.getKey());
+ appendString(result, name);
+ result.append(":");
+ final Object value = entry.getValue();
+ appendValue(result, objectRefs, refpath + "/" + name, value);
+ delim = ", ";
+ }
+ result.append("}");
+ return result;
+ }
+
+ /**
+ * Append the specified string to the specified StringBuilder.
+ *
+ * @param result StringBuilder to which the string is appended.
+ * @param string The string to be appended.
+ * @return The specified StringBuilder.
+ */
+ private static StringBuilder appendString(final StringBuilder result, final CharSequence string) {
+ result.append("\"");
+ int i = result.length();
+ result.append(string);
+ while (i < result.length()) { // escape if necessary
+ char c = result.charAt(i);
+ if ((c == '"') || (c == '\\')) {
+ result.insert(i, '\\');
+ i = i + 2;
+ continue;
+ }
+ if (c < 0x20) {
+ result.insert(i + 1, Integer.toHexString(c | 0x10000));
+ result.replace(i, i + 2, "\\u");
+ i = i + 6;
+ continue;
+ }
+ i++;
+ }
+ result.append("\"");
+ return result;
+ }
+
+ /**
+ * Compress, in length, the specified string.
+ *
+ * @param in The string to potentially compress.
+ * @return The string compressed, if necessary.
+ */
+ private static CharSequence compress(final CharSequence in) {
+ final int length = in.length();
+ if (length <= 21) {
+ return in;
+ }
+ StringBuilder result = new StringBuilder(21);
+ result.append(in, 0, 9);
+ result.append("...");
+ result.append(in, length - 9, length);
+ return result;
+ }
+}
diff --git a/src/main/java/org/osgi/dto/package-info.java b/src/main/java/org/osgi/dto/package-info.java
new file mode 100644
index 0000000..460ab55
--- /dev/null
+++ b/src/main/java/org/osgi/dto/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ * 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.
+ */
+
+/**
+ * OSGi Data Transfer Object 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.dto; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.dto; version="[1.0,1.1)"}
+ *
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+
+ at Version("1.0")
+package org.osgi.dto;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/dto/packageinfo b/src/main/java/org/osgi/dto/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/src/main/java/org/osgi/dto/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/src/main/java/org/osgi/framework/AdaptPermission.java b/src/main/java/org/osgi/framework/AdaptPermission.java
index fbe70c1..918e469 100644
--- a/src/main/java/org/osgi/framework/AdaptPermission.java
+++ b/src/main/java/org/osgi/framework/AdaptPermission.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.
@@ -41,7 +41,7 @@ import java.util.Map;
* {@code AdaptPermission} has one action: {@code adapt}.
*
* @ThreadSafe
- * @version $Id: 3bc095bd294db2d8ea25971a3d71991de1495b1a $
+ * @author $Id: 9f0866e633ce08566547b4955a2ece54c46944e0 $
*/
public final class AdaptPermission extends BasicPermission {
@@ -286,6 +286,7 @@ public final class AdaptPermission extends BasicPermission {
* @return {@code true} if the specified permission is implied by this
* object; {@code false} otherwise.
*/
+ @Override
public boolean implies(Permission p) {
if (!(p instanceof AdaptPermission)) {
return false;
@@ -339,6 +340,7 @@ public final class AdaptPermission extends BasicPermission {
* @return Canonical string representation of the {@code AdaptPermission}
* actions.
*/
+ @Override
public String getActions() {
String result = actions;
if (result == null) {
@@ -353,6 +355,7 @@ public final class AdaptPermission extends BasicPermission {
*
* @return A new {@code PermissionCollection} object.
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new AdaptPermissionCollection();
}
@@ -369,6 +372,7 @@ public final class AdaptPermission extends BasicPermission {
* the same name and actions as this {@code AdaptPermission} object;
* {@code false} otherwise.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -388,6 +392,7 @@ public final class AdaptPermission extends BasicPermission {
*
* @return A hash code value for this object.
*/
+ @Override
public int hashCode() {
int h = 31 * 17 + getName().hashCode();
h = 31 * h + getActions().hashCode();
@@ -424,9 +429,8 @@ public final class AdaptPermission extends BasicPermission {
}
/**
- * Called by {@code <@link AdaptPermission#implies(Permission)>}. This
- * method is only called on a requested permission which cannot have a
- * filter set.
+ * Called by {@link AdaptPermission#implies(Permission)}. This method is
+ * only called on a requested permission which cannot have a filter set.
*
* @return a map of properties for this permission.
*/
@@ -438,8 +442,8 @@ public final class AdaptPermission extends BasicPermission {
final Map<String, Object> map = new HashMap<String, Object>(5);
map.put("adaptClass", getName());
if (bundle != null) {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
map.put("id", new Long(bundle.getBundleId()));
map.put("location", bundle.getLocation());
String name = bundle.getSymbolicName();
@@ -502,6 +506,7 @@ final class AdaptPermissionCollection extends PermissionCollection {
* @throws SecurityException If this {@code AdaptPermissionCollection}
* object has been marked read-only.
*/
+ @Override
public void add(final Permission permission) {
if (!(permission instanceof AdaptPermission)) {
throw new IllegalArgumentException("invalid permission: " + permission);
@@ -547,6 +552,7 @@ final class AdaptPermissionCollection extends PermissionCollection {
* @return {@code true} if {@code permission} is a proper subset of a
* permission in the set; {@code false} otherwise.
*/
+ @Override
public boolean implies(final Permission permission) {
if (!(permission instanceof AdaptPermission)) {
return false;
@@ -590,6 +596,7 @@ final class AdaptPermissionCollection extends PermissionCollection {
*
* @return Enumeration of all {@code AdaptPermission} objects.
*/
+ @Override
public synchronized Enumeration<Permission> elements() {
List<Permission> all = new ArrayList<Permission>(permissions.values());
return Collections.enumeration(all);
@@ -607,7 +614,9 @@ final class AdaptPermissionCollection extends PermissionCollection {
private synchronized void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gfields = in.readFields();
- permissions = (HashMap<String, AdaptPermission>) gfields.get("permissions", null);
+ @SuppressWarnings("unchecked")
+ HashMap<String, AdaptPermission> p = (HashMap<String, AdaptPermission>) gfields.get("permissions", null);
+ permissions = p;
all_allowed = gfields.get("all_allowed", false);
}
}
diff --git a/src/main/java/org/osgi/framework/AdminPermission.java b/src/main/java/org/osgi/framework/AdminPermission.java
index 324360c..26e9093 100644
--- a/src/main/java/org/osgi/framework/AdminPermission.java
+++ b/src/main/java/org/osgi/framework/AdminPermission.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.
@@ -52,8 +52,10 @@ import java.util.Map;
* lifecycle BundleContext.installBundle
* Bundle.update
* Bundle.uninstall
- * listener BundleContext.addBundleListener for SynchronousBundleListener
- * BundleContext.removeBundleListener for SynchronousBundleListener
+ * listener BundleContext.addBundleListener for
+ * SynchronousBundleListener
+ * BundleContext.removeBundleListener for
+ * SynchronousBundleListener
* metadata Bundle.getHeaders
* Bundle.getLocation
* resolve FrameworkWiring.refreshBundles
@@ -67,7 +69,8 @@ import java.util.Map;
* startlevel FrameworkStartLevel.setStartLevel
* FrameworkStartLevel.setInitialBundleStartLevel
* context Bundle.getBundleContext
- * weave WovenClass.setBytes
+ * weave WovenClass.getBytes
+ * WovenClass.setBytes
* WovenClass.getDynamicImports for modification
* </pre>
*
@@ -89,7 +92,7 @@ import java.util.Map;
* Filter attribute names are processed in a case sensitive manner.
*
* @ThreadSafe
- * @version $Id: cd883e81fde210ce8f0cabaebea377378d672818 $
+ * @author $Id: 2a803b07dcdc9af47ca0cb208d96fcd9c0bcfb0c $
*/
public final class AdminPermission extends BasicPermission {
@@ -236,8 +239,9 @@ public final class AdminPermission extends BasicPermission {
* Examples:
*
* <pre>
- * (signer=\*,o=ACME,c=US)
- * (&(signer=\*,o=ACME,c=US)(name=com.acme.*)(location=http://www.acme.com/bundles/*))
+ * (signer=\*,o=ACME,c=US)
+ * (&(signer=\*,o=ACME,c=US)(name=com.acme.*)
+ * (location=http://www.acme.com/bundles/*))
* (id>=1)
* </pre>
*
@@ -593,6 +597,7 @@ public final class AdminPermission extends BasicPermission {
* @return {@code true} if the specified permission is implied by this
* object; {@code false} otherwise.
*/
+ @Override
public boolean implies(Permission p) {
if (!(p instanceof AdminPermission)) {
return false;
@@ -663,6 +668,7 @@ public final class AdminPermission extends BasicPermission {
* @return Canonical string representation of the {@code AdminPermission}
* actions.
*/
+ @Override
public String getActions() {
String result = actions;
if (result == null) {
@@ -740,6 +746,7 @@ public final class AdminPermission extends BasicPermission {
*
* @return A new {@code PermissionCollection} object.
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new AdminPermissionCollection();
}
@@ -751,6 +758,7 @@ public final class AdminPermission extends BasicPermission {
* @return {@code true} if {@code obj} is equivalent to this
* {@code AdminPermission}; {@code false} otherwise.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -770,6 +778,7 @@ public final class AdminPermission extends BasicPermission {
*
* @return Hash code value for this object.
*/
+ @Override
public int hashCode() {
int h = 31 * 17 + getName().hashCode();
h = 31 * h + getActions().hashCode();
@@ -833,8 +842,8 @@ public final class AdminPermission extends BasicPermission {
recurse.set(bundle);
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(bundle.getBundleId()));
map.put("location", bundle.getLocation());
String name = bundle.getSymbolicName();
@@ -893,6 +902,7 @@ final class AdminPermissionCollection extends PermissionCollection {
* @throws SecurityException If this {@code AdminPermissionCollection}
* object has been marked read-only.
*/
+ @Override
public void add(Permission permission) {
if (!(permission instanceof AdminPermission)) {
throw new IllegalArgumentException("invalid permission: " + permission);
@@ -936,6 +946,7 @@ final class AdminPermissionCollection extends PermissionCollection {
* {@code AdminPermission} in this collection, {@code false}
* otherwise.
*/
+ @Override
public boolean implies(Permission permission) {
if (!(permission instanceof AdminPermission)) {
return false;
@@ -979,6 +990,7 @@ final class AdminPermissionCollection extends PermissionCollection {
*
* @return Enumeration of all {@code AdminPermission} objects.
*/
+ @Override
public synchronized Enumeration<Permission> elements() {
List<Permission> all = new ArrayList<Permission>(permissions.values());
return Collections.enumeration(all);
@@ -997,6 +1009,7 @@ final class AdminPermissionCollection extends PermissionCollection {
private synchronized void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gfields = in.readFields();
+ @SuppressWarnings("unchecked")
Hashtable<String, AdminPermission> hashtable = (Hashtable<String, AdminPermission>) gfields.get("permissions", null);
permissions = new HashMap<String, AdminPermission>(hashtable);
all_allowed = gfields.get("all_allowed", false);
diff --git a/src/main/java/org/osgi/framework/AllServiceListener.java b/src/main/java/org/osgi/framework/AllServiceListener.java
index 71e27cd..4db7ba3 100644
--- a/src/main/java/org/osgi/framework/AllServiceListener.java
+++ b/src/main/java/org/osgi/framework/AllServiceListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2005, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2005, 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.
@@ -16,6 +16,8 @@
package org.osgi.framework;
+import org.osgi.annotation.versioning.ConsumerType;
+
/**
* A {@code ServiceEvent} listener that does not filter based upon package
* wiring. {@code AllServiceListener} is a listener interface that may be
@@ -52,9 +54,9 @@ package org.osgi.framework;
* @see ServicePermission
* @ThreadSafe
* @since 1.3
- * @version $Id: 7a0c82db414be7064a06e1868eb41a8c8f8d9d6c $
+ * @author $Id: fc2039183bb7c2117c182949118bb4cdd3b2e6c2 $
*/
-
+ at ConsumerType
public interface AllServiceListener extends ServiceListener {
// This is a marker interface
}
diff --git a/src/main/java/org/osgi/framework/Bundle.java b/src/main/java/org/osgi/framework/Bundle.java
index d814e9a..b9334ae 100644
--- a/src/main/java/org/osgi/framework/Bundle.java
+++ b/src/main/java/org/osgi/framework/Bundle.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.
@@ -25,6 +25,7 @@ import java.util.Dictionary;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.wiring.FrameworkWiring;
/**
@@ -44,12 +45,12 @@ import org.osgi.framework.wiring.FrameworkWiring;
* <p>
* A bundle can be in one of six states:
* <ul>
- * <li>{@link #UNINSTALLED}
- * <li>{@link #INSTALLED}
- * <li>{@link #RESOLVED}
- * <li>{@link #STARTING}
- * <li>{@link #STOPPING}
- * <li>{@link #ACTIVE}
+ * <li>{@link #UNINSTALLED}</li>
+ * <li>{@link #INSTALLED}</li>
+ * <li>{@link #RESOLVED}</li>
+ * <li>{@link #STARTING}</li>
+ * <li>{@link #STOPPING}</li>
+ * <li>{@link #ACTIVE}</li>
* </ul>
* <p>
* Values assigned to these states have no specified ordering; they represent
@@ -74,9 +75,9 @@ import org.osgi.framework.wiring.FrameworkWiring;
* bundle id} and is greater if it has a higher bundle id.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: 8a58ab72af389b1999b88348e4944203b7096510 $
+ * @author $Id: 81a8f18b2fcc7810817cd19f6d5e0709db1c1d12 $
*/
+ at ProviderType
public interface Bundle extends Comparable<Bundle> {
/**
* The bundle is uninstalled and may not be used.
@@ -114,14 +115,14 @@ public interface Bundle extends Comparable<Bundle> {
* include:
* <ul>
* <li>The bundle's class path from its {@link Constants#BUNDLE_CLASSPATH}
- * Manifest header.
+ * Manifest header.</li>
* <li>The bundle's package dependencies from its
* {@link Constants#EXPORT_PACKAGE} and {@link Constants#IMPORT_PACKAGE}
- * Manifest headers.
+ * Manifest headers.</li>
* <li>The bundle's required bundle dependencies from its
- * {@link Constants#REQUIRE_BUNDLE} Manifest header.
+ * {@link Constants#REQUIRE_BUNDLE} Manifest header.</li>
* <li>A fragment bundle's host dependency from its
- * {@link Constants#FRAGMENT_HOST} Manifest header.
+ * {@link Constants#FRAGMENT_HOST} Manifest header.</li>
* </ul>
* <p>
* Note that the bundle is not active yet. A bundle must be put in the
@@ -262,12 +263,11 @@ public interface Bundle extends Comparable<Bundle> {
* <ul>
* <li>If the {@link #START_TRANSIENT} option is set, then a
* {@code BundleException} is thrown indicating this bundle cannot be
- * started due to the Framework's current start level.
- *
+ * started due to the Framework's current start level.</li>
* <li>Otherwise, the Framework must set this bundle's persistent autostart
* setting to <em>Started with declared activation</em> if the
* {@link #START_ACTIVATION_POLICY} option is set or
- * <em>Started with eager activation</em> if not set.
+ * <em>Started with eager activation</em> if not set.</li>
* </ul>
* <p>
* When the Framework's current start level becomes equal to or more than
@@ -279,82 +279,71 @@ public interface Bundle extends Comparable<Bundle> {
* then this method must wait for activation or deactivation to complete
* before continuing. If this does not occur in a reasonable time, a
* {@code BundleException} is thrown to indicate this bundle was unable to
- * be started.
- *
- * <li>If this bundle's state is {@code ACTIVE} then this method returns
- * immediately.
- *
+ * be started.</li>
* <li>If the {@link #START_TRANSIENT} option is not set then set this
* bundle's autostart setting to <em>Started with declared activation</em>
* if the {@link #START_ACTIVATION_POLICY} option is set or
* <em>Started with eager activation</em> if not set. When the Framework is
* restarted and this bundle's autostart setting is not <em>Stopped</em>,
- * this bundle must be automatically started.
- *
+ * this bundle must be automatically started.</li>
+ * <li>If this bundle's state is {@code ACTIVE} then this method returns
+ * immediately.</li>
* <li>If this bundle's state is not {@code RESOLVED}, an attempt is made to
* resolve this bundle. If the Framework cannot resolve this bundle, a
- * {@code BundleException} is thrown.
- *
+ * {@code BundleException} is thrown.</li>
* <li>If the {@link #START_ACTIVATION_POLICY} option is set and this
* bundle's declared activation policy is {@link Constants#ACTIVATION_LAZY
* lazy} then:
* <ul>
* <li>If this bundle's state is {@code STARTING} then this method returns
- * immediately.
- * <li>This bundle's state is set to {@code STARTING}.
- * <li>A bundle event of type {@link BundleEvent#LAZY_ACTIVATION} is fired.
+ * immediately.</li>
+ * <li>This bundle's state is set to {@code STARTING}.</li>
+ * <li>A bundle event of type {@link BundleEvent#LAZY_ACTIVATION} is fired.</li>
* <li>This method returns immediately and the remaining steps will be
- * followed when this bundle's activation is later triggered.
+ * followed when this bundle's activation is later triggered.</li>
* </ul>
- * <i></i>
- * <li>This bundle's state is set to {@code STARTING}.
- *
- * <li>A bundle event of type {@link BundleEvent#STARTING} is fired.
- *
+ * </li>
+ * <li>This bundle's state is set to {@code STARTING}.</li>
+ * <li>A bundle event of type {@link BundleEvent#STARTING} is fired.</li>
* <li>The {@link BundleActivator#start(BundleContext)} method of this
* bundle's {@code BundleActivator}, if one is specified, is called. If the
* {@code BundleActivator} is invalid or throws an exception then:
* <ul>
- * <li>This bundle's state is set to {@code STOPPING}.
- * <li>A bundle event of type {@link BundleEvent#STOPPING} is fired.
- * <li>Any services registered by this bundle must be unregistered.
- * <li>Any services used by this bundle must be released.
- * <li>Any listeners registered by this bundle must be removed.
- * <li>This bundle's state is set to {@code RESOLVED}.
- * <li>A bundle event of type {@link BundleEvent#STOPPED} is fired.
- * <li>A {@code BundleException} is then thrown.
+ * <li>This bundle's state is set to {@code STOPPING}.</li>
+ * <li>A bundle event of type {@link BundleEvent#STOPPING} is fired.</li>
+ * <li>Any services registered by this bundle must be unregistered.</li>
+ * <li>Any services used by this bundle must be released.</li>
+ * <li>Any listeners registered by this bundle must be removed.</li>
+ * <li>This bundle's state is set to {@code RESOLVED}.</li>
+ * <li>A bundle event of type {@link BundleEvent#STOPPED} is fired.</li>
+ * <li>A {@code BundleException} is then thrown.</li>
* </ul>
- * <i></i>
- * <li>If this bundle's state is {@code UNINSTALLED}, because this bundle
- * was uninstalled while the {@code BundleActivator.start} method was
- * running, a {@code BundleException} is thrown.
- *
- * <li>This bundle's state is set to {@code ACTIVE}.
- *
- * <li>A bundle event of type {@link BundleEvent#STARTED} is fired.
+ * </li>
+ * <li>This bundle's state is set to {@code ACTIVE}.</li>
+ * <li>A bundle event of type {@link BundleEvent#STARTED} is fired.</li>
* </ol>
*
* <b>Preconditions </b>
* <ul>
* <li>{@code getState()} in { {@code INSTALLED}, {@code RESOLVED}
* } or { {@code INSTALLED}, {@code RESOLVED},
- * {@code STARTING} } if this bundle has a lazy activation policy.
+ * {@code STARTING} } if this bundle has a lazy activation policy.</li>
* </ul>
* <b>Postconditions, no exceptions thrown </b>
* <ul>
* <li>Bundle autostart setting is modified unless the
- * {@link #START_TRANSIENT} option was set.
+ * {@link #START_TRANSIENT} option was set.</li>
* <li>{@code getState()} in { {@code ACTIVE} } unless the
- * lazy activation policy was used.
+ * lazy activation policy was used.</li>
* <li>{@code BundleActivator.start()} has been called and did not throw an
- * exception unless the lazy activation policy was used.
+ * exception unless the lazy activation policy was used.</li>
* </ul>
* <b>Postconditions, when an exception is thrown </b>
* <ul>
* <li>Depending on when the exception occurred, bundle autostart setting is
- * modified unless the {@link #START_TRANSIENT} option was set.
+ * modified unless the {@link #START_TRANSIENT} option was set.</li>
* <li>{@code getState()} not in { {@code STARTING}, {@code ACTIVE}
- * }.
+ * }.</li>
* </ul>
*
* @param options The options for starting this bundle. See
@@ -404,62 +393,53 @@ public interface Bundle extends Comparable<Bundle> {
* The following steps are required to stop a bundle:
* <ol>
* <li>If this bundle's state is {@code UNINSTALLED} then an
- * {@code IllegalStateException} is thrown.
- *
+ * {@code IllegalStateException} is thrown.</li>
* <li>If this bundle is in the process of being activated or deactivated
* then this method must wait for activation or deactivation to complete
* before continuing. If this does not occur in a reasonable time, a
* {@code BundleException} is thrown to indicate this bundle was unable to
- * be stopped.
+ * be stopped.</li>
* <li>If the {@link #STOP_TRANSIENT} option is not set then then set this
* bundle's persistent autostart setting to to <em>Stopped</em>. When the
* Framework is restarted and this bundle's autostart setting is
- * <em>Stopped</em>, this bundle must not be automatically started.
- *
+ * <em>Stopped</em>, this bundle must not be automatically started.</li>
* <li>If this bundle's state is not {@code STARTING} or {@code ACTIVE} then
- * this method returns immediately.
- *
- * <li>This bundle's state is set to {@code STOPPING}.
- *
- * <li>A bundle event of type {@link BundleEvent#STOPPING} is fired.
- *
+ * this method returns immediately.</li>
+ * <li>This bundle's state is set to {@code STOPPING}.</li>
+ * <li>A bundle event of type {@link BundleEvent#STOPPING} is fired.</li>
* <li>If this bundle's state was {@code ACTIVE} prior to setting the state
* to {@code STOPPING}, the {@link BundleActivator#stop(BundleContext)}
* method of this bundle's {@code BundleActivator}, if one is specified, is
* called. If that method throws an exception, this method must continue to
* stop this bundle and a {@code BundleException} must be thrown after
- * completion of the remaining steps.
- *
- * <li>Any services registered by this bundle must be unregistered.
- * <li>Any services used by this bundle must be released.
- * <li>Any listeners registered by this bundle must be removed.
- *
+ * completion of the remaining steps.</li>
+ * <li>Any services registered by this bundle must be unregistered.</li>
+ * <li>Any services used by this bundle must be released.</li>
+ * <li>Any listeners registered by this bundle must be removed.</li>
* <li>If this bundle's state is {@code UNINSTALLED}, because this bundle
* was uninstalled while the {@code BundleActivator.stop} method was
- * running, a {@code BundleException} must be thrown.
- *
- * <li>This bundle's state is set to {@code RESOLVED}.
- *
- * <li>A bundle event of type {@link BundleEvent#STOPPED} is fired.
+ * running, a {@code BundleException} must be thrown.</li>
+ * <li>This bundle's state is set to {@code RESOLVED}.</li>
+ * <li>A bundle event of type {@link BundleEvent#STOPPED} is fired.</li>
* </ol>
*
* <b>Preconditions </b>
* <ul>
- * <li>{@code getState()} in { {@code ACTIVE} }.
+ * <li>{@code getState()} in { {@code ACTIVE} }.</li>
* </ul>
* <b>Postconditions, no exceptions thrown </b>
* <ul>
* <li>Bundle autostart setting is modified unless the
- * {@link #STOP_TRANSIENT} option was set.
+ * {@link #STOP_TRANSIENT} option was set.</li>
* <li>{@code getState()} not in { {@code ACTIVE}, {@code STOPPING}
- * }.
+ * }.</li>
* <li>{@code BundleActivator.stop} has been called and did not throw an
- * exception.
+ * exception.</li>
* </ul>
* <b>Postconditions, when an exception is thrown </b>
* <ul>
* <li>Bundle autostart setting is modified unless the
- * {@link #STOP_TRANSIENT} option was set.
+ * {@link #STOP_TRANSIENT} option was set.</li>
* </ul>
*
* @param options The options for stopping this bundle. See
@@ -520,45 +500,40 @@ public interface Bundle extends Comparable<Bundle> {
* The following steps are required to update a bundle:
* <ol>
* <li>If this bundle's state is {@code UNINSTALLED} then an
- * {@code IllegalStateException} is thrown.
- *
+ * {@code IllegalStateException} is thrown.</li>
* <li>If this bundle's state is {@code ACTIVE}, {@code STARTING} or
* {@code STOPPING}, this bundle is stopped as described in the
* {@code Bundle.stop} method. If {@code Bundle.stop} throws an exception,
- * the exception is rethrown terminating the update.
- *
+ * the exception is rethrown terminating the update.</li>
* <li>The updated version of this bundle is read from the input stream and
* installed. If the Framework is unable to install the updated version of
* this bundle, the original version of this bundle must be restored and a
* {@code BundleException} must be thrown after completion of the remaining
- * steps.
- *
- * <li>This bundle's state is set to {@code INSTALLED}.
- *
+ * steps.</li>
+ * <li>This bundle's state is set to {@code INSTALLED}.</li>
* <li>If the updated version of this bundle was successfully installed, a
- * bundle event of type {@link BundleEvent#UPDATED} is fired.
- *
+ * bundle event of type {@link BundleEvent#UPDATED} is fired.</li>
* <li>If this bundle's state was originally {@code ACTIVE}, the updated
* bundle is started as described in the {@code Bundle.start} method. If
* {@code Bundle.start} throws an exception, a Framework event of type
- * {@link FrameworkEvent#ERROR} is fired containing the exception.
+ * {@link FrameworkEvent#ERROR} is fired containing the exception.</li>
* </ol>
*
* <b>Preconditions </b>
* <ul>
- * <li>{@code getState()} not in { {@code UNINSTALLED} }.
+ * <li>{@code getState()} not in { {@code UNINSTALLED} }.</li>
* </ul>
* <b>Postconditions, no exceptions thrown </b>
* <ul>
* <li>{@code getState()} in { {@code INSTALLED}, {@code RESOLVED},
- * {@code ACTIVE} }.
- * <li>This bundle has been updated.
+ * {@code ACTIVE} }.</li>
+ * <li>This bundle has been updated.</li>
* </ul>
* <b>Postconditions, when an exception is thrown </b>
* <ul>
* <li>{@code getState()} in { {@code INSTALLED}, {@code RESOLVED},
- * {@code ACTIVE} }.
- * <li>Original bundle is still used; no update occurred.
+ * {@code ACTIVE} }.</li>
+ * <li>Original bundle is still used; no update occurred.</li>
* </ul>
*
* @param input The {@code InputStream} from which to read the new bundle or
@@ -633,35 +608,31 @@ public interface Bundle extends Comparable<Bundle> {
* The following steps are required to uninstall a bundle:
* <ol>
* <li>If this bundle's state is {@code UNINSTALLED} then an
- * {@code IllegalStateException} is thrown.
- *
+ * {@code IllegalStateException} is thrown.</li>
* <li>If this bundle's state is {@code ACTIVE}, {@code STARTING} or
* {@code STOPPING}, this bundle is stopped as described in the
* {@code Bundle.stop} method. If {@code Bundle.stop} throws an exception, a
* Framework event of type {@link FrameworkEvent#ERROR} is fired containing
- * the exception.
- *
- * <li>This bundle's state is set to {@code UNINSTALLED}.
- *
- * <li>A bundle event of type {@link BundleEvent#UNINSTALLED} is fired.
- *
+ * the exception.</li>
+ * <li>This bundle's state is set to {@code UNINSTALLED}.</li>
+ * <li>A bundle event of type {@link BundleEvent#UNINSTALLED} is fired.</li>
* <li>This bundle and any persistent storage area provided for this bundle
- * by the Framework are removed.
+ * by the Framework are removed.</li>
* </ol>
*
* <b>Preconditions </b>
* <ul>
- * <li>{@code getState()} not in { {@code UNINSTALLED} }.
+ * <li>{@code getState()} not in { {@code UNINSTALLED} }.</li>
* </ul>
* <b>Postconditions, no exceptions thrown </b>
* <ul>
- * <li>{@code getState()} in { {@code UNINSTALLED} }.
- * <li>This bundle has been uninstalled.
+ * <li>{@code getState()} in { {@code UNINSTALLED} }.</li>
+ * <li>This bundle has been uninstalled.</li>
* </ul>
* <b>Postconditions, when an exception is thrown </b>
* <ul>
- * <li>{@code getState()} not in { {@code UNINSTALLED} }.
- * <li>This Bundle has not been uninstalled.
+ * <li>{@code getState()} not in { {@code UNINSTALLED} }.</li>
+ * <li>This Bundle has not been uninstalled.</li>
* </ul>
*
* @throws BundleException If the uninstall failed. This can occur if
@@ -727,12 +698,12 @@ public interface Bundle extends Comparable<Bundle> {
* <p>
* A bundle's unique identifier has the following attributes:
* <ul>
- * <li>Is unique and persistent.
- * <li>Is a {@code long}.
+ * <li>Is unique and persistent.</li>
+ * <li>Is a {@code long}.</li>
* <li>Its value is not reused for another bundle, even after a bundle is
- * uninstalled.
- * <li>Does not change while a bundle remains installed.
- * <li>Does not change when a bundle is updated.
+ * uninstalled.</li>
+ * <li>Does not change while a bundle remains installed.</li>
+ * <li>Does not change when a bundle is updated.</li>
* </ul>
*
* <p>
@@ -789,8 +760,8 @@ public interface Bundle extends Comparable<Bundle> {
/**
* Returns this bundle's {@code ServiceReference} list for all services it
* is using or returns {@code null} if this bundle is not using any
- * services. A bundle is considered to be using a service if its use count
- * for that service is greater than zero.
+ * services. A bundle is considered to be using a service if it has any
+ * unreleased service objects.
*
* <p>
* If the Java Runtime Environment supports permissions, a
diff --git a/src/main/java/org/osgi/framework/BundleActivator.java b/src/main/java/org/osgi/framework/BundleActivator.java
index acdb825..ab80909 100644
--- a/src/main/java/org/osgi/framework/BundleActivator.java
+++ b/src/main/java/org/osgi/framework/BundleActivator.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.
@@ -16,6 +16,8 @@
package org.osgi.framework;
+import org.osgi.annotation.versioning.ConsumerType;
+
/**
* Customizes the starting and stopping of a bundle.
* <p>
@@ -34,19 +36,19 @@ package org.osgi.framework;
* {@code BundleActivator}. The form of the Manifest header is:
*
* <p>
- * {@code Bundle-Activator: <i>class-name</i>}
+ * {@code Bundle-Activator:} <i>class-name</i>
*
* <p>
- * where {@code <i>class-name</i>} is a fully qualified Java classname.
+ * where <i>class-name</i> is a fully qualified Java classname.
* <p>
* The specified {@code BundleActivator} class must have a public constructor
* that takes no parameters so that a {@code BundleActivator} object can be
* created by {@code Class.newInstance()}.
*
* @NotThreadSafe
- * @version $Id: f5b2debe0064ab60669102d0a087feaeab13dc0e $
+ * @author $Id: a9d91a8ae13157f49a6a55b0c7f25b63b6bd00bd $
*/
-
+ at ConsumerType
public interface BundleActivator {
/**
* Called when this bundle is started so the Framework can perform the
diff --git a/src/main/java/org/osgi/framework/BundleContext.java b/src/main/java/org/osgi/framework/BundleContext.java
index 71c3b92..600f548 100644
--- a/src/main/java/org/osgi/framework/BundleContext.java
+++ b/src/main/java/org/osgi/framework/BundleContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2000, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2014). 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.io.File;
import java.io.InputStream;
import java.util.Collection;
import java.util.Dictionary;
+import org.osgi.annotation.versioning.ProviderType;
/**
* A bundle's execution context within the Framework. The context is used to
@@ -29,15 +30,15 @@ import java.util.Dictionary;
* <p>
* {@code BundleContext} methods allow a bundle to:
* <ul>
- * <li>Subscribe to events published by the Framework.
- * <li>Register service objects with the Framework service registry.
- * <li>Retrieve {@code ServiceReferences} from the Framework service registry.
- * <li>Get and release service objects for a referenced service.
- * <li>Install new bundles in the Framework.
- * <li>Get the list of bundles installed in the Framework.
- * <li>Get the {@link Bundle} object for a bundle.
+ * <li>Subscribe to events published by the Framework.</li>
+ * <li>Register service objects with the Framework service registry.</li>
+ * <li>Retrieve {@code ServiceReferences} from the Framework service registry.</li>
+ * <li>Get and release service objects for a referenced service.</li>
+ * <li>Install new bundles in the Framework.</li>
+ * <li>Get the list of bundles installed in the Framework.</li>
+ * <li>Get the {@link Bundle} object for a bundle.</li>
* <li>Create {@code File} objects for files in a persistent storage area
- * provided for the bundle by the Framework.
+ * provided for the bundle by the Framework.</li>
* </ul>
*
* <p>
@@ -57,8 +58,17 @@ import java.util.Dictionary;
* <p>
* The {@code BundleContext} object is only valid during the execution of its
* context bundle; that is, during the period from when the context bundle is in
- * the {@code STARTING}, {@code STOPPING}, and {@code ACTIVE} bundle states. If
- * the {@code BundleContext} object is used subsequently, an
+ * the {@code STARTING}, {@code STOPPING}, and {@code ACTIVE} bundle states.
+ * However, the {@code BundleContext} object becomes invalid after
+ * {@link BundleActivator#stop(BundleContext)} returns (if the bundle has a
+ * Bundle Activator). The {@code BundleContext} object becomes invalid before
+ * disposing of any remaining registered services and releasing any remaining
+ * services in use. Since those activities can result in other bundles being
+ * called (for example, {@link ServiceListener}s for
+ * {@link ServiceEvent#UNREGISTERING} events and {@link ServiceFactory}s for
+ * unget operations), those other bundles can observe the stopping bundle in the
+ * {@code STOPPING} state but with an invalid {@code BundleContext} object. If
+ * the {@code BundleContext} object is used after it has become invalid, an
* {@code IllegalStateException} must be thrown. The {@code BundleContext}
* object must never be reused after its context bundle is stopped.
*
@@ -75,10 +85,9 @@ import java.util.Dictionary;
* Environment supports permissions.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: 4f166fd274f3965e48a7dbc239213d00e062b6d0 $
+ * @author $Id: fbf0b18296a0b85d628ee8c47d0f0f213a914e48 $
*/
-
+ at ProviderType
public interface BundleContext extends BundleReference {
/**
@@ -127,29 +136,24 @@ public interface BundleContext extends BundleReference {
* The following steps are required to install a bundle:
* <ol>
* <li>If a bundle containing the same location identifier is already
- * installed, the {@code Bundle} object for that bundle is returned.
- *
+ * installed, the {@code Bundle} object for that bundle is returned.</li>
* <li>The bundle's content is read from the input stream. If this fails, a
- * {@link BundleException} is thrown.
- *
+ * {@link BundleException} is thrown.</li>
* <li>The bundle's associated resources are allocated. The associated
* resources minimally consist of a unique identifier and a persistent
* storage area if the platform has file system support. If this step fails,
- * a {@code BundleException} is thrown.
- *
- * <li>The bundle's state is set to {@code INSTALLED}.
- *
- * <li>A bundle event of type {@link BundleEvent#INSTALLED} is fired.
- *
+ * a {@code BundleException} is thrown.</li>
+ * <li>The bundle's state is set to {@code INSTALLED}.</li>
+ * <li>A bundle event of type {@link BundleEvent#INSTALLED} is fired.</li>
* <li>The {@code Bundle} object for the newly or previously installed
- * bundle is returned.
+ * bundle is returned.</li>
* </ol>
*
* <b>Postconditions, no exceptions thrown </b>
* <ul>
* <li>{@code getState()} in { {@code INSTALLED}, {@code RESOLVED}
- * }.
- * <li>Bundle has a unique ID.
+ * }.</li>
+ * <li>Bundle has a unique ID.</li>
* </ul>
* <b>Postconditions, when an exception is thrown </b>
* <ul>
@@ -386,29 +390,36 @@ public interface BundleContext extends BundleReference {
* <p>
* The following steps are required to register a service:
* <ol>
- * <li>If {@code service} is not a {@code ServiceFactory}, an
+ * <li>If {@code service} does not implement {@code ServiceFactory}, an
* {@code IllegalArgumentException} is thrown if {@code service} is not an
- * {@code instanceof} all the specified class names.
+ * {@code instanceof} all the specified class names.</li>
* <li>The Framework adds the following service properties to the service
* properties from the specified {@code Dictionary} (which may be
- * {@code null}): <br/>
- * A property named {@link Constants#SERVICE_ID} identifying the
- * registration number of the service <br/>
- * A property named {@link Constants#OBJECTCLASS} containing all the
- * specified classes. <br/>
+ * {@code null}):
+ * <ul>
+ * <li>A property named {@link Constants#SERVICE_ID} identifying the
+ * registration number of the service</li>
+ * <li>A property named {@link Constants#OBJECTCLASS} containing all the
+ * specified classes.</li>
+ * <li>A property named {@link Constants#SERVICE_SCOPE} identifying the
+ * scope of the service.</li>
+ * <li>A property named {@link Constants#SERVICE_BUNDLEID} identifying the
+ * the context bundle.</li>
+ * </ul>
* Properties with these names in the specified {@code Dictionary} will be
- * ignored.
+ * ignored.</li>
* <li>The service is added to the Framework service registry and may now be
- * used by other bundles.
- * <li>A service event of type {@link ServiceEvent#REGISTERED} is fired.
+ * used by other bundles.</li>
+ * <li>A service event of type {@link ServiceEvent#REGISTERED} is fired.</li>
* <li>A {@code ServiceRegistration} object for this registration is
- * returned.
+ * returned.</li>
* </ol>
*
* @param clazzes The class names under which the service can be located.
* The class names in this array will be stored in the service's
* properties under the key {@link Constants#OBJECTCLASS}.
- * @param service The service object or a {@code ServiceFactory} object.
+ * @param service The service object or an object implementing
+ * {@code ServiceFactory}.
* @param properties The properties for this service. The keys in the
* properties object must all be {@code String} objects. See
* {@link Constants} for a list of standard service property keys.
@@ -422,10 +433,10 @@ public interface BundleContext extends BundleReference {
* unregister the service.
* @throws IllegalArgumentException If one of the following is true:
* <ul>
- * <li>{@code service} is {@code null}. <li>{@code service} is not a
- * {@code ServiceFactory} object and is not an instance of all the
- * named classes in {@code clazzes}. <li> {@code properties}
- * contains case variants of the same key name.
+ * <li>{@code service} is {@code null}.</li><li>{@code service} does
+ * not implement {@code ServiceFactory} and is not an instance of
+ * all the specified classes.</li><li> {@code properties} contains
+ * case variants of the same key name.</li>
* </ul>
* @throws SecurityException If the caller does not have the
* {@code ServicePermission} to register the service for all the
@@ -433,6 +444,7 @@ public interface BundleContext extends BundleReference {
* permissions.
* @throws IllegalStateException If this BundleContext is no longer valid.
* @see ServiceRegistration
+ * @see PrototypeServiceFactory
* @see ServiceFactory
*/
ServiceRegistration<?> registerService(String[] clazzes, Object service, Dictionary<String, ?> properties);
@@ -450,7 +462,8 @@ public interface BundleContext extends BundleReference {
* than just a single string.
*
* @param clazz The class name under which the service can be located.
- * @param service The service object or a {@code ServiceFactory} object.
+ * @param service The service object or an object implementing
+ * {@code ServiceFactory}.
* @param properties The properties for this service.
* @return A {@code ServiceRegistration} object for use by the bundle
* registering the service to update the service's properties or to
@@ -471,7 +484,8 @@ public interface BundleContext extends BundleReference {
*
* @param <S> Type of Service.
* @param clazz The class under whose name the service can be located.
- * @param service The service object or a {@code ServiceFactory} object.
+ * @param service The service object or an object implementing
+ * {@code ServiceFactory}.
* @param properties The properties for this service.
* @return A {@code ServiceRegistration} object for use by the bundle
* registering the service to update the service's properties or to
@@ -483,6 +497,29 @@ public interface BundleContext extends BundleReference {
<S> ServiceRegistration<S> registerService(Class<S> clazz, S service, Dictionary<String, ?> properties);
/**
+ * Registers the specified service factory object with the specified
+ * properties under the name of the specified class with the Framework.
+ *
+ * <p>
+ * This method is otherwise identical to
+ * {@link #registerService(Class, Object, Dictionary)} and is provided to
+ * return a type safe {@code ServiceRegistration} when registering a
+ * {@link ServiceFactory}.
+ *
+ * @param <S> Type of Service.
+ * @param clazz The class under whose name the service can be located.
+ * @param factory The {@code ServiceFactory} object.
+ * @param properties The properties for this service.
+ * @return A {@code ServiceRegistration} object for use by the bundle
+ * registering the service to update the service's properties or to
+ * unregister the service.
+ * @throws IllegalStateException If this BundleContext is no longer valid.
+ * @see #registerService(Class, Object, Dictionary)
+ * @since 1.8
+ */
+ <S> ServiceRegistration<S> registerService(Class<S> clazz, ServiceFactory<S> factory, Dictionary<String, ?> properties);
+
+ /**
* Returns an array of {@code ServiceReference} objects. The returned array
* of {@code ServiceReference} objects contains services that were
* registered under the specified class, match the specified filter
@@ -513,16 +550,16 @@ public interface BundleContext extends BundleReference {
* service must have been registered with the specified class name. The
* complete list of class names with which a service was registered is
* available from the service's {@link Constants#OBJECTCLASS objectClass}
- * property.
+ * property.</li>
* <li>If the specified {@code filter} is not {@code null}, the filter
- * expression must match the service.
+ * expression must match the service.</li>
* <li>If the Java Runtime Environment supports permissions, the caller must
* have {@code ServicePermission} with the {@code GET} action for at least
- * one of the class names under which the service was registered.
+ * one of the class names under which the service was registered.</li>
* <li>For each class name with which the service was registered, calling
* {@link ServiceReference#isAssignableTo(Bundle, String)} with the context
* bundle and the class name on the service's {@code ServiceReference}
- * object must return {@code true}
+ * object must return {@code true}</li>
* </ul>
*
* @param clazz The class name with which the service was registered or
@@ -565,12 +602,12 @@ public interface BundleContext extends BundleReference {
* service must have been registered with the specified class name. The
* complete list of class names with which a service was registered is
* available from the service's {@link Constants#OBJECTCLASS objectClass}
- * property.
+ * property.</li>
* <li>If the specified {@code filter} is not {@code null}, the filter
- * expression must match the service.
+ * expression must match the service.</li>
* <li>If the Java Runtime Environment supports permissions, the caller must
* have {@code ServicePermission} with the {@code GET} action for at least
- * one of the class names under which the service was registered.
+ * one of the class names under which the service was registered.</li>
* </ul>
*
* @param clazz The class name with which the service was registered or
@@ -606,7 +643,7 @@ public interface BundleContext extends BundleReference {
* highest ranking (as specified in its {@link Constants#SERVICE_RANKING}
* property) is returned.
* <p>
- * If there is a tie in ranking, the service with the lowest service ID (as
+ * If there is a tie in ranking, the service with the lowest service id (as
* specified in its {@link Constants#SERVICE_ID} property); that is, the
* service that was registered first is returned.
*
@@ -636,7 +673,7 @@ public interface BundleContext extends BundleReference {
* If multiple such services exist, the service with the highest ranking (as
* specified in its {@link Constants#SERVICE_RANKING} property) is returned.
* <p>
- * If there is a tie in ranking, the service with the lowest service ID (as
+ * If there is a tie in ranking, the service with the lowest service id (as
* specified in its {@link Constants#SERVICE_ID} property); that is, the
* service that was registered first is returned.
*
@@ -681,16 +718,16 @@ public interface BundleContext extends BundleReference {
* <li>The service must have been registered with the name of the specified
* class. The complete list of class names with which a service was
* registered is available from the service's {@link Constants#OBJECTCLASS
- * objectClass} property.
+ * objectClass} property.</li>
* <li>If the specified {@code filter} is not {@code null}, the filter
- * expression must match the service.
+ * expression must match the service.</li>
* <li>If the Java Runtime Environment supports permissions, the caller must
* have {@code ServicePermission} with the {@code GET} action for at least
- * one of the class names under which the service was registered.
+ * one of the class names under which the service was registered.</li>
* <li>For each class name with which the service was registered, calling
* {@link ServiceReference#isAssignableTo(Bundle, String)} with the context
* bundle and the class name on the service's {@code ServiceReference}
- * object must return {@code true}
+ * object must return {@code true}</li>
* </ul>
*
* @param <S> Type of Service
@@ -707,45 +744,47 @@ public interface BundleContext extends BundleReference {
<S> Collection<ServiceReference<S>> getServiceReferences(Class<S> clazz, String filter) throws InvalidSyntaxException;
/**
- * Returns the service object referenced by the specified
+ * Returns the service object for the service referenced by the specified
* {@code ServiceReference} object.
+ *
* <p>
- * A bundle's use of a service is tracked by the bundle's use count of that
- * service. Each time a service's service object is returned by
- * {@link #getService(ServiceReference)} the context bundle's use count for
- * that service is incremented by one. Each time the service is released by
- * {@link #ungetService(ServiceReference)} the context bundle's use count
- * for that service is decremented by one.
+ * A bundle's use of a service object obtained from this method is tracked
+ * by the bundle's use count of that service. Each time the service object
+ * is returned by {@link #getService(ServiceReference)} the context bundle's
+ * use count for the service is incremented by one. Each time the service
+ * object is released by {@link #ungetService(ServiceReference)} the context
+ * bundle's use count for the service is decremented by one.
+ *
* <p>
- * When a bundle's use count for a service drops to zero, the bundle should
- * no longer use that service.
+ * When a bundle's use count for the service drops to zero, the bundle
+ * should no longer use the service object.
*
* <p>
* This method will always return {@code null} when the service associated
- * with this {@code reference} has been unregistered.
+ * with the specified {@code reference} has been unregistered.
*
* <p>
* The following steps are required to get the service object:
* <ol>
- * <li>If the service has been unregistered, {@code null} is returned.
+ * <li>If the service has been unregistered, {@code null} is returned.</li>
* <li>If the context bundle's use count for the service is currently zero
- * and the service was registered with an object implementing the
- * {@code ServiceFactory} interface, the
+ * and the service has {@link Constants#SCOPE_BUNDLE bundle} or
+ * {@link Constants#SCOPE_PROTOTYPE prototype} scope, the
* {@link ServiceFactory#getService(Bundle, ServiceRegistration)} method is
- * called to create a service object for the context bundle. If the service
- * object returned by the {@code ServiceFactory} object is {@code null}, not
- * an {@code instanceof} all the classes named when the service was
- * registered or the {@code ServiceFactory} object throws an exception or
- * will be recursively called for the context bundle, {@code null} is
- * returned and a Framework event of type {@link FrameworkEvent#ERROR}
- * containing a {@link ServiceException} describing the error is fired. <br>
- * This service object is cached by the Framework. While the context
- * bundle's use count for the service is greater than zero, subsequent calls
- * to get the services's service object for the context bundle will return
- * the cached service object.
- * <li>The context bundle's use count for this service is incremented by
- * one.
- * <li>The service object for the service is returned.
+ * called to supply the service object for the context bundle. If the
+ * service object returned by the {@code ServiceFactory} object is
+ * {@code null}, not an {@code instanceof} all the classes named when the
+ * service was registered or the {@code ServiceFactory} object throws an
+ * exception or will be recursively called for the context bundle,
+ * {@code null} is returned and a Framework event of type
+ * {@link FrameworkEvent#ERROR} containing a {@link ServiceException}
+ * describing the error is fired. The supplied service object is cached by
+ * the Framework. While the context bundle's use count for the service is
+ * greater than zero, subsequent calls to get the service object for the
+ * context bundle will return the cached service object.</li>
+ * <li>The context bundle's use count for the service is incremented by one.
+ * </li>
+ * <li>The service object for the service is returned.</li>
* </ol>
*
* @param <S> Type of Service.
@@ -770,28 +809,28 @@ public interface BundleContext extends BundleReference {
<S> S getService(ServiceReference<S> reference);
/**
- * Releases the service object referenced by the specified
+ * Releases the service object for the service referenced by the specified
* {@code ServiceReference} object. If the context bundle's use count for
* the service is zero, this method returns {@code false}. Otherwise, the
* context bundle's use count for the service is decremented by one.
*
* <p>
- * The service's service object should no longer be used and all references
- * to it should be destroyed when a bundle's use count for the service drops
- * to zero.
+ * The service object must no longer be used and all references to it should
+ * be destroyed when a bundle's use count for the service drops to zero.
*
* <p>
- * The following steps are required to unget the service object:
+ * The following steps are required to release the service object:
* <ol>
* <li>If the context bundle's use count for the service is zero or the
- * service has been unregistered, {@code false} is returned.
- * <li>The context bundle's use count for this service is decremented by
- * one.
- * <li>If the context bundle's use count for the service is currently zero
- * and the service was registered with a {@code ServiceFactory} object, the
+ * service has been unregistered, {@code false} is returned.</li>
+ * <li>The context bundle's use count for the service is decremented by one.
+ * </li>
+ * <li>If the context bundle's use count for the service is now zero and the
+ * service has {@link Constants#SCOPE_BUNDLE bundle} or
+ * {@link Constants#SCOPE_PROTOTYPE prototype} scope, the
* {@link ServiceFactory#ungetService(Bundle, ServiceRegistration, Object)}
- * method is called to release the service object for the context bundle.
- * <li>{@code true} is returned.
+ * method is called to release the service object for the context bundle.</li>
+ * <li>{@code true} is returned.</li>
* </ol>
*
* @param reference A reference to the service to be released.
@@ -808,6 +847,47 @@ public interface BundleContext extends BundleReference {
boolean ungetService(ServiceReference<?> reference);
/**
+ * Returns the {@link ServiceObjects} object for the service referenced by
+ * the specified {@code ServiceReference} object.
+ *
+ * <p>
+ * The {@link ServiceObjects} object can be used to obtain multiple service
+ * objects for services with {@link Constants#SCOPE_PROTOTYPE prototype}
+ * scope.
+ *
+ * <p>
+ * For services with {@link Constants#SCOPE_SINGLETON singleton} or
+ * {@link Constants#SCOPE_BUNDLE bundle} scope, the
+ * {@link ServiceObjects#getService()} method behaves the same as the
+ * {@link #getService(ServiceReference)} method and the
+ * {@link ServiceObjects#ungetService(Object)} method behaves the same as
+ * the {@link #ungetService(ServiceReference)} method. That is, only one,
+ * use-counted service object is available from the {@link ServiceObjects}
+ * object.
+ *
+ * <p>
+ * This method will always return {@code null} when the service associated
+ * with the specified {@code reference} has been unregistered.
+ *
+ * @param <S> Type of Service.
+ * @param reference A reference to the service.
+ * @return A {@link ServiceObjects} object for the service associated with
+ * the specified {@code reference} or {@code null} if the service is
+ * not registered.
+ * @throws SecurityException If the caller does not have the
+ * {@code ServicePermission} to get the service using at least one
+ * of the named classes the service was registered under and the
+ * Java Runtime Environment supports permissions.
+ * @throws IllegalStateException If this BundleContext is no longer valid.
+ * @throws IllegalArgumentException If the specified
+ * {@code ServiceReference} was not created by the same framework
+ * instance as this {@code BundleContext}.
+ * @see PrototypeServiceFactory
+ * @since 1.8
+ */
+ <S> ServiceObjects<S> getServiceObjects(ServiceReference<S> reference);
+
+ /**
* Creates a {@code File} object for a file in the persistent storage area
* provided for the bundle by the Framework. This method will return
* {@code null} if the platform does not have file system support.
diff --git a/src/main/java/org/osgi/framework/BundleEvent.java b/src/main/java/org/osgi/framework/BundleEvent.java
index 04a34a3..5bc8614 100644
--- a/src/main/java/org/osgi/framework/BundleEvent.java
+++ b/src/main/java/org/osgi/framework/BundleEvent.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.
@@ -32,7 +32,7 @@ import java.util.EventObject;
* @Immutable
* @see BundleListener
* @see SynchronousBundleListener
- * @version $Id: 9e2102212eb526b5f11fdde4b0fc5c171a0b39c8 $
+ * @author $Id: cd49848213816c4f76541b70be12ac3af7900972 $
*/
public class BundleEvent extends EventObject {
@@ -201,16 +201,16 @@ public class BundleEvent extends EventObject {
/**
* Returns the type of lifecyle event. The type values are:
* <ul>
- * <li>{@link #INSTALLED}
- * <li>{@link #RESOLVED}
- * <li>{@link #LAZY_ACTIVATION}
- * <li>{@link #STARTING}
- * <li>{@link #STARTED}
- * <li>{@link #STOPPING}
- * <li>{@link #STOPPED}
- * <li>{@link #UPDATED}
- * <li>{@link #UNRESOLVED}
- * <li>{@link #UNINSTALLED}
+ * <li>{@link #INSTALLED}</li>
+ * <li>{@link #RESOLVED}</li>
+ * <li>{@link #LAZY_ACTIVATION}</li>
+ * <li>{@link #STARTING}</li>
+ * <li>{@link #STARTED}</li>
+ * <li>{@link #STOPPING}</li>
+ * <li>{@link #STOPPED}</li>
+ * <li>{@link #UPDATED}</li>
+ * <li>{@link #UNRESOLVED}</li>
+ * <li>{@link #UNINSTALLED}</li>
* </ul>
*
* @return The type of lifecycle event.
diff --git a/src/main/java/org/osgi/framework/BundleException.java b/src/main/java/org/osgi/framework/BundleException.java
index c47eb77..dfed442 100644
--- a/src/main/java/org/osgi/framework/BundleException.java
+++ b/src/main/java/org/osgi/framework/BundleException.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.
@@ -32,7 +32,7 @@ package org.osgi.framework;
* <p>
* This exception conforms to the general purpose exception chaining mechanism.
*
- * @version $Id: 0c97ed2696b4576d61440020922b1a97545beb1e $
+ * @author $Id: a0d23c4cb73b0d6386bcd6b9eebed29fdd9a4deb $
*/
public class BundleException extends Exception {
@@ -203,6 +203,7 @@ public class BundleException extends Exception {
* @return The cause of this exception or {@code null} if no cause was set.
* @since 1.3
*/
+ @Override
public Throwable getCause() {
return super.getCause();
}
@@ -218,6 +219,7 @@ public class BundleException extends Exception {
* been set.
* @since 1.3
*/
+ @Override
public Throwable initCause(Throwable cause) {
return super.initCause(cause);
}
diff --git a/src/main/java/org/osgi/framework/BundleListener.java b/src/main/java/org/osgi/framework/BundleListener.java
index 8d86d30..c177187 100644
--- a/src/main/java/org/osgi/framework/BundleListener.java
+++ b/src/main/java/org/osgi/framework/BundleListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2000, 2011). 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.
@@ -17,6 +17,7 @@
package org.osgi.framework;
import java.util.EventListener;
+import org.osgi.annotation.versioning.ConsumerType;
/**
* A {@code BundleEvent} listener. {@code BundleListener} is a listener
@@ -34,9 +35,9 @@ import java.util.EventListener;
*
* @see BundleEvent
* @NotThreadSafe
- * @version $Id: d48b4a8a59c839466a3d749dde23980d236f58c6 $
+ * @author $Id: 2c27d37a3a77e1c80f9b022f8dc2f614dff5f5ef $
*/
-
+ at ConsumerType
public interface BundleListener extends EventListener {
/**
* Receives notification that a bundle has had a lifecycle change.
diff --git a/src/main/java/org/osgi/framework/BundlePermission.java b/src/main/java/org/osgi/framework/BundlePermission.java
index f9e64ae..08c28cd 100644
--- a/src/main/java/org/osgi/framework/BundlePermission.java
+++ b/src/main/java/org/osgi/framework/BundlePermission.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2004, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2004, 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.
@@ -58,7 +58,7 @@ import java.util.Map;
*
* @since 1.3
* @ThreadSafe
- * @version $Id: ccba905e3373800dfdb080118e97145abf778da2 $
+ * @author $Id: 5d3a115a2622919f564e2a2f46d70090ad9859cb $
*/
public final class BundlePermission extends BasicPermission {
@@ -287,6 +287,7 @@ public final class BundlePermission extends BasicPermission {
* @return {@code true} if the specified {@code BundlePermission} action is
* implied by this object; {@code false} otherwise.
*/
+ @Override
public boolean implies(Permission p) {
if (!(p instanceof BundlePermission)) {
return false;
@@ -309,6 +310,7 @@ public final class BundlePermission extends BasicPermission {
* @return Canonical string representation of the {@code BundlePermission
* } actions.
*/
+ @Override
public String getActions() {
String result = actions;
if (result == null) {
@@ -351,6 +353,7 @@ public final class BundlePermission extends BasicPermission {
*
* @return A new {@code PermissionCollection} object.
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new BundlePermissionCollection();
}
@@ -368,6 +371,7 @@ public final class BundlePermission extends BasicPermission {
* has the same bundle symbolic name and actions as this
* {@code BundlePermission} object; {@code false} otherwise.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -387,6 +391,7 @@ public final class BundlePermission extends BasicPermission {
*
* @return A hash code value for this object.
*/
+ @Override
public int hashCode() {
int h = 31 * 17 + getName().hashCode();
h = 31 * h + getActions().hashCode();
@@ -461,6 +466,7 @@ final class BundlePermissionCollection extends PermissionCollection {
* @throws SecurityException If this {@code BundlePermissionCollection}
* object has been marked read-only.
*/
+ @Override
public void add(final Permission permission) {
if (!(permission instanceof BundlePermission)) {
throw new IllegalArgumentException("invalid permission: " + permission);
@@ -500,6 +506,7 @@ final class BundlePermissionCollection extends PermissionCollection {
* @return {@code true} if {@code permission} is a proper subset of a
* permission in the set; {@code false} otherwise.
*/
+ @Override
public boolean implies(final Permission permission) {
if (!(permission instanceof BundlePermission)) {
return false;
@@ -559,6 +566,7 @@ final class BundlePermissionCollection extends PermissionCollection {
*
* @return Enumeration of all {@code BundlePermission} objects.
*/
+ @Override
public synchronized Enumeration<Permission> elements() {
List<Permission> all = new ArrayList<Permission>(permissions.values());
return Collections.enumeration(all);
@@ -577,6 +585,7 @@ final class BundlePermissionCollection extends PermissionCollection {
private synchronized void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gfields = in.readFields();
+ @SuppressWarnings("unchecked")
Hashtable<String, BundlePermission> hashtable = (Hashtable<String, BundlePermission>) gfields.get("permissions", null);
permissions = new HashMap<String, BundlePermission>(hashtable);
all_allowed = gfields.get("all_allowed", false);
diff --git a/src/main/java/org/osgi/framework/BundleReference.java b/src/main/java/org/osgi/framework/BundleReference.java
index 97340f7..8cd2df5 100644
--- a/src/main/java/org/osgi/framework/BundleReference.java
+++ b/src/main/java/org/osgi/framework/BundleReference.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2009, 2010). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2009, 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.
@@ -16,14 +16,16 @@
package org.osgi.framework;
+import org.osgi.annotation.versioning.ProviderType;
+
/**
* A reference to a Bundle.
*
* @since 1.5
* @ThreadSafe
- * @noimplement
- * @version $Id: e61bd3e020264b04022a430fe09a85ee3aabf1a3 $
+ * @author $Id: ad4e0b99177540205a1a8f37f9075989434cc59f $
*/
+ at ProviderType
public interface BundleReference {
/**
* Returns the {@code Bundle} object associated with this
diff --git a/src/main/java/org/osgi/framework/CapabilityPermission.java b/src/main/java/org/osgi/framework/CapabilityPermission.java
index c27e1ac..56b1eb5 100644
--- a/src/main/java/org/osgi/framework/CapabilityPermission.java
+++ b/src/main/java/org/osgi/framework/CapabilityPermission.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.
@@ -41,13 +41,13 @@ import java.util.Set;
* A bundle's authority to provide or require a capability.
* <ul>
* <li>The {@code provide} action allows a bundle to provide a capability
- * matching the specified filter.
+ * matching the specified filter.</li>
* <li>The {@code require} action allows a bundle to require a capability
- * matching the specified filter.
+ * matching the specified filter.</li>
* </ul>
*
* @ThreadSafe
- * @version $Id: b17bcaec959f67c3eae4c4c80c39a0a8716b22dc $
+ * @author $Id: 1d8e892cf46d7410cd3fdff1f5ca2fb010a33ae6 $
* @since 1.6
*/
@@ -334,6 +334,7 @@ public final class CapabilityPermission extends BasicPermission {
* @return {@code true} if the specified permission is implied by this
* object; {@code false} otherwise.
*/
+ @Override
public boolean implies(Permission p) {
if (!(p instanceof CapabilityPermission)) {
return false;
@@ -382,6 +383,7 @@ public final class CapabilityPermission extends BasicPermission {
*
* @return The canonical string representation of the actions.
*/
+ @Override
public String getActions() {
String result = actions;
if (result == null) {
@@ -413,6 +415,7 @@ public final class CapabilityPermission extends BasicPermission {
* @return A new {@code PermissionCollection} object suitable for storing
* {@code CapabilityPermission} objects.
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new CapabilityPermissionCollection();
}
@@ -428,6 +431,7 @@ public final class CapabilityPermission extends BasicPermission {
* name and actions as this {@code CapabilityPermission} object;
* {@code false} otherwise.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -448,6 +452,7 @@ public final class CapabilityPermission extends BasicPermission {
*
* @return Hash code value for this object.
*/
+ @Override
public int hashCode() {
int h = 31 * 17 + getName().hashCode();
h = 31 * h + getActions().hashCode();
@@ -486,9 +491,8 @@ public final class CapabilityPermission extends BasicPermission {
}
/**
- * Called by {@code <@link CapabilityPermission#implies(Permission)>}. This
- * method is only called on a requested permission which cannot have a
- * filter set.
+ * Called by {@link CapabilityPermission#implies(Permission)}. This method
+ * is only called on a requested permission which cannot have a filter set.
*
* @return a map of properties for this permission.
*/
@@ -502,8 +506,8 @@ public final class CapabilityPermission extends BasicPermission {
if (bundle == null) {
return properties = props;
}
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
props.put("id", new Long(bundle.getBundleId()));
props.put("location", bundle.getLocation());
String name = bundle.getSymbolicName();
@@ -531,6 +535,7 @@ public final class CapabilityPermission extends BasicPermission {
entries = null;
}
+ @Override
public Object get(Object k) {
if (!(k instanceof String)) {
return null;
@@ -609,6 +614,7 @@ final class CapabilityPermissionCollection extends PermissionCollection {
* @throws SecurityException If this {@code CapabilityPermissionCollection}
* object has been marked read-only.
*/
+ @Override
public void add(final Permission permission) {
if (!(permission instanceof CapabilityPermission)) {
throw new IllegalArgumentException("invalid permission: " + permission);
@@ -663,6 +669,7 @@ final class CapabilityPermissionCollection extends PermissionCollection {
* @return {@code true} if {@code permission} is a proper subset of a
* permission in the set; {@code false} otherwise.
*/
+ @Override
public boolean implies(final Permission permission) {
if (!(permission instanceof CapabilityPermission)) {
return false;
@@ -743,6 +750,7 @@ final class CapabilityPermissionCollection extends PermissionCollection {
*
* @return Enumeration of all the CapabilityPermission objects.
*/
+ @Override
public synchronized Enumeration<Permission> elements() {
List<Permission> all = new ArrayList<Permission>(permissions.values());
Map<String, CapabilityPermission> pc = filterPermissions;
@@ -766,9 +774,11 @@ final class CapabilityPermissionCollection extends PermissionCollection {
private synchronized void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gfields = in.readFields();
+ @SuppressWarnings("unchecked")
HashMap<String, CapabilityPermission> p = (HashMap<String, CapabilityPermission>) gfields.get("permissions", null);
permissions = p;
all_allowed = gfields.get("all_allowed", false);
+ @SuppressWarnings("unchecked")
HashMap<String, CapabilityPermission> fp = (HashMap<String, CapabilityPermission>) gfields.get("filterPermissions", null);
filterPermissions = fp;
}
diff --git a/src/main/java/org/osgi/framework/Configurable.java b/src/main/java/org/osgi/framework/Configurable.java
index 5fa08c4..62abd45 100644
--- a/src/main/java/org/osgi/framework/Configurable.java
+++ b/src/main/java/org/osgi/framework/Configurable.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.
@@ -26,7 +26,7 @@ package org.osgi.framework;
* {@code instanceof Configurable}.
*
* @deprecated As of 1.2. Please use Configuration Admin service.
- * @version $Id: 1018601ae90d2d16ec34136db4b04dca3ccf8e65 $
+ * @author $Id: dce95833dd076e870099385a306989959a84aafd $
*/
public interface Configurable {
/**
diff --git a/src/main/java/org/osgi/framework/Constants.java b/src/main/java/org/osgi/framework/Constants.java
index 10618a1..2815b24 100644
--- a/src/main/java/org/osgi/framework/Constants.java
+++ b/src/main/java/org/osgi/framework/Constants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2000, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2014). 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.
@@ -16,6 +16,7 @@
package org.osgi.framework;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.hooks.bundle.CollisionHook;
import org.osgi.framework.launch.Framework;
@@ -28,10 +29,9 @@ import org.osgi.framework.launch.Framework;
* otherwise indicated.
*
* @since 1.1
- * @noimplement
- * @version $Id: 6d07a4c3e29a5cd93b3daf0f9fcdab5472b357f6 $
+ * @author $Id: 6873c6f7d537ddbe39a6a2eba107ca3c2de49ce5 $
*/
-
+ at ProviderType
public interface Constants {
/**
* Location identifier of the OSGi <i>system bundle </i>, which is defined
@@ -48,6 +48,14 @@ public interface Constants {
String SYSTEM_BUNDLE_SYMBOLICNAME = "system.bundle";
/**
+ * Identifier of the OSGi <i>system bundle </i>, which is defined to be
+ * {@code 0}.
+ *
+ * @since 1.8
+ */
+ long SYSTEM_BUNDLE_ID = 0L;
+
+ /**
* Manifest header identifying the bundle's category.
* <p>
* The header value may be retrieved from the {@code Dictionary} object
@@ -196,7 +204,7 @@ public interface Constants {
String BUNDLE_CONTACTADDRESS = "Bundle-ContactAddress";
/**
- * Manifest header attribute identifying the bundle's activator class.
+ * Manifest header identifying the bundle's activator class.
*
* <p>
* If present, this header specifies the name of the bundle resource class
@@ -211,6 +219,19 @@ public interface Constants {
String BUNDLE_ACTIVATOR = "Bundle-Activator";
/**
+ * Manifest header identifying the extension bundle's activator class.
+ *
+ * <p>
+ * If present, this header specifies the name of the extension bundle
+ * resource class that implements the {@code BundleActivator} interface and
+ * whose {@code start} and {@code stop} methods are called by the Framework
+ * when the Framework is initialized and shutdown, respectively.
+ *
+ * @since 1.8
+ */
+ String EXTENSION_BUNDLE_ACTIVATOR = "ExtensionBundle-Activator";
+
+ /**
* Manifest header identifying the location from which a new bundle version
* is obtained during a bundle update operation.
*
@@ -387,7 +408,8 @@ public interface Constants {
* like:
*
* <pre>
- * Bundle-SymbolicName: com.acme.module.test; fragment-attachment:="resolve-time"
+ * Bundle-SymbolicName: com.acme.module.test;
+ * fragment-attachment:="resolve-time"
* </pre>
*
* @see #FRAGMENT_ATTACHMENT_DIRECTIVE
@@ -543,7 +565,8 @@ public interface Constants {
* like:
*
* <pre>
- * Import-Package: org.osgi.framework; bundle-symbolic-name="com.acme.module.test"
+ * Import-Package: org.osgi.framework;
+ * bundle-symbolic-name="com.acme.module.test"
* </pre>
*
* @see #IMPORT_PACKAGE
@@ -786,6 +809,9 @@ public interface Constants {
* Fragment-Host: system.bundle; extension:="framework"
* </pre>
*
+ * <p>
+ * The default value is {@link #EXTENSION_FRAMEWORK framework}.
+ *
* @see #FRAGMENT_HOST
* @see #EXTENSION_FRAMEWORK
* @see #EXTENSION_BOOTCLASSPATH
@@ -1257,9 +1283,10 @@ public interface Constants {
*
* <p>
* The value of this property is assigned by the Framework when a service is
- * registered. The Framework assigns a unique value that is larger than all
- * previously assigned values since the Framework was started. These values
- * are NOT persistent across restarts of the Framework.
+ * registered. The Framework assigns a unique, non-negative value that is
+ * larger than all previously assigned values since the Framework was
+ * started. These values are NOT persistent across restarts of the
+ * Framework.
*/
String SERVICE_ID = "service.id";
@@ -1331,6 +1358,66 @@ public interface Constants {
String SERVICE_DESCRIPTION = "service.description";
/**
+ * Service property identifying the {@link Bundle#getBundleId() bundle id}
+ * of the {@link ServiceReference#getBundle() bundle registering the
+ * service}.
+ *
+ * <p>
+ * This property is set by the Framework when a service is registered. The
+ * value of this property must be of type {@code Long}.
+ *
+ * @since 1.8
+ */
+ String SERVICE_BUNDLEID = "service.bundleid";
+
+ /**
+ * Service property identifying a service's scope.
+ *
+ * <p>
+ * This property is set by the Framework when a service is registered. If
+ * the registered object implements {@link PrototypeServiceFactory}, then
+ * the value of this service property will be {@link #SCOPE_PROTOTYPE}.
+ * Otherwise, if the registered object implements {@link ServiceFactory},
+ * then the value of this service property will be {@link #SCOPE_BUNDLE}.
+ * Otherwise, the value of this service property will be
+ * {@link #SCOPE_SINGLETON}.
+ *
+ * @since 1.8
+ * @see #SCOPE_SINGLETON
+ * @see #SCOPE_BUNDLE
+ * @see #SCOPE_PROTOTYPE
+ */
+ String SERVICE_SCOPE = "service.scope";
+
+ /**
+ * Service scope is singleton. All bundles using the service receive the
+ * same service object.
+ *
+ * @since 1.8
+ * @see #SERVICE_SCOPE
+ */
+ String SCOPE_SINGLETON = "singleton";
+
+ /**
+ * Service scope is bundle. Each bundle using the service receives a
+ * customized service object.
+ *
+ * @since 1.8
+ * @see #SERVICE_SCOPE
+ */
+ String SCOPE_BUNDLE = "bundle";
+
+ /**
+ * Service scope is prototype. Each bundle using the service receives either
+ * a customized service object or can request multiple customized service
+ * objects via {@link ServiceObjects}.
+ *
+ * @since 1.8
+ * @see #SERVICE_SCOPE
+ */
+ String SCOPE_PROTOTYPE = "prototype";
+
+ /**
* Framework environment property identifying the Framework's universally
* unique identifier (UUID). A UUID represents a 128-bit value. A new UUID
* is generated by the {@link Framework#init()} method each time a framework
@@ -1700,4 +1787,26 @@ public interface Constants {
* @see BundleException#DUPLICATE_BUNDLE_ERROR
*/
String FRAMEWORK_BSNVERSION_MANAGED = "managed";
+
+ /**
+ * Manifest header identifying the bundle's icon URLs.
+ *
+ * <p>
+ * The header value may be retrieved from the {@code Dictionary} object
+ * returned by the {@code Bundle.getHeaders} method.
+ *
+ * @since 1.8
+ */
+ String BUNDLE_ICON = "Bundle-Icon";
+
+ /**
+ * Manifest header identifying the bundle's license information.
+ *
+ * <p>
+ * The header value may be retrieved from the {@code Dictionary} object
+ * returned by the {@code Bundle.getHeaders} method.
+ *
+ * @since 1.8
+ */
+ String BUNDLE_LICENSE = "Bundle-License";
}
diff --git a/src/main/java/org/osgi/framework/Filter.java b/src/main/java/org/osgi/framework/Filter.java
index 230a6e9..25a60b9 100644
--- a/src/main/java/org/osgi/framework/Filter.java
+++ b/src/main/java/org/osgi/framework/Filter.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.
@@ -18,6 +18,7 @@ package org.osgi.framework;
import java.util.Dictionary;
import java.util.Map;
+import org.osgi.annotation.versioning.ProviderType;
/**
* An <a href="http://www.ietf.org/rfc/rfc1960.txt">RFC 1960</a>-based Filter.
@@ -41,9 +42,9 @@ import java.util.Map;
* @since 1.1
* @see "Core Specification, Filters, for a description of the filter string syntax."
* @ThreadSafe
- * @noimplement
- * @version $Id: 807a04ac07c3230b8f4d4e0f9588a35fbdc41e18 $
+ * @author $Id: 58cd4db16892b20e44be1288ccac929a5a26c53a $
*/
+ at ProviderType
public interface Filter {
/**
* Filter using a service's properties.
diff --git a/src/main/java/org/osgi/framework/FrameworkEvent.java b/src/main/java/org/osgi/framework/FrameworkEvent.java
index 59fa92e..06a62f8 100644
--- a/src/main/java/org/osgi/framework/FrameworkEvent.java
+++ b/src/main/java/org/osgi/framework/FrameworkEvent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2004, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2004, 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.
@@ -33,7 +33,7 @@ import org.osgi.framework.wiring.FrameworkWiring;
*
* @Immutable
* @see FrameworkListener
- * @version $Id: f679c7581879a2e6006ecdd317a5dd5f735764e3 $
+ * @author $Id: 7b74a68311acf2116ccf21e589ece0ce2cd383ba $
*/
public class FrameworkEvent extends EventObject {
@@ -223,16 +223,16 @@ public class FrameworkEvent extends EventObject {
* <p>
* The type values are:
* <ul>
- * <li>{@link #STARTED}
- * <li>{@link #ERROR}
- * <li>{@link #WARNING}
- * <li>{@link #INFO}
- * <li>{@link #PACKAGES_REFRESHED}
- * <li>{@link #STARTLEVEL_CHANGED}
- * <li>{@link #STOPPED}
- * <li>{@link #STOPPED_BOOTCLASSPATH_MODIFIED}
- * <li>{@link #STOPPED_UPDATE}
- * <li>{@link #WAIT_TIMEDOUT}
+ * <li>{@link #STARTED}</li>
+ * <li>{@link #ERROR}</li>
+ * <li>{@link #WARNING}</li>
+ * <li>{@link #INFO}</li>
+ * <li>{@link #PACKAGES_REFRESHED}</li>
+ * <li>{@link #STARTLEVEL_CHANGED}</li>
+ * <li>{@link #STOPPED}</li>
+ * <li>{@link #STOPPED_BOOTCLASSPATH_MODIFIED}</li>
+ * <li>{@link #STOPPED_UPDATE}</li>
+ * <li>{@link #WAIT_TIMEDOUT}</li>
* </ul>
*
* @return The type of state change.
diff --git a/src/main/java/org/osgi/framework/FrameworkListener.java b/src/main/java/org/osgi/framework/FrameworkListener.java
index 7e1e813..1ed8faa 100644
--- a/src/main/java/org/osgi/framework/FrameworkListener.java
+++ b/src/main/java/org/osgi/framework/FrameworkListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2000, 2011). 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.
@@ -17,6 +17,7 @@
package org.osgi.framework;
import java.util.EventListener;
+import org.osgi.annotation.versioning.ConsumerType;
/**
* A {@code FrameworkEvent} listener. {@code FrameworkListener} is a listener
@@ -34,9 +35,9 @@ import java.util.EventListener;
*
* @see FrameworkEvent
* @NotThreadSafe
- * @version $Id: ad7f563bd13b60e2b8a378f147057ca7f0accae2 $
+ * @author $Id: 97c76c64c6e6595ad445dcc2d8083d52540f73b8 $
*/
-
+ at ConsumerType
public interface FrameworkListener extends EventListener {
/**
diff --git a/src/main/java/org/osgi/framework/FrameworkUtil.java b/src/main/java/org/osgi/framework/FrameworkUtil.java
index c26ba43..ab0af92 100644
--- a/src/main/java/org/osgi/framework/FrameworkUtil.java
+++ b/src/main/java/org/osgi/framework/FrameworkUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2005, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2005, 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.
@@ -43,7 +43,7 @@ import javax.security.auth.x500.X500Principal;
*
* @since 1.3
* @ThreadSafe
- * @version $Id: 1f46ea2bbbe2a1242fdaf0877709fb9c02eefae1 $
+ * @author $Id: e93d15cef98c0e7f425f3b076d317c46ebb9a52a $
*/
public class FrameworkUtil {
/**
@@ -539,6 +539,7 @@ public class FrameworkUtil {
*
* @return This {@code Filter}'s filter string.
*/
+ @Override
public String toString() {
String result = filterString;
if (result == null) {
@@ -661,6 +662,7 @@ public class FrameworkUtil {
* {@code this.toString().equals(obj.toString()}; {@code false}
* otherwise.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -682,6 +684,7 @@ public class FrameworkUtil {
*
* @return The hashCode of this {@code Filter}.
*/
+ @Override
public int hashCode() {
return this.toString().hashCode();
}
@@ -768,6 +771,7 @@ public class FrameworkUtil {
return compare_Boolean(operation, ((Boolean) value1).booleanValue(), value2);
}
if (value1 instanceof Comparable<?>) {
+ @SuppressWarnings("unchecked")
Comparable<Object> comparable = (Comparable<Object>) value1;
return compare_Comparable(operation, comparable, value2);
}
@@ -1615,6 +1619,7 @@ public class FrameworkUtil {
this.keys = keyList.toArray(new String[keyList.size()]);
}
+ @Override
public Object get(Object o) {
String k = (String) o;
for (String key : keys) {
@@ -1643,6 +1648,7 @@ public class FrameworkUtil {
this.reference = reference;
}
+ @Override
public Object get(Object key) {
if (reference == null) {
return null;
@@ -1655,14 +1661,14 @@ public class FrameworkUtil {
}
}
- static private final class SetAccessibleAction implements PrivilegedAction<Object> {
+ static private final class SetAccessibleAction implements PrivilegedAction<Void> {
private final AccessibleObject accessible;
SetAccessibleAction(AccessibleObject accessible) {
this.accessible = accessible;
}
- public Object run() {
+ public Void run() {
accessible.setAccessible(true);
return null;
}
@@ -1772,45 +1778,51 @@ public class FrameworkUtil {
* wildcard ("*"), or a List of Strings, each String representing a
* name/value pair in the RDN.
*
- * @param dnChain
+ * @param pattern
* @return a list of DNs.
* @throws IllegalArgumentException
*/
- private static List<Object> parseDNchainPattern(String dnChain) {
- if (dnChain == null) {
- throw new IllegalArgumentException("The DN chain must not be null.");
+ private static List<Object> parseDNchainPattern(String pattern) {
+ if (pattern == null) {
+ throw new IllegalArgumentException("The pattern must not be null.");
}
List<Object> parsed = new ArrayList<Object>();
- int startIndex = 0;
- startIndex = skipSpaces(dnChain, startIndex);
- while (startIndex < dnChain.length()) {
+ final int length = pattern.length();
+ char c = ';'; // start with semi-colon to detect empty pattern
+ for (int startIndex = skipSpaces(pattern, 0); startIndex < length;) {
+ int cursor = startIndex;
int endIndex = startIndex;
- boolean inQuote = false;
- out: while (endIndex < dnChain.length()) {
- char c = dnChain.charAt(endIndex);
+ out: for (boolean inQuote = false; cursor < length; cursor++) {
+ c = pattern.charAt(cursor);
switch (c) {
case '"' :
inQuote = !inQuote;
break;
case '\\' :
- endIndex++; // skip the escaped char
+ cursor++; // skip the escaped char
+ if (cursor == length) {
+ throw new IllegalArgumentException("unterminated escape");
+ }
break;
case ';' :
- if (!inQuote)
- break out;
+ if (!inQuote) {
+ break out; // end of pattern
+ }
+ break;
+ }
+ if (c != ' ') { // ignore trailing whitespace
+ endIndex = cursor + 1;
}
- endIndex++;
- }
- if (endIndex > dnChain.length()) {
- throw new IllegalArgumentException("unterminated escape");
}
- parsed.add(dnChain.substring(startIndex, endIndex));
- startIndex = endIndex + 1;
- startIndex = skipSpaces(dnChain, startIndex);
+ parsed.add(pattern.substring(startIndex, endIndex));
+ startIndex = skipSpaces(pattern, cursor + 1);
+ }
+ if (c == ';') { // last non-whitespace character was a semi-colon
+ throw new IllegalArgumentException("empty pattern");
}
- // Now we parse is a list of strings, lets make List of rdn out
- // of them
+ // Now we have parsed into a list of strings, lets make List of rdn
+ // out of them
for (int i = 0; i < parsed.size(); i++) {
String dn = (String) parsed.get(i);
if (dn.equals(STAR_WILDCARD) || dn.equals(MINUS_WILDCARD)) {
@@ -1818,11 +1830,12 @@ public class FrameworkUtil {
}
List<Object> rdns = new ArrayList<Object>();
if (dn.charAt(0) == '*') {
- if (dn.charAt(1) != ',') {
+ int index = skipSpaces(dn, 1);
+ if (dn.charAt(index) != ',') {
throw new IllegalArgumentException("invalid wildcard prefix");
}
rdns.add(STAR_WILDCARD);
- dn = new X500Principal(dn.substring(2)).getName(X500Principal.CANONICAL);
+ dn = new X500Principal(dn.substring(index + 1)).getName(X500Principal.CANONICAL);
} else {
dn = new X500Principal(dn).getName(X500Principal.CANONICAL);
}
@@ -1830,9 +1843,6 @@ public class FrameworkUtil {
parseDN(dn, rdns);
parsed.set(i, rdns);
}
- if (parsed.size() == 0) {
- throw new IllegalArgumentException("empty DN chain");
- }
return parsed;
}
@@ -2056,7 +2066,7 @@ public class FrameworkUtil {
* "cn=me,c=US;*;cn=you" will match
* "cn=me,c=US";cn=you" and "cn=me,c=US;cn=her;cn=you". The
* pattern "cn=me,c=US;-;cn=you" will match "cn=me,c=US";cn=you"
- * and "cn=me,c=US;cn=her;cn=him;cn=you".
+ * and "cn=me,c=US;cn=her;cn=him;cn=you".</li>
* <li>As a DN prefix. In this case, the DN must start with "*,".
* The wild card will match zero or more RDNs at the start of a
* DN. For example, "*,cn=me,c=US;cn=you" will match
diff --git a/src/main/java/org/osgi/framework/InvalidSyntaxException.java b/src/main/java/org/osgi/framework/InvalidSyntaxException.java
index e2296c0..03f6f2b 100644
--- a/src/main/java/org/osgi/framework/InvalidSyntaxException.java
+++ b/src/main/java/org/osgi/framework/InvalidSyntaxException.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.
@@ -28,7 +28,7 @@ package org.osgi.framework;
* <p>
* This exception conforms to the general purpose exception chaining mechanism.
*
- * @version $Id: 8820ca2db85b557cef8da09ee861249dfb5ee914 $
+ * @author $Id: 59696296eff1574fa844e3a0a975ba6c83ec59af $
*/
public class InvalidSyntaxException extends Exception {
@@ -99,6 +99,7 @@ public class InvalidSyntaxException extends Exception {
* @return The cause of this exception or {@code null} if no cause was set.
* @since 1.3
*/
+ @Override
public Throwable getCause() {
return super.getCause();
}
@@ -114,6 +115,7 @@ public class InvalidSyntaxException extends Exception {
* been set.
* @since 1.3
*/
+ @Override
public Throwable initCause(Throwable cause) {
return super.initCause(cause);
}
diff --git a/src/main/java/org/osgi/framework/PackagePermission.java b/src/main/java/org/osgi/framework/PackagePermission.java
index 62d0d8d..940ee4f 100644
--- a/src/main/java/org/osgi/framework/PackagePermission.java
+++ b/src/main/java/org/osgi/framework/PackagePermission.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.
@@ -54,7 +54,7 @@ import java.util.Map;
* deprecated, implies the {@code import} action.
*
* @ThreadSafe
- * @version $Id: e993fbc36b6bff84182a8594af5af3cad8c4e2a3 $
+ * @author $Id: c2d45ff158a6a19ff7bc155af3ac9941cb6a89d6 $
*/
public final class PackagePermission extends BasicPermission {
@@ -372,6 +372,7 @@ public final class PackagePermission extends BasicPermission {
* @return {@code true} if the specified permission is implied by this
* object; {@code false} otherwise.
*/
+ @Override
public boolean implies(Permission p) {
if (!(p instanceof PackagePermission)) {
return false;
@@ -424,6 +425,7 @@ public final class PackagePermission extends BasicPermission {
* @return Canonical string representation of the {@code PackagePermission}
* actions.
*/
+ @Override
public String getActions() {
String result = actions;
if (result == null) {
@@ -453,6 +455,7 @@ public final class PackagePermission extends BasicPermission {
*
* @return A new {@code PermissionCollection} object.
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new PackagePermissionCollection();
}
@@ -470,6 +473,7 @@ public final class PackagePermission extends BasicPermission {
* has the same package name and actions as this
* {@code PackagePermission} object; {@code false} otherwise.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -489,6 +493,7 @@ public final class PackagePermission extends BasicPermission {
*
* @return A hash code value for this object.
*/
+ @Override
public int hashCode() {
int h = 31 * 17 + getName().hashCode();
h = 31 * h + getActions().hashCode();
@@ -525,9 +530,8 @@ public final class PackagePermission extends BasicPermission {
}
/**
- * Called by {@code <@link PackagePermission#implies(Permission)>}. This
- * method is only called on a requested permission which cannot have a
- * filter set.
+ * Called by {@link PackagePermission#implies(Permission)}. This method is
+ * only called on a requested permission which cannot have a filter set.
*
* @return a map of properties for this permission.
*/
@@ -539,8 +543,8 @@ public final class PackagePermission extends BasicPermission {
final Map<String, Object> map = new HashMap<String, Object>(5);
map.put("package.name", getName());
if (bundle != null) {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
map.put("id", new Long(bundle.getBundleId()));
map.put("location", bundle.getLocation());
String name = bundle.getSymbolicName();
@@ -610,6 +614,7 @@ final class PackagePermissionCollection extends PermissionCollection {
* @throws SecurityException If this {@code PackagePermissionCollection}
* object has been marked read-only.
*/
+ @Override
public void add(final Permission permission) {
if (!(permission instanceof PackagePermission)) {
throw new IllegalArgumentException("invalid permission: " + permission);
@@ -666,6 +671,7 @@ final class PackagePermissionCollection extends PermissionCollection {
* @return {@code true} if {@code permission} is a proper subset of a
* permission in the set; {@code false} otherwise.
*/
+ @Override
public boolean implies(final Permission permission) {
if (!(permission instanceof PackagePermission)) {
return false;
@@ -744,6 +750,7 @@ final class PackagePermissionCollection extends PermissionCollection {
*
* @return Enumeration of all {@code PackagePermission} objects.
*/
+ @Override
public synchronized Enumeration<Permission> elements() {
List<Permission> all = new ArrayList<Permission>(permissions.values());
Map<String, PackagePermission> pc = filterPermissions;
@@ -768,9 +775,11 @@ final class PackagePermissionCollection extends PermissionCollection {
private synchronized void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gfields = in.readFields();
+ @SuppressWarnings("unchecked")
Hashtable<String, PackagePermission> hashtable = (Hashtable<String, PackagePermission>) gfields.get("permissions", null);
permissions = new HashMap<String, PackagePermission>(hashtable);
all_allowed = gfields.get("all_allowed", false);
+ @SuppressWarnings("unchecked")
HashMap<String, PackagePermission> fp = (HashMap<String, PackagePermission>) gfields.get("filterPermissions", null);
filterPermissions = fp;
}
diff --git a/src/main/java/org/osgi/framework/PrototypeServiceFactory.java b/src/main/java/org/osgi/framework/PrototypeServiceFactory.java
new file mode 100644
index 0000000..bb37bdc
--- /dev/null
+++ b/src/main/java/org/osgi/framework/PrototypeServiceFactory.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * A factory for {@link Constants#SCOPE_PROTOTYPE prototype scope} services. The
+ * factory can provide multiple, customized service objects in the OSGi
+ * environment.
+ *
+ * <p>
+ * When registering a service, a {@code PrototypeServiceFactory} object can be
+ * used instead of a service object, so that the bundle developer can create a
+ * customized service object for each caller that is using the service.
+ *
+ * <p>
+ * When a caller uses a {@link ServiceObjects} to
+ * {@link ServiceObjects#getService() request} a service object, the framework
+ * calls the {@link #getService(Bundle, ServiceRegistration) getService} method
+ * to return a service object customized for the requesting caller. The caller
+ * can {@link ServiceObjects#ungetService(Object) release} the returned service
+ * object and the framework will call the
+ * {@link #ungetService(Bundle, ServiceRegistration, Object) ungetService}
+ * method with the service object.
+ *
+ * <p>
+ * When a bundle uses the {@link BundleContext#getService(ServiceReference)}
+ * method to obtain a service object, the framework must act as if the service
+ * has {@link Constants#SCOPE_BUNDLE bundle scope}. That is, the framework will
+ * call the {@link #getService(Bundle, ServiceRegistration) getService} method
+ * to obtain a bundle-scoped service object which will be cached and have a use
+ * count. See {@link ServiceFactory}.
+ *
+ * <p>
+ * A bundle can use both {@link ServiceObjects} and
+ * {@link BundleContext#getService(ServiceReference)} to obtain a service object
+ * for a service. {@link ServiceObjects#getService()} will always return a
+ * service object provided by a call to
+ * {@link #getService(Bundle, ServiceRegistration)} and
+ * {@link BundleContext#getService(ServiceReference)} will always return the
+ * bundle-scoped service object.
+ *
+ * <p>
+ * {@code PrototypeServiceFactory} objects are only used by the Framework and
+ * are not made available to other bundles in the OSGi environment. The
+ * Framework may concurrently call a {@code PrototypeServiceFactory}.
+ *
+ * @param <S> Type of Service
+ * @see BundleContext#getServiceObjects(ServiceReference)
+ * @see ServiceObjects
+ * @ThreadSafe
+ * @since 1.8
+ * @author $Id: PrototypeServiceFactory.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+ at ConsumerType
+public interface PrototypeServiceFactory<S> extends ServiceFactory<S> {
+ /**
+ * Returns a service object for a caller.
+ *
+ * <p>
+ * The Framework invokes this method for each caller requesting a service
+ * object using {@link ServiceObjects#getService()}. The factory can then
+ * return a customized service object for the caller.
+ *
+ * <p>
+ * The Framework must check that the returned service object is valid. If
+ * the returned service object is {@code null} or is not an
+ * {@code instanceof} all the classes named when the service was registered,
+ * a framework event of type {@link FrameworkEvent#ERROR} is fired
+ * containing a service exception of type
+ * {@link ServiceException#FACTORY_ERROR} and {@code null} is returned to
+ * the caller. If this method throws an exception, a framework event of type
+ * {@link FrameworkEvent#ERROR} is fired containing a service exception of
+ * type {@link ServiceException#FACTORY_EXCEPTION} with the thrown exception
+ * as the cause and {@code null} is returned to the caller.
+ *
+ * @param bundle The bundle requesting the service.
+ * @param registration The {@code ServiceRegistration} object for the
+ * requested service.
+ * @return A service object that <strong>must</strong> be an instance of all
+ * the classes named when the service was registered.
+ * @see ServiceObjects#getService()
+ */
+ public S getService(Bundle bundle, ServiceRegistration<S> registration);
+
+ /**
+ * Releases a service object customized for a caller.
+ *
+ * <p>
+ * The Framework invokes this method when a service has been released by a
+ * bundle such as by calling {@link ServiceObjects#ungetService(Object)}.
+ * The service object may then be destroyed.
+ *
+ * <p>
+ * If this method throws an exception, a framework event of type
+ * {@link FrameworkEvent#ERROR} is fired containing a service exception of
+ * type {@link ServiceException#FACTORY_EXCEPTION} with the thrown exception
+ * as the cause.
+ *
+ * @param bundle The bundle releasing the service.
+ * @param registration The {@code ServiceRegistration} object for the
+ * service being released.
+ * @param service The service object returned by a previous call to the
+ * {@link #getService(Bundle, ServiceRegistration) getService}
+ * method.
+ * @see ServiceObjects#ungetService(Object)
+ */
+ public void ungetService(Bundle bundle, ServiceRegistration<S> registration, S service);
+}
diff --git a/src/main/java/org/osgi/framework/ServiceEvent.java b/src/main/java/org/osgi/framework/ServiceEvent.java
index 2a59fe8..06eae88 100644
--- a/src/main/java/org/osgi/framework/ServiceEvent.java
+++ b/src/main/java/org/osgi/framework/ServiceEvent.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.
@@ -32,7 +32,7 @@ import java.util.EventObject;
* @Immutable
* @see ServiceListener
* @see AllServiceListener
- * @version $Id: 49e34e0ad5564d6f4ca0ab0053b272c22b9fb917 $
+ * @author $Id: b27a941cb68e6416825b1b717090a2eb098733f3 $
*/
public class ServiceEvent extends EventObject {
diff --git a/src/main/java/org/osgi/framework/ServiceException.java b/src/main/java/org/osgi/framework/ServiceException.java
index de90784..e0a120c 100644
--- a/src/main/java/org/osgi/framework/ServiceException.java
+++ b/src/main/java/org/osgi/framework/ServiceException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2007, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2007, 2014). 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.
@@ -30,7 +30,7 @@ package org.osgi.framework;
* <p>
* This exception conforms to the general purpose exception chaining mechanism.
*
- * @version $Id: 9f763412635f59585bb615cbc449fc7ab72b7103 $
+ * @author $Id: 32a515460813c702b127f65dda91cd23781b2a98 $
* @since 1.5
*/
@@ -74,6 +74,12 @@ public class ServiceException extends RuntimeException {
* @since 1.6
*/
public static final int FACTORY_RECURSION = 6;
+ /**
+ * An asynchronous operation was unable to obtain the service.
+ *
+ * @since 1.8
+ */
+ public static final int ASYNC_ERROR = 7;
/**
* Creates a {@code ServiceException} with the specified message and
diff --git a/src/main/java/org/osgi/framework/ServiceFactory.java b/src/main/java/org/osgi/framework/ServiceFactory.java
index 4b52fee..1447958 100644
--- a/src/main/java/org/osgi/framework/ServiceFactory.java
+++ b/src/main/java/org/osgi/framework/ServiceFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2000, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2014). 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.
@@ -16,26 +16,34 @@
package org.osgi.framework;
+import org.osgi.annotation.versioning.ConsumerType;
+
/**
- * Allows services to provide customized service objects in the OSGi
+ * A factory for {@link Constants#SCOPE_BUNDLE bundle scope} services. The
+ * factory can provide service objects customized for each bundle in the OSGi
* environment.
*
* <p>
* When registering a service, a {@code ServiceFactory} object can be used
- * instead of a service object, so that the bundle developer can gain control of
- * the specific service object granted to a bundle that is using the service.
+ * instead of a service object, so that the bundle developer can create a
+ * customized service object for each bundle that is using the service.
*
* <p>
- * When this happens, the {@code BundleContext.getService(ServiceReference)}
- * method calls the {@code ServiceFactory.getService} method to create a service
- * object specifically for the requesting bundle. The service object returned by
- * the {@code ServiceFactory} is cached by the Framework until the bundle
- * releases its use of the service.
+ * When a bundle {@link BundleContext#getService(ServiceReference) requests} the
+ * service object, the framework calls the
+ * {@link #getService(Bundle, ServiceRegistration) getService} method to return
+ * a service object customized for the requesting bundle. The returned service
+ * object is cached by the Framework for subsequent calls to
+ * {@link BundleContext#getService(ServiceReference)} until the bundle releases
+ * its use of the service.
*
* <p>
- * When the bundle's use count for the service is decremented to zero (including
- * the bundle stopping or the service being unregistered), the
- * {@code ServiceFactory.ungetService} method is called.
+ * When the bundle's use count for the service is
+ * {@link BundleContext#ungetService(ServiceReference) decremented} to zero
+ * (including the bundle stopping or the service being unregistered), the
+ * framework will call the
+ * {@link #ungetService(Bundle, ServiceRegistration, Object) ungetService}
+ * method.
*
* <p>
* {@code ServiceFactory} objects are only used by the Framework and are not
@@ -45,18 +53,18 @@ package org.osgi.framework;
* @param <S> Type of Service
* @see BundleContext#getService(ServiceReference)
* @ThreadSafe
- * @version $Id: 535776e702ec5ace54f577218ff8f7920741558b $
+ * @author $Id: f11fc6bee18315fb659c7987d1b66f1c9c95548a $
*/
-
+ at ConsumerType
public interface ServiceFactory<S> {
/**
- * Creates a new service object.
+ * Returns a service object for a bundle.
*
* <p>
* The Framework invokes this method the first time the specified
* {@code bundle} requests a service object using the
- * {@code BundleContext.getService(ServiceReference)} method. The service
- * factory can then return a specific service object for each bundle.
+ * {@link BundleContext#getService(ServiceReference)} method. The factory
+ * can then return a customized service object for each bundle.
*
* <p>
* The Framework must check that the returned service object is valid. If
@@ -76,9 +84,10 @@ public interface ServiceFactory<S> {
*
* <p>
* The Framework caches the valid service object and will return the same
- * service object on any future call to {@code BundleContext.getService} for
- * the specified bundle. This means the Framework must not allow this method
- * to be concurrently called for the specified bundle.
+ * service object on any future call to
+ * {@link BundleContext#getService(ServiceReference)} for the specified
+ * bundle. This means the Framework must not allow this method to be
+ * concurrently called for the specified bundle.
*
* @param bundle The bundle requesting the service.
* @param registration The {@code ServiceRegistration} object for the
@@ -90,7 +99,7 @@ public interface ServiceFactory<S> {
public S getService(Bundle bundle, ServiceRegistration<S> registration);
/**
- * Releases a service object.
+ * Releases a service object customized for a bundle.
*
* <p>
* The Framework invokes this method when a service has been released by a
diff --git a/src/main/java/org/osgi/framework/ServiceListener.java b/src/main/java/org/osgi/framework/ServiceListener.java
index 839c1bc..f0d8ae2 100644
--- a/src/main/java/org/osgi/framework/ServiceListener.java
+++ b/src/main/java/org/osgi/framework/ServiceListener.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.
@@ -17,6 +17,7 @@
package org.osgi.framework;
import java.util.EventListener;
+import org.osgi.annotation.versioning.ConsumerType;
/**
* A {@code ServiceEvent} listener. {@code ServiceListener} is a listener
@@ -49,9 +50,9 @@ import java.util.EventListener;
* @see ServiceEvent
* @see ServicePermission
* @ThreadSafe
- * @version $Id: 601dfda6183ab7f18cd3916958a39734ea141c25 $
+ * @author $Id: 8468dbc769382269184c932d41e084cb2fa58eb9 $
*/
-
+ at ConsumerType
public interface ServiceListener extends EventListener {
/**
* Receives notification that a service has had a lifecycle change.
diff --git a/src/main/java/org/osgi/framework/ServiceObjects.java b/src/main/java/org/osgi/framework/ServiceObjects.java
new file mode 100644
index 0000000..2c1bd19
--- /dev/null
+++ b/src/main/java/org/osgi/framework/ServiceObjects.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework;
+
+import org.osgi.annotation.versioning.ProviderType;
+
+/**
+ * Allows multiple service objects for a service to be obtained.
+ *
+ * <p>
+ * For services with {@link Constants#SCOPE_PROTOTYPE prototype} scope, multiple
+ * service objects for the service can be obtained. For services with
+ * {@link Constants#SCOPE_SINGLETON singleton} or {@link Constants#SCOPE_BUNDLE
+ * bundle} scope, only one, use-counted service object is available to a
+ * requesting bundle.
+ *
+ * <p>
+ * Any unreleased service objects obtained from this {@code ServiceObjects}
+ * object are automatically released by the framework when the bundle associated
+ * with the BundleContext used to create this {@code ServiceObjects} object is
+ * stopped.
+ *
+ * @param <S> Type of Service
+ * @see BundleContext#getServiceObjects(ServiceReference)
+ * @see PrototypeServiceFactory
+ * @ThreadSafe
+ * @since 1.8
+ * @author $Id: ServiceObjects.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+ at ProviderType
+public interface ServiceObjects<S> {
+ /**
+ * Returns a service object for the {@link #getServiceReference()
+ * associated} service.
+ *
+ * <p>
+ * This {@code ServiceObjects} object can be used to obtain multiple service
+ * objects for the associated service if the service has
+ * {@link Constants#SCOPE_PROTOTYPE prototype} scope.
+ *
+ * <p>
+ * If the associated service has {@link Constants#SCOPE_SINGLETON singleton}
+ * or {@link Constants#SCOPE_BUNDLE bundle} scope, this method behaves the
+ * same as calling the {@link BundleContext#getService(ServiceReference)}
+ * method for the associated service. That is, only one, use-counted service
+ * object is available from this {@link ServiceObjects} object.
+ *
+ * <p>
+ * This method will always return {@code null} when the associated service
+ * has been unregistered.
+ *
+ * <p>
+ * For a prototype scope service, the following steps are required to obtain
+ * a service object:
+ * <ol>
+ * <li>If the associated service has been unregistered, {@code null} is
+ * returned.</li>
+ * <li>The
+ * {@link PrototypeServiceFactory#getService(Bundle, ServiceRegistration)}
+ * method is called to supply a customized service object for the caller.</li>
+ * <li>If the service object returned by the {@code PrototypeServiceFactory}
+ * object is {@code null}, not an {@code instanceof} all the classes named
+ * when the service was registered or the {@code PrototypeServiceFactory}
+ * object throws an exception, {@code null} is returned and a Framework
+ * event of type {@link FrameworkEvent#ERROR} containing a
+ * {@link ServiceException} describing the error is fired.</li>
+ * <li>The customized service object is returned.</li>
+ * </ol>
+ *
+ * @return A service object for the associated service or {@code null} if
+ * the service is not registered, the customized service object
+ * returned by a {@code ServiceFactory} does not implement the
+ * classes under which it was registered or the
+ * {@code ServiceFactory} threw an exception.
+ * @throws IllegalStateException If the BundleContext used to create this
+ * {@code ServiceObjects} object is no longer valid.
+ * @see #ungetService(Object)
+ */
+ public S getService();
+
+ /**
+ * Releases a service object for the {@link #getServiceReference()
+ * associated} service.
+ *
+ * <p>
+ * This {@code ServiceObjects} object can be used to obtain multiple service
+ * objects for the associated service if the service has
+ * {@link Constants#SCOPE_PROTOTYPE prototype} scope. If the associated
+ * service has {@link Constants#SCOPE_SINGLETON singleton} or
+ * {@link Constants#SCOPE_BUNDLE bundle} scope, this method behaves the same
+ * as calling the {@link BundleContext#ungetService(ServiceReference)}
+ * method for the associated service. That is, only one, use-counted service
+ * object is available from this {@link ServiceObjects} object.
+ *
+ * <p>
+ * For a prototype scope service, the following steps are required to
+ * release a service object:
+ * <ol>
+ * <li>If the associated service has been unregistered, this method returns
+ * without doing anything.</li>
+ * <li>The
+ * {@link PrototypeServiceFactory#ungetService(Bundle, ServiceRegistration, Object)}
+ * method is called to release the specified service object.</li>
+ * </ol>
+ *
+ * <p>
+ * The specified service object must no longer be used and all references to
+ * it should be destroyed after calling this method.
+ *
+ * @param service A service object previously provided by this
+ * {@code ServiceObjects} object.
+ * @throws IllegalStateException If the BundleContext used to create this
+ * {@code ServiceObjects} object is no longer valid.
+ * @throws IllegalArgumentException If the specified service object was not
+ * provided by this {@code ServiceObjects} object.
+ * @see #getService()
+ */
+ public void ungetService(S service);
+
+ /**
+ * Returns the {@link ServiceReference} for the service associated with this
+ * {@code ServiceObjects} object.
+ *
+ * @return The {@link ServiceReference} for the service associated with this
+ * {@code ServiceObjects} object.
+ */
+ public ServiceReference<S> getServiceReference();
+}
diff --git a/src/main/java/org/osgi/framework/ServicePermission.java b/src/main/java/org/osgi/framework/ServicePermission.java
index 23ecfba..36e7558 100644
--- a/src/main/java/org/osgi/framework/ServicePermission.java
+++ b/src/main/java/org/osgi/framework/ServicePermission.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.
@@ -42,8 +42,8 @@ import java.util.Set;
* A bundle's authority to register or get a service.
* <ul>
* <li>The {@code register} action allows a bundle to register a service on the
- * specified names.
- * <li>The {@code get} action allows a bundle to detect a service and get it.
+ * specified names.</li>
+ * <li>The {@code get} action allows a bundle to detect a service and get it.</li>
* </ul>
* Permission to get a service is required in order to detect events regarding
* the service. Untrusted bundles should not be able to detect the presence of
@@ -51,7 +51,7 @@ import java.util.Set;
* to get the specific service.
*
* @ThreadSafe
- * @version $Id: 96438ad164d7f0f4273787226298bf8208cf0034 $
+ * @author $Id: ff7fc46dd623c0a09b49965048dd6faa2b111b39 $
*/
public final class ServicePermission extends BasicPermission {
@@ -207,7 +207,7 @@ public final class ServicePermission extends BasicPermission {
if (reference == null) {
throw new IllegalArgumentException("reference must not be null");
}
- StringBuffer sb = new StringBuffer("(service.id=");
+ StringBuffer sb = new StringBuffer("(" + Constants.SERVICE_ID + "=");
sb.append(reference.getProperty(Constants.SERVICE_ID));
sb.append(")");
return sb.toString();
@@ -364,6 +364,7 @@ public final class ServicePermission extends BasicPermission {
* @return {@code true} if the specified permission is implied by this
* object; {@code false} otherwise.
*/
+ @Override
public boolean implies(Permission p) {
if (!(p instanceof ServicePermission)) {
return false;
@@ -438,6 +439,7 @@ public final class ServicePermission extends BasicPermission {
*
* @return The canonical string representation of the actions.
*/
+ @Override
public String getActions() {
String result = actions;
if (result == null) {
@@ -469,6 +471,7 @@ public final class ServicePermission extends BasicPermission {
* @return A new {@code PermissionCollection} object suitable for storing
* {@code ServicePermission} objects.
*/
+ @Override
public PermissionCollection newPermissionCollection() {
return new ServicePermissionCollection();
}
@@ -484,6 +487,7 @@ public final class ServicePermission extends BasicPermission {
* class name and actions as this {@code ServicePermission} object;
* {@code false} otherwise.
*/
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -503,6 +507,7 @@ public final class ServicePermission extends BasicPermission {
*
* @return Hash code value for this object.
*/
+ @Override
public int hashCode() {
int h = 31 * 17 + getName().hashCode();
h = 31 * h + getActions().hashCode();
@@ -538,9 +543,8 @@ public final class ServicePermission extends BasicPermission {
}
/**
- * Called by {@code <@link ServicePermission#implies(Permission)>}. This
- * method is only called on a requested permission which cannot have a
- * filter set.
+ * Called by {@link ServicePermission#implies(Permission)}. This method is
+ * only called on a requested permission which cannot have a filter set.
*
* @return a map of properties for this permission.
*/
@@ -557,8 +561,8 @@ public final class ServicePermission extends BasicPermission {
final Map<String, Object> props = new HashMap<String, Object>(4);
final Bundle bundle = service.getBundle();
if (bundle != null) {
- AccessController.doPrivileged(new PrivilegedAction<Object>() {
- public Object run() {
+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
+ public Void run() {
props.put("id", new Long(bundle.getBundleId()));
props.put("location", bundle.getLocation());
String name = bundle.getSymbolicName();
@@ -587,6 +591,7 @@ public final class ServicePermission extends BasicPermission {
entries = null;
}
+ @Override
public Object get(Object k) {
if (!(k instanceof String)) {
return null;
@@ -639,14 +644,17 @@ public final class ServicePermission extends BasicPermission {
throw new UnsupportedOperationException();
}
+ @Override
public String toString() {
return k + "=" + v;
}
+ @Override
public int hashCode() {
return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode());
}
+ @Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
@@ -717,6 +725,7 @@ final class ServicePermissionCollection extends PermissionCollection {
* @throws SecurityException If this {@code ServicePermissionCollection}
* object has been marked read-only.
*/
+ @Override
public void add(final Permission permission) {
if (!(permission instanceof ServicePermission)) {
throw new IllegalArgumentException("invalid permission: " + permission);
@@ -771,6 +780,7 @@ final class ServicePermissionCollection extends PermissionCollection {
* @return {@code true} if {@code permission} is a proper subset of a
* permission in the set; {@code false} otherwise.
*/
+ @Override
public boolean implies(final Permission permission) {
if (!(permission instanceof ServicePermission)) {
return false;
@@ -877,6 +887,7 @@ final class ServicePermissionCollection extends PermissionCollection {
*
* @return Enumeration of all the ServicePermission objects.
*/
+ @Override
public synchronized Enumeration<Permission> elements() {
List<Permission> all = new ArrayList<Permission>(permissions.values());
Map<String, ServicePermission> pc = filterPermissions;
@@ -901,9 +912,11 @@ final class ServicePermissionCollection extends PermissionCollection {
private synchronized void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
ObjectInputStream.GetField gfields = in.readFields();
+ @SuppressWarnings("unchecked")
Hashtable<String, ServicePermission> hashtable = (Hashtable<String, ServicePermission>) gfields.get("permissions", null);
permissions = new HashMap<String, ServicePermission>(hashtable);
all_allowed = gfields.get("all_allowed", false);
+ @SuppressWarnings("unchecked")
HashMap<String, ServicePermission> fp = (HashMap<String, ServicePermission>) gfields.get("filterPermissions", null);
filterPermissions = fp;
}
diff --git a/src/main/java/org/osgi/framework/ServiceReference.java b/src/main/java/org/osgi/framework/ServiceReference.java
index 7541517..193f749 100644
--- a/src/main/java/org/osgi/framework/ServiceReference.java
+++ b/src/main/java/org/osgi/framework/ServiceReference.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.
@@ -17,6 +17,7 @@
package org.osgi.framework;
import java.util.Dictionary;
+import org.osgi.annotation.versioning.ProviderType;
/**
* A reference to a service.
@@ -46,11 +47,11 @@ import java.util.Dictionary;
* @see BundleContext#getServiceReferences(Class, String)
* @see BundleContext#getServiceReferences(String, String)
* @see BundleContext#getService(ServiceReference)
+ * @see BundleContext#getServiceObjects(ServiceReference)
* @ThreadSafe
- * @noimplement
- * @version $Id: 75352193f9f11a2c19692890153c6ff91611023b $
+ * @author $Id: a56f8df70e8c74a76a1ef02b714b4612bc064ecc $
*/
-
+ at ProviderType
public interface ServiceReference<S> extends Comparable<Object> {
/**
* Returns the property value to which the specified property key is mapped
diff --git a/src/main/java/org/osgi/framework/ServiceRegistration.java b/src/main/java/org/osgi/framework/ServiceRegistration.java
index 702e918..b50e6cb 100644
--- a/src/main/java/org/osgi/framework/ServiceRegistration.java
+++ b/src/main/java/org/osgi/framework/ServiceRegistration.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2000, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2014). 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.
@@ -17,6 +17,7 @@
package org.osgi.framework;
import java.util.Dictionary;
+import org.osgi.annotation.versioning.ProviderType;
/**
* A registered service.
@@ -33,10 +34,9 @@ import java.util.Dictionary;
* @param <S> Type of Service.
* @see BundleContext#registerService(String[],Object,Dictionary)
* @ThreadSafe
- * @noimplement
- * @version $Id: a84248da0db0538708d2394a9478153e06b8afb9 $
+ * @author $Id: 0bc5bfa68ae7cb4a409c066585d3ab4077d80eeb $
*/
-
+ at ProviderType
public interface ServiceRegistration<S> {
/**
* Returns a {@code ServiceReference} object for a service being registered.
@@ -53,15 +53,16 @@ public interface ServiceRegistration<S> {
* Updates the properties associated with a service.
*
* <p>
- * The {@link Constants#OBJECTCLASS} and {@link Constants#SERVICE_ID} keys
+ * The {@link Constants#OBJECTCLASS}, {@link Constants#SERVICE_BUNDLEID},
+ * {@link Constants#SERVICE_ID} and {@link Constants#SERVICE_SCOPE} keys
* cannot be modified by this method. These values are set by the Framework
* when the service is registered in the OSGi environment.
*
* <p>
* The following steps are required to modify service properties:
* <ol>
- * <li>The service's properties are replaced with the provided properties.
- * <li>A service event of type {@link ServiceEvent#MODIFIED} is fired.
+ * <li>The service's properties are replaced with the provided properties.</li>
+ * <li>A service event of type {@link ServiceEvent#MODIFIED} is fired.</li>
* </ol>
*
* @param properties The properties for this service. See {@link Constants}
@@ -86,18 +87,21 @@ public interface ServiceRegistration<S> {
* The following steps are required to unregister a service:
* <ol>
* <li>The service is removed from the Framework service registry so that it
- * can no longer be obtained.
+ * can no longer be obtained.</li>
* <li>A service event of type {@link ServiceEvent#UNREGISTERING} is fired
* so that bundles using this service can release their use of the service.
* Once delivery of the service event is complete, the
* {@code ServiceReference} objects for the service may no longer be used to
- * get a service object for the service.
+ * get a service object for the service.</li>
* <li>For each bundle whose use count for this service is greater than
- * zero: <br>
- * The bundle's use count for this service is set to zero. <br>
- * If the service was registered with a {@link ServiceFactory} object, the
- * {@code ServiceFactory.ungetService} method is called to release the
- * service object for the bundle.
+ * zero:
+ * <ul>
+ * <li>The bundle's use count for this service is set to zero.</li>
+ * <li>If the service was registered with a {@link ServiceFactory} object,
+ * the {@code ServiceFactory.ungetService} method is called to release the
+ * service object for the bundle.</li>
+ * </ul>
+ * </li>
* </ol>
*
* @throws IllegalStateException If this {@code ServiceRegistration} object
diff --git a/src/main/java/org/osgi/framework/SignerProperty.java b/src/main/java/org/osgi/framework/SignerProperty.java
index 9236dfa..0dbb6ca 100644
--- a/src/main/java/org/osgi/framework/SignerProperty.java
+++ b/src/main/java/org/osgi/framework/SignerProperty.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2009, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2009, 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.
@@ -26,7 +26,7 @@ import java.util.Map;
* during filter expression evaluation in the permission implies method.
*
* @Immutable
- * @version $Id: 94eea19050b84907f1257d7a12ebf8ab404f4473 $
+ * @author $Id: 53dec4a366c1c419baeb1e3b7d6b2b3bf172ad93 $
*/
final class SignerProperty {
private final Bundle bundle;
@@ -64,6 +64,7 @@ final class SignerProperty {
* @param o SignerProperty to compare against.
* @return true if the DN name chain matches the pattern.
*/
+ @Override
public boolean equals(Object o) {
if (!(o instanceof SignerProperty))
return false;
@@ -91,6 +92,7 @@ final class SignerProperty {
* Since the equals method does not obey the general equals contract, this
* method cannot generate hash codes which obey the equals contract.
*/
+ @Override
public int hashCode() {
return 31;
}
diff --git a/src/main/java/org/osgi/framework/SynchronousBundleListener.java b/src/main/java/org/osgi/framework/SynchronousBundleListener.java
index ee8474c..76ec1ba 100644
--- a/src/main/java/org/osgi/framework/SynchronousBundleListener.java
+++ b/src/main/java/org/osgi/framework/SynchronousBundleListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2001, 2011). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2001, 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.
@@ -16,6 +16,8 @@
package org.osgi.framework;
+import org.osgi.annotation.versioning.ConsumerType;
+
/**
* A synchronous {@code BundleEvent} listener. {@code SynchronousBundleListener}
* is a listener interface that may be implemented by a bundle developer. When a
@@ -57,9 +59,9 @@ package org.osgi.framework;
* @since 1.1
* @see BundleEvent
* @ThreadSafe
- * @version $Id: 74246f4ceeba7f9a5ee198048522f93d4691c51a $
+ * @author $Id: 6b50c6c9d8b8b091928495eb036552773284b13a $
*/
-
+ at ConsumerType
public interface SynchronousBundleListener extends BundleListener {
// This is a marker interface
}
diff --git a/src/main/java/org/osgi/framework/UnfilteredServiceListener.java b/src/main/java/org/osgi/framework/UnfilteredServiceListener.java
index d712fcf..27271ca 100644
--- a/src/main/java/org/osgi/framework/UnfilteredServiceListener.java
+++ b/src/main/java/org/osgi/framework/UnfilteredServiceListener.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2011). 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.
@@ -16,6 +16,7 @@
package org.osgi.framework;
+import org.osgi.annotation.versioning.ConsumerType;
import org.osgi.framework.hooks.service.ListenerHook;
/**
@@ -65,9 +66,9 @@ import org.osgi.framework.hooks.service.ListenerHook;
* @see ServicePermission
* @ThreadSafe
* @since 1.7
- * @version $Id: 543a345802f8dc7a49d29e8fb7aee7004ee2b329 $
+ * @author $Id: c68fe7ab0c3461256613d22dd666f17f87597dfe $
*/
-
+ at ConsumerType
public interface UnfilteredServiceListener extends ServiceListener {
// This is a marker interface
}
diff --git a/src/main/java/org/osgi/framework/Version.java b/src/main/java/org/osgi/framework/Version.java
index 02f6ddd..7ec6dc0 100644
--- a/src/main/java/org/osgi/framework/Version.java
+++ b/src/main/java/org/osgi/framework/Version.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2004, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2004, 2014). 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.
@@ -37,7 +37,7 @@ import java.util.StringTokenizer;
*
* @since 1.3
* @Immutable
- * @version $Id: a0b5a865f7fbf2b3dcb77a13b2e99da0b64702bb $
+ * @author $Id: c24d4d37a0657ac69de29085d2d290cbb0031c4a $
*/
public class Version implements Comparable<Version> {
@@ -210,13 +210,13 @@ public class Version implements Comparable<Version> {
* Parses a version identifier from the specified string.
*
* <p>
- * See {@code Version(String)} for the format of the version string.
+ * See {@link #Version(String)} for the format of the version string.
*
* @param version String representation of the version identifier. Leading
* and trailing whitespace will be ignored.
* @return A {@code Version} object representing the version identifier. If
* {@code version} is {@code null} or the empty string then
- * {@code emptyVersion} will be returned.
+ * {@link #emptyVersion} will be returned.
* @throws IllegalArgumentException If {@code version} is improperly
* formatted.
*/
@@ -225,6 +225,30 @@ public class Version implements Comparable<Version> {
return emptyVersion;
}
+ return valueOf(version);
+ }
+
+ /**
+ * Returns a {@code Version} object holding the version identifier in the
+ * specified {@code String}.
+ *
+ * <p>
+ * See {@link #Version(String)} for the format of the version string.
+ *
+ * <p>
+ * This method performs a similar function as {@link #parseVersion(String)}
+ * but has the static factory {@code valueOf(String)} method signature.
+ *
+ * @param version String representation of the version identifier. Leading
+ * and trailing whitespace will be ignored. Must not be {@code null}.
+ * @return A {@code Version} object representing the version identifier. If
+ * {@code version} is the empty string then {@link #emptyVersion}
+ * will be returned.
+ * @throws IllegalArgumentException If {@code version} is improperly
+ * formatted.
+ * @since 1.8
+ */
+ public static Version valueOf(String version) {
version = version.trim();
if (version.length() == 0) {
return emptyVersion;
@@ -279,6 +303,7 @@ public class Version implements Comparable<Version> {
*
* @return The string representation of this version identifier.
*/
+ @Override
public String toString() {
return toString0();
}
@@ -289,8 +314,9 @@ public class Version implements Comparable<Version> {
* @return The string representation of this version identifier.
*/
String toString0() {
- if (versionString != null) {
- return versionString;
+ String s = versionString;
+ if (s != null) {
+ return s;
}
int q = qualifier.length();
StringBuffer result = new StringBuffer(20 + q);
@@ -311,11 +337,13 @@ public class Version implements Comparable<Version> {
*
* @return An integer which is a hash code value for this object.
*/
+ @Override
public int hashCode() {
- if (hash != 0) {
- return hash;
+ int h = hash;
+ if (h != 0) {
+ return h;
}
- int h = 31 * 17;
+ h = 31 * 17;
h = 31 * h + major;
h = 31 * h + minor;
h = 31 * h + micro;
@@ -335,6 +363,7 @@ public class Version implements Comparable<Version> {
* @return {@code true} if {@code object} is a {@code Version} and is equal
* to this object; {@code false} otherwise.
*/
+ @Override
public boolean equals(Object object) {
if (object == this) { // quicktest
return true;
diff --git a/src/main/java/org/osgi/framework/VersionRange.java b/src/main/java/org/osgi/framework/VersionRange.java
index 0589a75..db4fc7b 100644
--- a/src/main/java/org/osgi/framework/VersionRange.java
+++ b/src/main/java/org/osgi/framework/VersionRange.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.
@@ -32,7 +32,7 @@ import java.util.StringTokenizer;
*
* @since 1.7
* @Immutable
- * @version $Id: d0c21e6a5015a7fa0b33179a29122ea7d137145a $
+ * @author $Id: 1f5fa660a1a42e83371fe0d2c61ae79ce1cb1710 $
*/
public class VersionRange {
@@ -123,7 +123,7 @@ public class VersionRange {
*
* @param range String representation of the version range. The versions in
* the range must contain no whitespace. Other whitespace in the
- * range string is ignored.
+ * range string is ignored. Must not be {@code null}.
* @throws IllegalArgumentException If {@code range} is improperly
* formatted.
*/
@@ -191,7 +191,7 @@ public class VersionRange {
*/
private static Version parseVersion(String version, String range) {
try {
- return Version.parseVersion(version);
+ return Version.valueOf(version);
} catch (IllegalArgumentException e) {
IllegalArgumentException iae = new IllegalArgumentException("invalid range \"" + range + "\": " + e.getMessage());
iae.initCause(e);
@@ -377,9 +377,11 @@ public class VersionRange {
*
* @return The string representation of this version range.
*/
+ @Override
public String toString() {
- if (versionRangeString != null) {
- return versionRangeString;
+ String s = versionRangeString;
+ if (s != null) {
+ return s;
}
String leftVersion = left.toString();
if (right == null) {
@@ -402,14 +404,16 @@ public class VersionRange {
*
* @return An integer which is a hash code value for this object.
*/
+ @Override
public int hashCode() {
- if (hash != 0) {
- return hash;
+ int h = hash;
+ if (h != 0) {
+ return h;
}
if (empty) {
return hash = 31;
}
- int h = 31 + (leftClosed ? 7 : 5);
+ h = 31 + (leftClosed ? 7 : 5);
h = 31 * h + left.hashCode();
if (right != null) {
h = 31 * h + right.hashCode();
@@ -430,6 +434,7 @@ public class VersionRange {
* @return {@code true} if {@code object} is a {@code VersionRange} and is
* equal to this object; {@code false} otherwise.
*/
+ @Override
public boolean equals(Object object) {
if (object == this) { // quicktest
return true;
@@ -471,9 +476,16 @@ public class VersionRange {
}
StringBuffer result = new StringBuffer(128);
- if (right != null) {
+ final boolean needPresence = !leftClosed && ((right == null) || !rightClosed);
+ final boolean multipleTerms = needPresence || (right != null);
+ if (multipleTerms) {
result.append("(&");
}
+ if (needPresence) {
+ result.append('(');
+ result.append(attributeName);
+ result.append("=*)");
+ }
if (leftClosed) {
result.append('(');
result.append(attributeName);
@@ -501,9 +513,31 @@ public class VersionRange {
result.append(right.toString0());
result.append("))");
}
+ }
+ if (multipleTerms) {
result.append(')');
}
return result.toString();
}
+
+ /**
+ * Returns a {@code VersionRange} object holding the version range in the
+ * specified {@code String}.
+ *
+ * <p>
+ * See {@link #VersionRange(String)} for the format of the version range
+ * string.
+ *
+ * @param range String representation of the version range. The versions in
+ * the range must contain no whitespace. Other whitespace in the
+ * range string is ignored. Must not be {@code null}.
+ * @return A {@code VersionRange} object representing the version range.
+ * @throws IllegalArgumentException If {@code range} is improperly
+ * formatted.
+ * @since 1.8
+ */
+ public static VersionRange valueOf(String range) {
+ return new VersionRange(range);
+ }
}
diff --git a/src/main/java/org/osgi/framework/dto/BundleDTO.java b/src/main/java/org/osgi/framework/dto/BundleDTO.java
new file mode 100644
index 0000000..58429b4
--- /dev/null
+++ b/src/main/java/org/osgi/framework/dto/BundleDTO.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.dto;
+
+import org.osgi.dto.DTO;
+import org.osgi.framework.Bundle;
+
+/**
+ * Data Transfer Object for a Bundle.
+ *
+ * <p>
+ * A Bundle can be adapted to provide a {@code BundleDTO} for the Bundle.
+ *
+ * @author $Id: BundleDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class BundleDTO extends DTO {
+ /**
+ * The bundle's unique identifier.
+ *
+ * @see Bundle#getBundleId()
+ */
+ public long id;
+
+ /**
+ * The time when the bundle was last modified.
+ *
+ * @see Bundle#getLastModified()
+ */
+ public long lastModified;
+
+ /**
+ * The bundle's state.
+ *
+ * @see Bundle#getState()
+ */
+ public int state;
+
+ /**
+ * The bundle's symbolic name.
+ *
+ * @see Bundle#getSymbolicName()
+ */
+ public String symbolicName;
+
+ /**
+ * The bundle's version.
+ *
+ * @see Bundle#getVersion()
+ */
+ public String version;
+}
diff --git a/src/main/java/org/osgi/framework/dto/FrameworkDTO.java b/src/main/java/org/osgi/framework/dto/FrameworkDTO.java
new file mode 100644
index 0000000..cd1c4e0
--- /dev/null
+++ b/src/main/java/org/osgi/framework/dto/FrameworkDTO.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.dto;
+
+import java.util.List;
+import java.util.Map;
+import org.osgi.dto.DTO;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Data Transfer Object for a Framework.
+ *
+ * <p>
+ * The System Bundle can be adapted to provide a {@code FrameworkDTO} for the
+ * framework of the system bundle. A {@code FrameworkDTO} obtained from a
+ * framework will contain only the launch properties of the framework. These
+ * properties will not include the System properties.
+ *
+ * @author $Id: FrameworkDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class FrameworkDTO extends DTO {
+ /**
+ * The bundles that are installed in the framework.
+ *
+ * @see BundleContext#getBundles()
+ */
+ public List<BundleDTO> bundles;
+
+ /**
+ * The launch properties of the framework.
+ *
+ * The value type must be a numerical type, Boolean, String, DTO or an array
+ * of any of the former.
+ *
+ * @see BundleContext#getProperty(String)
+ */
+ public Map<String, Object> properties;
+
+ /**
+ * The services that are registered in the framework.
+ *
+ * @see BundleContext#getServiceReferences(String, String)
+ */
+ public List<ServiceReferenceDTO> services;
+}
diff --git a/src/main/java/org/osgi/framework/dto/ServiceReferenceDTO.java b/src/main/java/org/osgi/framework/dto/ServiceReferenceDTO.java
new file mode 100644
index 0000000..23a4a0a
--- /dev/null
+++ b/src/main/java/org/osgi/framework/dto/ServiceReferenceDTO.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.dto;
+
+import java.util.Map;
+import org.osgi.dto.DTO;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Data Transfer Object for a ServiceReference.
+ *
+ * <p>
+ * {@code ServiceReferenceDTO}s for all registered services can be obtained from
+ * a {@link FrameworkDTO}. An installed Bundle can be adapted to provide a
+ * {@code ServiceReferenceDTO[]} of the services registered by the Bundle. A
+ * {@code ServiceReferenceDTO} obtained from a framework must convert service
+ * property values which are not valid value types for DTOs to type
+ * {@code String} using {@code String.valueOf(Object)}.
+ *
+ * @author $Id: ServiceReferenceDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class ServiceReferenceDTO extends DTO {
+ /**
+ * The id of the service.
+ *
+ * @see Constants#SERVICE_ID
+ */
+ public long id;
+
+ /**
+ * The id of the bundle that registered the service.
+ *
+ * @see ServiceReference#getBundle()
+ */
+ public long bundle;
+
+ /**
+ * The properties for the service.
+ *
+ * The value type must be a numerical type, Boolean, String, DTO or an array
+ * of any of the former.
+ *
+ * @see ServiceReference#getProperty(String)
+ */
+ public Map<String, Object> properties;
+
+ /**
+ * The ids of the bundles that are using the service.
+ *
+ * @see ServiceReference#getUsingBundles()
+ */
+ public long[] usingBundles;
+}
diff --git a/src/main/java/org/osgi/framework/dto/package-info.java b/src/main/java/org/osgi/framework/dto/package-info.java
new file mode 100644
index 0000000..286362b
--- /dev/null
+++ b/src/main/java/org/osgi/framework/dto/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). 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.
+ */
+
+/**
+ * OSGi Data Transfer Object Framework Package Version 1.8.
+ *
+ * <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.framework.dto; version="[1.8,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.framework.dto; version="[1.8,1.9)"}
+ *
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+
+ at Version("1.8")
+package org.osgi.framework.dto;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/framework/dto/packageinfo b/src/main/java/org/osgi/framework/dto/packageinfo
new file mode 100644
index 0000000..ed9885d
--- /dev/null
+++ b/src/main/java/org/osgi/framework/dto/packageinfo
@@ -0,0 +1 @@
+version 1.8
diff --git a/src/main/java/org/osgi/framework/hooks/bundle/CollisionHook.java b/src/main/java/org/osgi/framework/hooks/bundle/CollisionHook.java
index 37446ff..cb3eb2d 100644
--- a/src/main/java/org/osgi/framework/hooks/bundle/CollisionHook.java
+++ b/src/main/java/org/osgi/framework/hooks/bundle/CollisionHook.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.
@@ -17,6 +17,7 @@
package org.osgi.framework.hooks.bundle;
import java.util.Collection;
+import org.osgi.annotation.versioning.ConsumerType;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
@@ -33,8 +34,9 @@ import org.osgi.framework.Constants;
* in a bundle symbolic name and version collision.
*
* @ThreadSafe
- * @version $Id: a1a25ee0432f210a56e911246f477f19edc28bc1 $
+ * @author $Id: b05e0c3819aff6df35c2ec034242596d04f53408 $
*/
+ at ConsumerType
public interface CollisionHook {
/**
@@ -54,17 +56,17 @@ public interface CollisionHook {
* on the operation type the target bundle and the collision candidate
* collection are the following:
* <ul>
- * <li> {@link #INSTALLING installing} - The target is the bundle associated
+ * <li>{@link #INSTALLING installing} - The target is the bundle associated
* with the {@link BundleContext} used to call one of the
* {@link BundleContext#installBundle(String) install} methods. The
* collision candidate collection contains the existing bundles installed
* which have the same symbolic name and version as the bundle being
- * installed.
- * <li> {@link #UPDATING updating} - The target is the bundle used to call
+ * installed.</li>
+ * <li>{@link #UPDATING updating} - The target is the bundle used to call
* one of the {@link Bundle#update() update} methods. The collision
* candidate collection contains the existing bundles installed which have
* the same symbolic name and version as the content the target bundle is
- * being updated to.
+ * being updated to.</li>
* </ul>
* This method can filter the collection of collision candidates by removing
* potential collisions. For the specified operation to succeed, the
diff --git a/src/main/java/org/osgi/framework/hooks/bundle/EventHook.java b/src/main/java/org/osgi/framework/hooks/bundle/EventHook.java
index e66a20e..4bd7657 100644
--- a/src/main/java/org/osgi/framework/hooks/bundle/EventHook.java
+++ b/src/main/java/org/osgi/framework/hooks/bundle/EventHook.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.
@@ -17,6 +17,7 @@
package org.osgi.framework.hooks.bundle;
import java.util.Collection;
+import org.osgi.annotation.versioning.ConsumerType;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
@@ -28,8 +29,9 @@ import org.osgi.framework.BundleEvent;
* (install, start, stop, update, and uninstall bundle) operations.
*
* @ThreadSafe
- * @version $Id: e1471b36491a02bd8598a30d05c889ee58edc760 $
+ * @author $Id: 0b986db904e41d5a5bfb5d28fc849ee967decf0d $
*/
+ at ConsumerType
public interface EventHook {
/**
diff --git a/src/main/java/org/osgi/framework/hooks/bundle/FindHook.java b/src/main/java/org/osgi/framework/hooks/bundle/FindHook.java
index af556ea..9c8ab23 100644
--- a/src/main/java/org/osgi/framework/hooks/bundle/FindHook.java
+++ b/src/main/java/org/osgi/framework/hooks/bundle/FindHook.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.
@@ -17,6 +17,7 @@
package org.osgi.framework.hooks.bundle;
import java.util.Collection;
+import org.osgi.annotation.versioning.ConsumerType;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
@@ -29,8 +30,9 @@ import org.osgi.framework.BundleException;
* (get bundles) operations.
*
* @ThreadSafe
- * @version $Id: ae6bf5fc5cf999ac39dfc195c99ef7e223e3b847 $
+ * @author $Id: 1029e10212f150304095fc99433197083cc00e9e $
*/
+ at ConsumerType
public interface FindHook {
/**
* Find hook method. This method is called for the following:
diff --git a/src/main/java/org/osgi/framework/hooks/bundle/package-info.java b/src/main/java/org/osgi/framework/hooks/bundle/package-info.java
new file mode 100644
index 0000000..f701a5f
--- /dev/null
+++ b/src/main/java/org/osgi/framework/hooks/bundle/package-info.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ * 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.
+ */
+
+/**
+ * Framework Bundle Hooks Package Version 1.1.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.framework.hooks.bundle; version="[1.1,2.0)"}
+ *
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+
+ at Version("1.1")
+package org.osgi.framework.hooks.bundle;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/framework/hooks/bundle/packageinfo b/src/main/java/org/osgi/framework/hooks/bundle/packageinfo
new file mode 100644
index 0000000..3987f9c
--- /dev/null
+++ b/src/main/java/org/osgi/framework/hooks/bundle/packageinfo
@@ -0,0 +1 @@
+version 1.1
diff --git a/src/main/java/org/osgi/framework/hooks/resolver/ResolverHook.java b/src/main/java/org/osgi/framework/hooks/resolver/ResolverHook.java
index 51c46ec..f1d663f 100644
--- a/src/main/java/org/osgi/framework/hooks/resolver/ResolverHook.java
+++ b/src/main/java/org/osgi/framework/hooks/resolver/ResolverHook.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.
@@ -17,6 +17,7 @@
package org.osgi.framework.hooks.resolver;
import java.util.Collection;
+import org.osgi.annotation.versioning.ConsumerType;
import org.osgi.framework.Bundle;
import org.osgi.framework.namespace.BundleNamespace;
import org.osgi.framework.namespace.IdentityNamespace;
@@ -71,51 +72,47 @@ import org.osgi.framework.wiring.FrameworkWiring;
* <li>For each bundle revision {@code B} left in the shrinkable collection
* {@code Resolvable} and any bundle revision {@code B} which is currently
* resolved that represents a singleton bundle do the following:
- * <p/>
- * Determine the collection of available capabilities that have a namespace of
- * {@link IdentityNamespace osgi.identity}, are singletons, and have the same
+ * <ul>
+ * <li>Determine the collection of available capabilities that have a namespace
+ * of {@link IdentityNamespace osgi.identity}, are singletons, and have the same
* symbolic name as the singleton bundle revision {@code B} and place each of
- * the matching capabilities into a shrinkable collection {@code Collisions}.
- * <p/>
- * Remove the {@link IdentityNamespace osgi.identity} capability provided by
+ * the matching capabilities into a shrinkable collection {@code Collisions}.</li>
+ * <li>Remove the {@link IdentityNamespace osgi.identity} capability provided by
* bundle revision {@code B} from shrinkable collection {@code Collisions}. A
- * singleton bundle cannot collide with itself.
- * <p/>
- * For each resolver hook call the
+ * singleton bundle cannot collide with itself.</li>
+ * <li>For each resolver hook call the
* {@link #filterSingletonCollisions(BundleCapability, Collection)} with the
* {@link IdentityNamespace osgi.identity} capability provided by bundle
- * revision {@code B} and the shrinkable collection {@code Collisions}
- * <p/>
- * The shrinkable collection {@code Collisions} now contains all singleton
+ * revision {@code B} and the shrinkable collection {@code Collisions}</li>
+ * <li>The shrinkable collection {@code Collisions} now contains all singleton
* {@link IdentityNamespace osgi.identity} capabilities that can influence the
- * ability of bundle revision {@code B} to resolve.
- * <p/>
- * If the bundle revision {@code B} is already resolved then any resolvable
+ * ability of bundle revision {@code B} to resolve.</li>
+ * <li>If the bundle revision {@code B} is already resolved then any resolvable
* bundle revision contained in the collection {@code Collisions} is not allowed
* to resolve.</li>
+ * </ul>
+ * </li>
* <li>During a resolve process a framework is free to attempt to resolve any or
* all bundles contained in shrinkable collection {@code Resolvable}. For each
* bundle revision {@code B} left in the shrinkable collection
* {@code Resolvable} which the framework attempts to resolve the following
* steps must be followed:
- * <p/>
- * For each requirement {@code R} specified by bundle revision {@code B}
+ * <ul>
+ * <li>For each requirement {@code R} specified by bundle revision {@code B}
* determine the collection of capabilities that satisfy (or match) the
* requirement and place each matching capability into a shrinkable collection
* {@code Candidates}. A capability is considered to match a particular
* requirement if its attributes satisfy a specified requirement and the
- * requirer bundle has permission to access the capability.
- *
- * <p/>
- * For each resolver hook call the
+ * requirer bundle has permission to access the capability.</li>
+ * <li>For each resolver hook call the
* {@link #filterMatches(BundleRequirement, Collection)} with the requirement
- * {@code R} and the shrinkable collection {@code Candidates}.
- *
- * <p/>
- * The shrinkable collection {@code Candidates} now contains all the
+ * {@code R} and the shrinkable collection {@code Candidates}.</li>
+ * <li>The shrinkable collection {@code Candidates} now contains all the
* capabilities that may be used to satisfy the requirement {@code R}. Any other
* capabilities that got removed from the shrinkable collection
* {@code Candidates} must not be used to satisfy requirement {@code R}.</li>
+ * </ul>
+ * </li>
* <li>For each resolver hook call the {@link #end()} method to inform the hooks
* about a resolve process ending.</li>
* </ol>
@@ -134,8 +131,9 @@ import org.osgi.framework.wiring.FrameworkWiring;
*
* @see ResolverHookFactory
* @NotThreadSafe
- * @version $Id: 9d3ef6240aead0952b5a47b793780c1c0589089a $
+ * @author $Id: 7b2a0a5dbec7b0e999112ae324d050fcf190fa5d $
*/
+ at ConsumerType
public interface ResolverHook {
/**
* Filter resolvable candidates hook method. This method may be called
diff --git a/src/main/java/org/osgi/framework/hooks/resolver/ResolverHookFactory.java b/src/main/java/org/osgi/framework/hooks/resolver/ResolverHookFactory.java
index 91ce5f7..10f6e97 100644
--- a/src/main/java/org/osgi/framework/hooks/resolver/ResolverHookFactory.java
+++ b/src/main/java/org/osgi/framework/hooks/resolver/ResolverHookFactory.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.
@@ -17,6 +17,7 @@
package org.osgi.framework.hooks.resolver;
import java.util.Collection;
+import org.osgi.annotation.versioning.ConsumerType;
import org.osgi.framework.Bundle;
import org.osgi.framework.wiring.BundleRevision;
import org.osgi.framework.wiring.FrameworkWiring;
@@ -31,8 +32,9 @@ import org.osgi.framework.wiring.FrameworkWiring;
*
* @ThreadSafe
* @see ResolverHook
- * @version $Id: e0a2f3ad081c31bbb682fa366c15a3080bf6da2b $
+ * @author $Id: d073890a9814291f258c9326f720323d7f4d7d90 $
*/
+ at ConsumerType
public interface ResolverHookFactory {
/**
* This method is called by the framework each time a resolve process begins
diff --git a/src/main/java/org/osgi/framework/hooks/resolver/package-info.java b/src/main/java/org/osgi/framework/hooks/resolver/package-info.java
new file mode 100644
index 0000000..2f447ff
--- /dev/null
+++ b/src/main/java/org/osgi/framework/hooks/resolver/package-info.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ * 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.
+ */
+
+/**
+ * Framework Resolver Hooks 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.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.framework.hooks.resolver; version="[1.0,2.0)"}
+ *
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+
+ at Version("1.0")
+package org.osgi.framework.hooks.resolver;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/framework/hooks/resolver/packageinfo b/src/main/java/org/osgi/framework/hooks/resolver/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/src/main/java/org/osgi/framework/hooks/resolver/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/src/main/java/org/osgi/framework/hooks/service/EventHook.java b/src/main/java/org/osgi/framework/hooks/service/EventHook.java
index 03a84d4..3603e77 100644
--- a/src/main/java/org/osgi/framework/hooks/service/EventHook.java
+++ b/src/main/java/org/osgi/framework/hooks/service/EventHook.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2008, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2008, 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.
@@ -17,6 +17,7 @@
package org.osgi.framework.hooks.service;
import java.util.Collection;
+import org.osgi.annotation.versioning.ConsumerType;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceEvent;
@@ -29,9 +30,9 @@ import org.osgi.framework.ServiceEvent;
*
* @ThreadSafe
* @deprecated As of 1.1. Replaced by {@link EventListenerHook}.
- * @version $Id: 84757a5f719db4d7671e81a76af2b320404ae0f5 $
+ * @author $Id: b8c500c6f09cc25e3a6294489b7e6a1d458d5e6f $
*/
-
+ at ConsumerType
public interface EventHook {
/**
* Event hook method. This method is called prior to service event delivery
diff --git a/src/main/java/org/osgi/framework/hooks/service/EventListenerHook.java b/src/main/java/org/osgi/framework/hooks/service/EventListenerHook.java
index 534efc5..3230742 100644
--- a/src/main/java/org/osgi/framework/hooks/service/EventListenerHook.java
+++ b/src/main/java/org/osgi/framework/hooks/service/EventListenerHook.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.
@@ -18,6 +18,7 @@ package org.osgi.framework.hooks.service;
import java.util.Collection;
import java.util.Map;
+import org.osgi.annotation.versioning.ConsumerType;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.hooks.service.ListenerHook.ListenerInfo;
@@ -31,9 +32,9 @@ import org.osgi.framework.hooks.service.ListenerHook.ListenerInfo;
*
* @ThreadSafe
* @since 1.1
- * @version $Id: b0b99b29206f272ad479fa08ffcd5ef5fda909b8 $
+ * @author $Id: 2b80241ca24005be3a9a3550138e1ba9a3a9ad6e $
*/
-
+ at ConsumerType
public interface EventListenerHook {
/**
* Event listener hook method. This method is called prior to service event
diff --git a/src/main/java/org/osgi/framework/hooks/service/FindHook.java b/src/main/java/org/osgi/framework/hooks/service/FindHook.java
index 4cd467c..745a6b4 100644
--- a/src/main/java/org/osgi/framework/hooks/service/FindHook.java
+++ b/src/main/java/org/osgi/framework/hooks/service/FindHook.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2008, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2008, 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.
@@ -17,6 +17,7 @@
package org.osgi.framework.hooks.service;
import java.util.Collection;
+import org.osgi.annotation.versioning.ConsumerType;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
@@ -28,9 +29,9 @@ import org.osgi.framework.ServiceReference;
* (get service references) operations.
*
* @ThreadSafe
- * @version $Id: 45612d6a10a25ca0b40ba695eb8dba21c2c78c24 $
+ * @author $Id: 4325a49f8c29ac9e7f32e8450db26148bbda5642 $
*/
-
+ at ConsumerType
public interface FindHook {
/**
* Find hook method. This method is called during the service find operation
diff --git a/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java b/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java
index ef933c3..2f4cab9 100644
--- a/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java
+++ b/src/main/java/org/osgi/framework/hooks/service/ListenerHook.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2008, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2008, 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.
@@ -17,6 +17,8 @@
package org.osgi.framework.hooks.service;
import java.util.Collection;
+import org.osgi.annotation.versioning.ConsumerType;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.BundleContext;
/**
@@ -27,9 +29,9 @@ import org.osgi.framework.BundleContext;
* addition and removal.
*
* @ThreadSafe
- * @version $Id: 94029e2b70119793b3e7d77d6e1d5052d9ee1723 $
+ * @author $Id: 34bd086f723505e6ec22dadd9f0e47e92f80352b $
*/
-
+ at ConsumerType
public interface ListenerHook {
/**
* Added listeners hook method. This method is called to provide the hook
@@ -66,8 +68,8 @@ public interface ListenerHook {
* which added the Service Listener and the filter with which it was added.
*
* @ThreadSafe
- * @noimplement
*/
+ @ProviderType
public interface ListenerInfo {
/**
* Return the context of the bundle which added the listener.
diff --git a/src/main/java/org/osgi/framework/hooks/service/package-info.java b/src/main/java/org/osgi/framework/hooks/service/package-info.java
new file mode 100644
index 0000000..1cdd0e9
--- /dev/null
+++ b/src/main/java/org/osgi/framework/hooks/service/package-info.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ * 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.
+ */
+
+/**
+ * Framework Service Hooks Package Version 1.1.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.framework.hooks.service; version="[1.1,2.0)"}
+ *
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+
+ at Version("1.1")
+package org.osgi.framework.hooks.service;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/framework/hooks/service/packageinfo b/src/main/java/org/osgi/framework/hooks/service/packageinfo
new file mode 100644
index 0000000..3987f9c
--- /dev/null
+++ b/src/main/java/org/osgi/framework/hooks/service/packageinfo
@@ -0,0 +1 @@
+version 1.1
diff --git a/src/main/java/org/osgi/framework/hooks/weaving/WeavingException.java b/src/main/java/org/osgi/framework/hooks/weaving/WeavingException.java
index 8842797..254dd9b 100644
--- a/src/main/java/org/osgi/framework/hooks/weaving/WeavingException.java
+++ b/src/main/java/org/osgi/framework/hooks/weaving/WeavingException.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2010). 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.
@@ -23,7 +23,7 @@ package org.osgi.framework.hooks.weaving;
* <p>
* This exception conforms to the general purpose exception chaining mechanism.
*
- * @version $Id: eb38b85f6ed66ec445fb2f0ee7143df021327a9a $
+ * @author $Id: 7575fc1b015fea7c77397391df6c8d2085513e76 $
*/
public class WeavingException extends RuntimeException {
diff --git a/src/main/java/org/osgi/framework/hooks/weaving/WeavingHook.java b/src/main/java/org/osgi/framework/hooks/weaving/WeavingHook.java
index be57658..760b00c 100644
--- a/src/main/java/org/osgi/framework/hooks/weaving/WeavingHook.java
+++ b/src/main/java/org/osgi/framework/hooks/weaving/WeavingHook.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2010). 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.
@@ -16,6 +16,8 @@
package org.osgi.framework.hooks.weaving;
+import org.osgi.annotation.versioning.ConsumerType;
+
/**
* OSGi Framework Weaving Hook Service.
*
@@ -34,9 +36,9 @@ package org.osgi.framework.hooks.weaving;
* bytes as modified by previously called weaving hooks.
*
* @ThreadSafe
- * @version $Id: d1985029024baba2db1c56aab1e06ee953fd6365 $
+ * @author $Id: 8d99df5b0f3e7ffa9573695923afe86de9835fde $
*/
-
+ at ConsumerType
public interface WeavingHook {
/**
* Weaving hook method.
diff --git a/src/main/java/org/osgi/framework/hooks/weaving/WovenClass.java b/src/main/java/org/osgi/framework/hooks/weaving/WovenClass.java
index 697a435..a7e131c 100644
--- a/src/main/java/org/osgi/framework/hooks/weaving/WovenClass.java
+++ b/src/main/java/org/osgi/framework/hooks/weaving/WovenClass.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.
@@ -18,6 +18,7 @@ package org.osgi.framework.hooks.weaving;
import java.security.ProtectionDomain;
import java.util.List;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.wiring.BundleWiring;
/**
@@ -29,25 +30,92 @@ import org.osgi.framework.wiring.BundleWiring;
* should be added to the bundle as dynamic imports.
*
* <p>
- * After weaving is {@link #isWeavingComplete() complete}, this object becomes
- * effectively immutable.
+ * Upon entering one of the terminal states, this object becomes effectively
+ * immutable.
*
* @NotThreadSafe
- * @noimplement
- * @version $Id: 549caef41027c8f0d0fdb4deae756eae6b69d1ee $
+ * @author $Id: b86db7713c738ae7147fe86f754302e2e324676b $
*/
+ at ProviderType
public interface WovenClass {
+ /**
+ * The woven class is being transformed.
+ *
+ * <p>
+ * The woven class is in this state while {@link WeavingHook weaving hooks}
+ * are being called. The woven class is mutable so the {@link #getBytes()
+ * class bytes} may be {@link #setBytes(byte[]) modified} and
+ * {@link #getDynamicImports() dynamic imports} may be added. If a weaving
+ * hook throws an exception the state transitions to
+ * {@link #TRANSFORMING_FAILED}. Otherwise, after the last weaving hook has
+ * been successfully called, the state transitions to {@link #TRANSFORMED}.
+ *
+ * @since 1.1
+ */
+ int TRANSFORMING = 0x00000001;
+
+ /**
+ * The woven class has been transformed.
+ *
+ * <p>
+ * The woven class is in this state after {@link WeavingHook weaving hooks}
+ * have been called and before the class is defined. The woven class cannot
+ * be further transformed. The woven class is in this state while defining
+ * the class. If a failure occurs while defining the class, the state
+ * transitions to {@link #DEFINE_FAILED}. Otherwise, after the class has
+ * been defined, the state transitions to {@link #DEFINED}.
+ *
+ * @since 1.1
+ */
+ int TRANSFORMED = 0x00000002;
+
+ /**
+ * The woven class has been defined.
+ * <p>
+ * The woven class is in this state after the class is defined. The woven
+ * class cannot be further transformed. This is a terminal state. Upon
+ * entering this state, this object is effectively immutable, the
+ * {@link #getBundleWiring() bundle wiring} has been updated with the
+ * {@link #getDynamicImports() dynamic import requirements} and the class
+ * has been {@link #getDefinedClass() defined}.
+ *
+ * @since 1.1
+ */
+ int DEFINED = 0x00000004;
+
+ /**
+ * The woven class failed to transform.
+ * <p>
+ * The woven class is in this state if a {@link WeavingHook weaving hook}
+ * threw an exception. The woven class cannot be further transformed or
+ * defined. This is a terminal state. Upon entering this state, this object
+ * is effectively immutable.
+ *
+ * @since 1.1
+ */
+ int TRANSFORMING_FAILED = 0x00000008;
+
+ /**
+ * The woven class failed to define.
+ * <p>
+ * The woven class is in this state when a failure occurs while defining the
+ * class. The woven class cannot be further transformed or defined. This is
+ * a terminal state. Upon entering this state, this object is effectively
+ * immutable.
+ *
+ * @since 1.1
+ */
+ int DEFINE_FAILED = 0x00000010;
/**
* Returns the class file bytes to be used to define the
* {@link WovenClass#getClassName() named} class.
*
* <p>
- * While weaving is not {@link #isWeavingComplete() complete}, this method
- * returns a reference to the class files byte array contained in this
- * object. After weaving is {@link #isWeavingComplete() complete}, this
- * object becomes effectively immutable and a copy of the class file byte
- * array is returned.
+ * While in the {@link #TRANSFORMING} state, this method returns a reference
+ * to the class files byte array contained in this object. After leaving the
+ * {@link #TRANSFORMING} state, this woven class can no longer be
+ * transformed and a copy of the class file byte array is returned.
*
* @return The bytes to be used to define the
* {@link WovenClass#getClassName() named} class.
@@ -64,10 +132,10 @@ public interface WovenClass {
* weave} method by the framework.
*
* <p>
- * While weaving is not {@link #isWeavingComplete() complete}, this method
- * replaces the reference to the array contained in this object with the
- * specified array. After weaving is {@link #isWeavingComplete() complete},
- * this object becomes effectively immutable and this method will throw an
+ * While in the {@link #TRANSFORMING} state, this method replaces the
+ * reference to the array contained in this object with the specified array.
+ * After leaving the {@link #TRANSFORMING} state, this woven class can no
+ * longer be transformed and this method will throw an
* {@link IllegalStateException}.
*
* @param newBytes The new classfile that will be used to define the
@@ -75,8 +143,9 @@ public interface WovenClass {
* is retained by this object and the caller must not modify the
* specified array.
* @throws NullPointerException If newBytes is {@code null}.
- * @throws IllegalStateException If weaving is {@link #isWeavingComplete()
- * complete}.
+ * @throws IllegalStateException If state is {@link #TRANSFORMED},
+ * {@link #DEFINED}, {@link #TRANSFORMING_FAILED} or
+ * {@link #DEFINE_FAILED}.
* @throws SecurityException If the caller does not have
* {@code AdminPermission[bundle,WEAVE]} and the Java runtime
* environment supports permissions.
@@ -92,12 +161,14 @@ public interface WovenClass {
* weave} method by the framework.
*
* <p>
- * After weaving is {@link #isWeavingComplete() complete}, this object
- * becomes effectively immutable and the returned list will be unmodifiable.
+ * After leaving the {@link #TRANSFORMING} state, this woven class can no
+ * longer be transformed and the returned list will be unmodifiable.
*
* <p>
- * If the Java runtime environment supports permissions, the caller must
- * have {@code AdminPermission[bundle,WEAVE]} to modify the returned list.
+ * If the Java runtime environment supports permissions, any modification to
+ * the returned list requires {@code AdminPermission[bundle,WEAVE]}.
+ * Additionally, any add or set modification requires
+ * {@code PackagePermission[package,IMPORT]}.
*
* @return A list containing zero or more dynamic import package
* descriptions to add to the bundle wiring for this woven class.
@@ -109,13 +180,11 @@ public interface WovenClass {
/**
* Returns whether weaving is complete in this woven class. Weaving is
- * complete after the last {@link WeavingHook weaving hook} is called and
- * the class is defined.
- *
- * <p>
- * After weaving is complete, this object becomes effectively immutable.
+ * complete after the class is defined.
*
- * @return {@code true} weaving is complete, {@code false} otherwise.
+ * @return {@code true} if {@link #getState() state} is {@link #DEFINED},
+ * {@link #TRANSFORMING_FAILED} or {@link #DEFINE_FAILED};
+ * {@code false} otherwise.
*/
public boolean isWeavingComplete();
@@ -154,4 +223,16 @@ public interface WovenClass {
* @return The bundle wiring whose class loader will define the woven class.
*/
public BundleWiring getBundleWiring();
+
+ /**
+ * Returns the current state of this woven class.
+ * <p>
+ * A woven class can be in only one state at any time.
+ *
+ * @return Either {@link #TRANSFORMING}, {@link #TRANSFORMED},
+ * {@link #DEFINED}, {@link #TRANSFORMING_FAILED} or
+ * {@link #DEFINE_FAILED}.
+ * @since 1.1
+ */
+ public int getState();
}
diff --git a/src/main/java/org/osgi/framework/hooks/weaving/WovenClassListener.java b/src/main/java/org/osgi/framework/hooks/weaving/WovenClassListener.java
new file mode 100644
index 0000000..915b249
--- /dev/null
+++ b/src/main/java/org/osgi/framework/hooks/weaving/WovenClassListener.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.hooks.weaving;
+
+import org.osgi.annotation.versioning.ConsumerType;
+
+/**
+ * Woven Class Listener Service.
+ *
+ * <p>
+ * Bundles registering this service will receive notifications whenever a
+ * {@link WovenClass woven class} completes a {@link WovenClass#getState()
+ * state} transition. Woven Class Listeners are not able to modify the woven
+ * class in contrast with {@link WeavingHook weaving hooks}.
+ *
+ * <p>
+ * Receiving a woven class in the {@link WovenClass#TRANSFORMED TRANSFORMED}
+ * state allows listeners to observe the modified {@link WovenClass#getBytes()
+ * byte codes} before the class has been {@link WovenClass#DEFINED DEFINED} as
+ * well as the additional {@link WovenClass#getDynamicImports() dynamic imports}
+ * before the {@link WovenClass#getBundleWiring() bundle wiring} has been
+ * updated.
+ *
+ * <p>
+ * Woven class listeners are synchronously {@link #modified(WovenClass) called}
+ * when a woven class completes a state transition. The woven class processing
+ * will not proceed until all woven class listeners are done.
+ *
+ * <p>
+ * If the Java runtime environment supports permissions, the caller must have
+ * {@code ServicePermission[WovenClassListener,REGISTER]} in order to register a
+ * listener.
+ *
+ * @ThreadSafe
+ * @since 1.1
+ * @author $Id: WovenClassListener.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+ at ConsumerType
+public interface WovenClassListener {
+ /**
+ * Receives notification that a {@link WovenClass woven class} has completed
+ * a state transition.
+ *
+ * <p>
+ * The listener will be notified when a woven class has entered the
+ * {@link WovenClass#TRANSFORMED TRANSFORMED}, {@link WovenClass#DEFINED
+ * DEFINED}, {@link WovenClass#TRANSFORMING_FAILED TRANSFORMING_FAILED} and
+ * {@link WovenClass#DEFINE_FAILED DEFINE_FAILED} states.
+ *
+ * <p>
+ * If this method throws any exception, the Framework must log the exception
+ * but otherwise ignore it.
+ *
+ * @param wovenClass The woven class that completed a state transition.
+ */
+ public void modified(WovenClass wovenClass);
+}
diff --git a/src/main/java/org/osgi/framework/hooks/weaving/package-info.java b/src/main/java/org/osgi/framework/hooks/weaving/package-info.java
new file mode 100644
index 0000000..05810dd
--- /dev/null
+++ b/src/main/java/org/osgi/framework/hooks/weaving/package-info.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ * 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.
+ */
+
+/**
+ * Framework Weaving Hooks Package Version 1.1.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest.
+ * </p>
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * </p>
+ * <p>
+ * {@code Import-Package: org.osgi.framework.hooks.weaving; version="[1.1,2.0)"}
+ * </p>
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+
+ at Version("1.1")
+package org.osgi.framework.hooks.weaving;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/framework/hooks/weaving/packageinfo b/src/main/java/org/osgi/framework/hooks/weaving/packageinfo
new file mode 100644
index 0000000..3987f9c
--- /dev/null
+++ b/src/main/java/org/osgi/framework/hooks/weaving/packageinfo
@@ -0,0 +1 @@
+version 1.1
diff --git a/src/main/java/org/osgi/framework/launch/Framework.java b/src/main/java/org/osgi/framework/launch/Framework.java
index 54d599b..125e581 100644
--- a/src/main/java/org/osgi/framework/launch/Framework.java
+++ b/src/main/java/org/osgi/framework/launch/Framework.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2008, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2008, 2014). 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,10 +19,12 @@ package org.osgi.framework.launch;
import java.io.InputStream;
import java.net.URL;
import java.util.Enumeration;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
import org.osgi.framework.FrameworkEvent;
+import org.osgi.framework.FrameworkListener;
/**
* A Framework instance. A Framework is also known as a System Bundle.
@@ -33,12 +35,29 @@ import org.osgi.framework.FrameworkEvent;
* instance.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: e76240d5de584d1666880d9bc358571a76cbd8fb $
+ * @author $Id: 25b603f31ba381c47a8db8a9f2e006e13588877a $
*/
+ at ProviderType
public interface Framework extends Bundle {
/**
+ * Initialize this Framework.
+ * <p>
+ * This method performs the same function as calling
+ * {@link #init(FrameworkListener...)} with no framework listeners.
+ *
+ * @throws BundleException If this Framework could not be initialized.
+ * @throws SecurityException If the Java Runtime Environment supports
+ * permissions and the caller does not have the appropriate
+ * {@code AdminPermission[this,EXECUTE]} or if there is a security
+ * manager already installed and the
+ * {@link Constants#FRAMEWORK_SECURITY} configuration property is
+ * set.
+ * @see #init(FrameworkListener...)
+ */
+ void init() throws BundleException;
+
+ /**
* Initialize this Framework. After calling this method, this Framework
* must:
* <ul>
@@ -53,6 +72,8 @@ public interface Framework extends Bundle {
* {@code ConditionalPermissionAdmin}.</li>
* <li>Be {@link #adapt(Class) adaptable} to the OSGi defined types to which
* a system bundle can be adapted.</li>
+ * <li>Have called the {@code start} method of the extension bundle
+ * activator for all resolved extension bundles.</li>
* </ul>
*
* <p>
@@ -63,6 +84,17 @@ public interface Framework extends Bundle {
* This method does nothing if called when this Framework is in the
* {@link #STARTING}, {@link #ACTIVE} or {@link #STOPPING} states.
*
+ * <p>
+ * All framework events fired by this method method are also delivered to
+ * the specified FrameworkListeners in the order they are specified before
+ * returning from this method. After returning from this method the
+ * specified listeners are no longer notified of framework events.
+ *
+ * @param listeners Zero or more listeners to be notified when framework
+ * events occur while initializing the framework. The specified
+ * listeners do not need to be otherwise registered with the
+ * framework. If a specified listener is registered with the
+ * framework, it will be notified twice for each framework event.
* @throws BundleException If this Framework could not be initialized.
* @throws SecurityException If the Java Runtime Environment supports
* permissions and the caller does not have the appropriate
@@ -70,9 +102,9 @@ public interface Framework extends Bundle {
* manager already installed and the
* {@link Constants#FRAMEWORK_SECURITY} configuration property is
* set.
- *
+ * @since 1.2
*/
- void init() throws BundleException;
+ void init(FrameworkListener... listeners) throws BundleException;
/**
* Wait until this Framework has completely stopped. The {@code stop} and
@@ -328,6 +360,20 @@ public interface Framework extends Bundle {
URL getEntry(String path);
/**
+ * Returns the time when the set of bundles in this framework was last
+ * modified. The set of bundles is considered to be modified when a bundle
+ * is installed, updated or uninstalled.
+ *
+ * <p>
+ * The time value is the number of milliseconds since January 1, 1970,
+ * 00:00:00 UTC.
+ *
+ * @return The time when the set of bundles in this framework was last
+ * modified.
+ */
+ long getLastModified();
+
+ /**
* Returns {@code null} as a framework implementation does not have a proper
* bundle from which to return entries.
*
diff --git a/src/main/java/org/osgi/framework/launch/FrameworkFactory.java b/src/main/java/org/osgi/framework/launch/FrameworkFactory.java
index bac0183..6d656d3 100644
--- a/src/main/java/org/osgi/framework/launch/FrameworkFactory.java
+++ b/src/main/java/org/osgi/framework/launch/FrameworkFactory.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2009, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2009, 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.
@@ -17,6 +17,7 @@
package org.osgi.framework.launch;
import java.util.Map;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.Bundle;
/**
@@ -44,9 +45,9 @@ import org.osgi.framework.Bundle;
* the resource.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: 1684e14aa98a1f6e1ff3e0f3afa2c55982210f72 $
+ * @author $Id: c1647bcb8416b6dfa9e37c6cc146bb54c7173526 $
*/
+ at ProviderType
public interface FrameworkFactory {
/**
diff --git a/src/main/java/org/osgi/framework/BundleReference.java b/src/main/java/org/osgi/framework/launch/package-info.java
similarity index 50%
copy from src/main/java/org/osgi/framework/BundleReference.java
copy to src/main/java/org/osgi/framework/launch/package-info.java
index 97340f7..ca81049 100644
--- a/src/main/java/org/osgi/framework/BundleReference.java
+++ b/src/main/java/org/osgi/framework/launch/package-info.java
@@ -1,6 +1,6 @@
/*
- * Copyright (c) OSGi Alliance (2009, 2010). All Rights Reserved.
- *
+ * Copyright (c) OSGi Alliance (2010, 2014). 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
@@ -14,23 +14,23 @@
* limitations under the License.
*/
-package org.osgi.framework;
-
/**
- * A reference to a Bundle.
- *
- * @since 1.5
- * @ThreadSafe
- * @noimplement
- * @version $Id: e61bd3e020264b04022a430fe09a85ee3aabf1a3 $
+ * Framework Launch Package Version 1.2.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.framework.launch; version="[1.2,2.0)"}
+ *
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
*/
-public interface BundleReference {
- /**
- * Returns the {@code Bundle} object associated with this
- * {@code BundleReference}.
- *
- * @return The {@code Bundle} object associated with this
- * {@code BundleReference}.
- */
- public Bundle getBundle();
-}
+
+ at Version("1.2")
+package org.osgi.framework.launch;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/framework/launch/packageinfo b/src/main/java/org/osgi/framework/launch/packageinfo
new file mode 100644
index 0000000..ef7df68
--- /dev/null
+++ b/src/main/java/org/osgi/framework/launch/packageinfo
@@ -0,0 +1 @@
+version 1.2
diff --git a/src/main/java/org/osgi/framework/namespace/AbstractWiringNamespace.java b/src/main/java/org/osgi/framework/namespace/AbstractWiringNamespace.java
index 52563e2..c5186a1 100644
--- a/src/main/java/org/osgi/framework/namespace/AbstractWiringNamespace.java
+++ b/src/main/java/org/osgi/framework/namespace/AbstractWiringNamespace.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.
@@ -16,6 +16,7 @@
package org.osgi.framework.namespace;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.resource.Namespace;
/**
@@ -31,8 +32,9 @@ import org.osgi.resource.Namespace;
* otherwise indicated.
*
* @Immutable
- * @version $Id: 383e84df9190757ce6bb6fb722e80a3b7d6b68da $
+ * @author $Id: 6bbd0ddefc452b0ace2f43ec3aa67a687adcf03c $
*/
+ at ProviderType
public abstract class AbstractWiringNamespace extends Namespace {
/**
diff --git a/src/main/java/org/osgi/framework/namespace/BundleNamespace.java b/src/main/java/org/osgi/framework/namespace/BundleNamespace.java
index 84b6700..59e36cb 100644
--- a/src/main/java/org/osgi/framework/namespace/BundleNamespace.java
+++ b/src/main/java/org/osgi/framework/namespace/BundleNamespace.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.
@@ -66,7 +66,7 @@ import org.osgi.resource.Namespace;
* capability.
*
* @Immutable
- * @version $Id: 339f1204725aa9d9c2463b1224b2e38e505024e9 $
+ * @author $Id: 2672d40cf3705b2cf21d01530e4bdfa2cdc61764 $
*/
public final class BundleNamespace extends AbstractWiringNamespace {
diff --git a/src/main/java/org/osgi/framework/namespace/ExecutionEnvironmentNamespace.java b/src/main/java/org/osgi/framework/namespace/ExecutionEnvironmentNamespace.java
index 5328cae..a3f79a0 100644
--- a/src/main/java/org/osgi/framework/namespace/ExecutionEnvironmentNamespace.java
+++ b/src/main/java/org/osgi/framework/namespace/ExecutionEnvironmentNamespace.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.
@@ -29,7 +29,7 @@ import org.osgi.resource.Namespace;
* {@code String}, unless otherwise indicated.
*
* @Immutable
- * @version $Id: e1c30aac8efacc1b21ab20ffebcc1af30a1054a8 $
+ * @author $Id: 45a233050d35a5debc8a7d1be1f7e81178916984 $
*/
public final class ExecutionEnvironmentNamespace extends Namespace {
diff --git a/src/main/java/org/osgi/framework/namespace/HostNamespace.java b/src/main/java/org/osgi/framework/namespace/HostNamespace.java
index 5964cf5..28f7c1d 100644
--- a/src/main/java/org/osgi/framework/namespace/HostNamespace.java
+++ b/src/main/java/org/osgi/framework/namespace/HostNamespace.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.
@@ -66,7 +66,7 @@ import org.osgi.resource.Namespace;
* capability.
*
* @Immutable
- * @version $Id: aa3cc744c7b9c21d908260f456567ab8a6de1430 $
+ * @author $Id: a7cbf04c393bfaaa7515804a8ab6b9ebfd72fbe5 $
*/
public final class HostNamespace extends AbstractWiringNamespace {
@@ -132,7 +132,7 @@ public final class HostNamespace extends AbstractWiringNamespace {
/**
* The requirement directive used to specify the type of the extension
- * fragment.
+ * fragment. The default value is {@link #EXTENSION_FRAMEWORK framework}.
*
* @see #EXTENSION_FRAMEWORK
* @see #EXTENSION_BOOTCLASSPATH
diff --git a/src/main/java/org/osgi/framework/namespace/IdentityNamespace.java b/src/main/java/org/osgi/framework/namespace/IdentityNamespace.java
index c925e5a..cfbb843 100644
--- a/src/main/java/org/osgi/framework/namespace/IdentityNamespace.java
+++ b/src/main/java/org/osgi/framework/namespace/IdentityNamespace.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.
@@ -41,7 +41,7 @@ import org.osgi.resource.Namespace;
* capability.
*
* @Immutable
- * @version $Id: e34dcaba1f828326a0db13b3d811b2d170ff97a5 $
+ * @author $Id: 7bc7a11c45b30538ffbb7572c4539f6160557684 $
*/
public final class IdentityNamespace extends Namespace {
diff --git a/src/main/java/org/osgi/framework/namespace/NativeNamespace.java b/src/main/java/org/osgi/framework/namespace/NativeNamespace.java
new file mode 100644
index 0000000..816aa2d
--- /dev/null
+++ b/src/main/java/org/osgi/framework/namespace/NativeNamespace.java
@@ -0,0 +1,81 @@
+/*
+ * 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.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.namespace;
+
+import org.osgi.framework.Constants;
+import org.osgi.resource.Namespace;
+
+/**
+ * Native 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
+ * @author $Id: NativeNamespace.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+public final class NativeNamespace extends Namespace {
+
+ /**
+ * Namespace name for native capabilities and requirements.
+ */
+ public static final String NATIVE_NAMESPACE = "osgi.native";
+
+ /**
+ * The capability attribute contains alias values of the
+ * {@link Constants#FRAMEWORK_OS_NAME org.osgi.framework.os.name} launching
+ * property value according to the <a
+ * href="http://www.osgi.org/Specifications/Reference">OSGi Specification
+ * References</a>. The value of this attribute must be of type
+ * {@code List<String>}.
+ */
+ public final static String CAPABILITY_OSNAME_ATTRIBUTE = NATIVE_NAMESPACE + ".osname";
+
+ /**
+ * The capability attribute contains a {@code Version} parsed from the
+ * {@link Constants#FRAMEWORK_OS_VERSION org.osgi.framework.os.version}
+ * launching property value. The value of this attribute must be of type
+ * {@code Version}.
+ */
+ public final static String CAPABILITY_OSVERSION_ATTRIBUTE = NATIVE_NAMESPACE + ".osversion";
+
+ /**
+ * The capability attribute contains alias values of the
+ * {@link Constants#FRAMEWORK_PROCESSOR org.osgi.framework.processor}
+ * launching property value according to the <a
+ * href="http://www.osgi.org/Specifications/Reference">OSGi Specification
+ * References</a>. The value of this attribute must be of type
+ * {@code List<String>}.
+ */
+ public final static String CAPABILITY_PROCESSOR_ATTRIBUTE = NATIVE_NAMESPACE + ".processor";
+
+ /**
+ * The capability attribute contains the
+ * {@link Constants#FRAMEWORK_LANGUAGE org.osgi.framework.language}
+ * launching property value. The value of this attribute must be of type
+ * {@code String}.
+ */
+ public final static String CAPABILITY_LANGUAGE_ATTRIBUTE = NATIVE_NAMESPACE + ".language";
+
+ private NativeNamespace() {
+ // empty
+ }
+}
diff --git a/src/main/java/org/osgi/framework/namespace/PackageNamespace.java b/src/main/java/org/osgi/framework/namespace/PackageNamespace.java
index 2d1cbc3..9f7114c 100644
--- a/src/main/java/org/osgi/framework/namespace/PackageNamespace.java
+++ b/src/main/java/org/osgi/framework/namespace/PackageNamespace.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.
@@ -59,7 +59,7 @@ import org.osgi.resource.Namespace;
* </ul>
*
* @Immutable
- * @version $Id: 5adc45bd1ae26120cbff3562c7c8cefc01e38bd3 $
+ * @author $Id: 5f241fb0804d477ab8f2d33f247d45e62caf72df $
*/
public final class PackageNamespace extends AbstractWiringNamespace {
diff --git a/src/main/java/org/osgi/framework/BundleReference.java b/src/main/java/org/osgi/framework/namespace/package-info.java
similarity index 54%
copy from src/main/java/org/osgi/framework/BundleReference.java
copy to src/main/java/org/osgi/framework/namespace/package-info.java
index 97340f7..7d661e3 100644
--- a/src/main/java/org/osgi/framework/BundleReference.java
+++ b/src/main/java/org/osgi/framework/namespace/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2009, 2010). 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.
@@ -14,23 +14,19 @@
* limitations under the License.
*/
-package org.osgi.framework;
-
/**
- * A reference to a Bundle.
+ * Namespace Package Version 1.1.
+ *
+ * <p>
+ * Bundles should not need to import this package at runtime since all
+ * the types in this package just contain constants for capability and
+ * requirement namespaces specified by the OSGi Alliance.
*
- * @since 1.5
- * @ThreadSafe
- * @noimplement
- * @version $Id: e61bd3e020264b04022a430fe09a85ee3aabf1a3 $
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
*/
-public interface BundleReference {
- /**
- * Returns the {@code Bundle} object associated with this
- * {@code BundleReference}.
- *
- * @return The {@code Bundle} object associated with this
- * {@code BundleReference}.
- */
- public Bundle getBundle();
-}
+
+ at Version("1.1")
+package org.osgi.framework.namespace;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/framework/namespace/packageinfo b/src/main/java/org/osgi/framework/namespace/packageinfo
new file mode 100644
index 0000000..3987f9c
--- /dev/null
+++ b/src/main/java/org/osgi/framework/namespace/packageinfo
@@ -0,0 +1 @@
+version 1.1
diff --git a/src/main/java/org/osgi/framework/BundleReference.java b/src/main/java/org/osgi/framework/package-info.java
similarity index 54%
copy from src/main/java/org/osgi/framework/BundleReference.java
copy to src/main/java/org/osgi/framework/package-info.java
index 97340f7..3428139 100644
--- a/src/main/java/org/osgi/framework/BundleReference.java
+++ b/src/main/java/org/osgi/framework/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2009, 2010). 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.
@@ -14,23 +14,23 @@
* limitations under the License.
*/
-package org.osgi.framework;
-
/**
- * A reference to a Bundle.
+ * Framework Package Version 1.8.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.framework; version="[1.8,2.0)"}
*
- * @since 1.5
- * @ThreadSafe
- * @noimplement
- * @version $Id: e61bd3e020264b04022a430fe09a85ee3aabf1a3 $
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
*/
-public interface BundleReference {
- /**
- * Returns the {@code Bundle} object associated with this
- * {@code BundleReference}.
- *
- * @return The {@code Bundle} object associated with this
- * {@code BundleReference}.
- */
- public Bundle getBundle();
-}
+
+ at Version("1.8")
+package org.osgi.framework;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/framework/packageinfo b/src/main/java/org/osgi/framework/packageinfo
new file mode 100644
index 0000000..ed9885d
--- /dev/null
+++ b/src/main/java/org/osgi/framework/packageinfo
@@ -0,0 +1 @@
+version 1.8
diff --git a/src/main/java/org/osgi/framework/startlevel/BundleStartLevel.java b/src/main/java/org/osgi/framework/startlevel/BundleStartLevel.java
index d22d3ef..44e3c45 100644
--- a/src/main/java/org/osgi/framework/startlevel/BundleStartLevel.java
+++ b/src/main/java/org/osgi/framework/startlevel/BundleStartLevel.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2010). 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.
@@ -16,6 +16,7 @@
package org.osgi.framework.startlevel;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
@@ -29,9 +30,9 @@ import org.osgi.framework.BundleReference;
* calling {@link BundleReference#getBundle()}.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: 9a000be191fe3cb4ae82535a30940db0340d5356 $
+ * @author $Id: 421ffd6e9c48cda1bcd28c62e9ace1c05852f112 $
*/
+ at ProviderType
public interface BundleStartLevel extends BundleReference {
/**
* Return the assigned start level value for the bundle.
diff --git a/src/main/java/org/osgi/framework/startlevel/FrameworkStartLevel.java b/src/main/java/org/osgi/framework/startlevel/FrameworkStartLevel.java
index 11a8049..632c94c 100644
--- a/src/main/java/org/osgi/framework/startlevel/FrameworkStartLevel.java
+++ b/src/main/java/org/osgi/framework/startlevel/FrameworkStartLevel.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2002, 2011). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 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.
@@ -16,6 +16,7 @@
package org.osgi.framework.startlevel;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
import org.osgi.framework.FrameworkListener;
@@ -32,9 +33,9 @@ import org.osgi.framework.FrameworkListener;
* obtained by calling {@link BundleReference#getBundle()}.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: 12c6f60842df994c7de2cc3cfd02f791b95fc35b $
+ * @author $Id: de8d10036e85359428ca3e14bbe9b2c6d448fb93 $
*/
+ at ProviderType
public interface FrameworkStartLevel extends BundleReference {
/**
* Return the active start level value of the Framework.
@@ -69,13 +70,13 @@ public interface FrameworkStartLevel extends BundleReference {
* At each intermediate start level value on the way to and including the
* target start level, the Framework must:
* <ol>
- * <li>Change the active start level to the intermediate start level value.
+ * <li>Change the active start level to the intermediate start level value.</li>
* <li>Start bundles at the intermediate start level whose autostart setting
* indicate they must be started. They are started as described in the
* {@link Bundle#start(int)} method using the {@link Bundle#START_TRANSIENT}
* option. The {@link Bundle#START_ACTIVATION_POLICY} option must also be
* used if {@link BundleStartLevel#isActivationPolicyUsed()} returns
- * {@code true} for the bundle.
+ * {@code true} for the bundle.</li>
* </ol>
* When this process completes after the specified start level is reached,
* the Framework will fire a Framework event of type
@@ -92,8 +93,8 @@ public interface FrameworkStartLevel extends BundleReference {
* <ol>
* <li>Stop bundles at the intermediate start level as described in the
* {@link Bundle#stop(int)} method using the {@link Bundle#STOP_TRANSIENT}
- * option.
- * <li>Change the active start level to the intermediate start level value.
+ * option.</li>
+ * <li>Change the active start level to the intermediate start level value.</li>
* </ol>
* When this process completes after the specified start level is reached,
* the Framework will fire a Framework event of type
diff --git a/src/main/java/org/osgi/framework/startlevel/dto/BundleStartLevelDTO.java b/src/main/java/org/osgi/framework/startlevel/dto/BundleStartLevelDTO.java
new file mode 100644
index 0000000..f430124
--- /dev/null
+++ b/src/main/java/org/osgi/framework/startlevel/dto/BundleStartLevelDTO.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.startlevel.dto;
+
+import org.osgi.dto.DTO;
+import org.osgi.framework.startlevel.BundleStartLevel;
+
+/**
+ * Data Transfer Object for a BundleStartLevel.
+ *
+ * <p>
+ * An installed Bundle can be adapted to provide a {@code BundleStartLevelDTO}
+ * for the Bundle.
+ *
+ * @author $Id: BundleStartLevelDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class BundleStartLevelDTO extends DTO {
+ /**
+ * The id of the bundle associated with this start level.
+ *
+ * @see BundleStartLevel#getBundle()
+ */
+ public long bundle;
+
+ /**
+ * The assigned start level value for the bundle.
+ *
+ * @see BundleStartLevel#getStartLevel()
+ */
+ public int startLevel;
+
+ /**
+ * The bundle's autostart setting indicates that the activation policy
+ * declared in the bundle manifest must be used.
+ *
+ * @see BundleStartLevel#isActivationPolicyUsed()
+ */
+ public boolean activationPolicyUsed;
+
+ /**
+ * The bundle's autostart setting indicates it must be started.
+ *
+ * @see BundleStartLevel#isPersistentlyStarted()
+ */
+ public boolean persistentlyStarted;
+}
diff --git a/src/main/java/org/osgi/framework/startlevel/dto/FrameworkStartLevelDTO.java b/src/main/java/org/osgi/framework/startlevel/dto/FrameworkStartLevelDTO.java
new file mode 100644
index 0000000..0ea44fe
--- /dev/null
+++ b/src/main/java/org/osgi/framework/startlevel/dto/FrameworkStartLevelDTO.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.startlevel.dto;
+
+import org.osgi.dto.DTO;
+import org.osgi.framework.startlevel.FrameworkStartLevel;
+
+/**
+ * Data Transfer Object for a FrameworkStartLevel.
+ *
+ * <p>
+ * The System Bundle can be adapted to provide a {@code FrameworkStartLevelDTO}
+ * for the framework of the Bundle.
+ *
+ * @author $Id: FrameworkStartLevelDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class FrameworkStartLevelDTO extends DTO {
+ /**
+ * The active start level value for the framework.
+ *
+ * @see FrameworkStartLevel#getStartLevel()
+ */
+ public int startLevel;
+
+ /**
+ * The initial start level value that is assigned to a bundle when it is
+ * first installed.
+ *
+ * @see FrameworkStartLevel#getInitialBundleStartLevel()
+ */
+ public int initialBundleStartLevel;
+}
diff --git a/src/main/java/org/osgi/framework/startlevel/dto/package-info.java b/src/main/java/org/osgi/framework/startlevel/dto/package-info.java
new file mode 100644
index 0000000..2ef56ec
--- /dev/null
+++ b/src/main/java/org/osgi/framework/startlevel/dto/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). 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.
+ */
+
+/**
+ * OSGi Data Transfer Object Framework Start Level 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.framework.startlevel.dto; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.framework.startlevel.dto; version="[1.0,1.1)"}
+ *
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+
+ at Version("1.0")
+package org.osgi.framework.startlevel.dto;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/framework/startlevel/dto/packageinfo b/src/main/java/org/osgi/framework/startlevel/dto/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/src/main/java/org/osgi/framework/startlevel/dto/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/src/main/java/org/osgi/framework/startlevel/package-info.java b/src/main/java/org/osgi/framework/startlevel/package-info.java
new file mode 100644
index 0000000..14618ed
--- /dev/null
+++ b/src/main/java/org/osgi/framework/startlevel/package-info.java
@@ -0,0 +1,83 @@
+/*
+ * 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.
+ * 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.
+ */
+
+/**
+ * Framework Start Level Package Version 1.0.
+ *
+ * <p>
+ * The Framework Start Level package allows management agents to manage a start
+ * level assigned to each bundle and the active start level of the Framework.
+ * This package is a replacement for the now deprecated
+ * {@code org.osgi.service.startlevel} package.
+ *
+ * <p>
+ * A start level is defined to be a state of execution in which the Framework
+ * exists. Start level values are defined as unsigned integers with 0 (zero)
+ * being the state where the Framework is not launched. Progressively higher
+ * integral values represent progressively higher start levels. For example, 2
+ * is a higher start level than 1.
+ *
+ * <p>
+ * {@code AdminPermission} is required to modify start level information.
+ *
+ * <p>
+ * Start Level support in the Framework includes the ability to modify the
+ * active start level of the Framework and to assign a specific start level to a
+ * bundle. The beginning start level of a Framework is specified via the
+ * {@link org.osgi.framework.Constants#FRAMEWORK_BEGINNING_STARTLEVEL} framework
+ * property when configuring a framework.
+ *
+ * <p>
+ * When the Framework is first started it must be at start level zero. In this
+ * state, no bundles are running. This is the initial state of the Framework
+ * before it is launched. When the Framework is launched, the Framework will
+ * enter start level one and all bundles which are assigned to start level one
+ * and whose autostart setting indicates the bundle should be started are
+ * started as described in the {@link org.osgi.framework.Bundle#start(int)}
+ * method. The Framework will continue to increase the start level, starting
+ * bundles at each start level, until the Framework has reached a beginning
+ * start level. At this point the Framework has completed starting bundles and
+ * will then fire a Framework event of type
+ * {@link org.osgi.framework.FrameworkEvent#STARTED} to announce it has
+ * completed its launch.
+ *
+ * <p>
+ * Within a start level, bundles may be started in an order defined by the
+ * Framework implementation. This may be something like ascending
+ * {@link org.osgi.framework.Bundle#getBundleId()} order or an order based upon
+ * dependencies between bundles. A similar but reversed order may be used when
+ * stopping bundles within a start level.
+ *
+ * <p>
+ * The Framework Start Level package can be used by management bundles to alter
+ * the active start level of the framework.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest. For example:
+ *
+ * <pre>
+ * Import-Package: org.osgi.framework.startlevel; version="[1.0,2.0)"
+ * </pre>
+ *
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+
+ at Version("1.0")
+package org.osgi.framework.startlevel;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/framework/startlevel/packageinfo b/src/main/java/org/osgi/framework/startlevel/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/src/main/java/org/osgi/framework/startlevel/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/src/main/java/org/osgi/framework/wiring/BundleCapability.java b/src/main/java/org/osgi/framework/wiring/BundleCapability.java
index 19d7a67..705ba74 100644
--- a/src/main/java/org/osgi/framework/wiring/BundleCapability.java
+++ b/src/main/java/org/osgi/framework/wiring/BundleCapability.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.
@@ -17,6 +17,7 @@
package org.osgi.framework.wiring;
import java.util.Map;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.namespace.AbstractWiringNamespace;
import org.osgi.resource.Capability;
@@ -25,9 +26,9 @@ import org.osgi.resource.Capability;
* revision}.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: 39086f7e6086c2b3d83fbcb976a011cf69483ad8 $
+ * @author $Id: 834fb5779fb3c1b1b16ab25ffa4ab97a131b1262 $
*/
+ at ProviderType
public interface BundleCapability extends Capability {
/**
diff --git a/src/main/java/org/osgi/framework/wiring/BundleRequirement.java b/src/main/java/org/osgi/framework/wiring/BundleRequirement.java
index bb26c5d..42742dc 100644
--- a/src/main/java/org/osgi/framework/wiring/BundleRequirement.java
+++ b/src/main/java/org/osgi/framework/wiring/BundleRequirement.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.
@@ -17,6 +17,7 @@
package org.osgi.framework.wiring;
import java.util.Map;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.namespace.AbstractWiringNamespace;
import org.osgi.resource.Requirement;
@@ -25,9 +26,9 @@ import org.osgi.resource.Requirement;
* revision}.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: 212ffb64f724d982db86ff7e49ed64ea530e670a $
+ * @author $Id: ac0578af567754bcd12c63a350c06afdd1bfec05 $
*/
+ at ProviderType
public interface BundleRequirement extends Requirement {
/**
* Returns the bundle revision declaring this requirement.
diff --git a/src/main/java/org/osgi/framework/wiring/BundleRevision.java b/src/main/java/org/osgi/framework/wiring/BundleRevision.java
index 1ba9365..89d13b1 100644
--- a/src/main/java/org/osgi/framework/wiring/BundleRevision.java
+++ b/src/main/java/org/osgi/framework/wiring/BundleRevision.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.
@@ -17,6 +17,7 @@
package org.osgi.framework.wiring;
import java.util.List;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
import org.osgi.framework.Constants;
@@ -51,9 +52,9 @@ import org.osgi.resource.Resource;
* {@link Constants#REQUIRE_CAPABILITY Require-Capability} manifest headers.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: e68e01a670f0ae9d6eb736414f875c8b216ed1bc $
+ * @author $Id: 1f318afdf8f5fe6097a841b49b67bf67d8c924f2 $
*/
+ at ProviderType
public interface BundleRevision extends BundleReference, Resource {
/**
* Returns the symbolic name for this bundle revision.
@@ -235,7 +236,7 @@ public interface BundleRevision extends BundleReference, Resource {
* Returns the special types of this bundle revision. The bundle revision
* type values are:
* <ul>
- * <li>{@link #TYPE_FRAGMENT}
+ * <li>{@link #TYPE_FRAGMENT}</li>
* </ul>
*
* A bundle revision may be more than one type at a time. A type code is
diff --git a/src/main/java/org/osgi/framework/wiring/BundleRevisions.java b/src/main/java/org/osgi/framework/wiring/BundleRevisions.java
index f0d03ff..f9f7871 100644
--- a/src/main/java/org/osgi/framework/wiring/BundleRevisions.java
+++ b/src/main/java/org/osgi/framework/wiring/BundleRevisions.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.
@@ -17,6 +17,7 @@
package org.osgi.framework.wiring;
import java.util.List;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
@@ -36,9 +37,9 @@ import org.osgi.framework.BundleReference;
* {@link #getRevisions()} on the bundle.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: 8423242078417873faf0f8979e153e3c1f3a0e4b $
+ * @author $Id: 83e7bf03af2150a54af13a319325856e532cefde $
*/
+ at ProviderType
public interface BundleRevisions extends BundleReference {
/**
* Return the bundle revisions for the {@link BundleReference#getBundle()
diff --git a/src/main/java/org/osgi/framework/wiring/BundleWire.java b/src/main/java/org/osgi/framework/wiring/BundleWire.java
index d14829a..ab2c658 100644
--- a/src/main/java/org/osgi/framework/wiring/BundleWire.java
+++ b/src/main/java/org/osgi/framework/wiring/BundleWire.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.
@@ -16,15 +16,16 @@
package org.osgi.framework.wiring;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.resource.Wire;
/**
* A wire connecting a {@link BundleCapability} to a {@link BundleRequirement}.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: 02e7cd6ec0fa9fdb73f782a6890984d5d4e7ca21 $
+ * @author $Id: f51255c8510d4b513dc2bb70c2274d9c51e9b9e5 $
*/
+ at ProviderType
public interface BundleWire extends Wire {
/**
* Returns the {@link BundleCapability} for this wire.
diff --git a/src/main/java/org/osgi/framework/wiring/BundleWiring.java b/src/main/java/org/osgi/framework/wiring/BundleWiring.java
index b234c38..a11040c 100644
--- a/src/main/java/org/osgi/framework/wiring/BundleWiring.java
+++ b/src/main/java/org/osgi/framework/wiring/BundleWiring.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.
@@ -19,6 +19,7 @@ package org.osgi.framework.wiring;
import java.net.URL;
import java.util.Collection;
import java.util.List;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
import org.osgi.framework.namespace.IdentityNamespace;
@@ -52,9 +53,9 @@ import org.osgi.resource.Wiring;
* a bundle returns {@code null}.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: a3b3fd7ad7d289a5bfc6e4e02c875bc42a34df89 $
+ * @author $Id: 367499c4b37683c52e622f479242a9caf7e59b0f $
*/
+ at ProviderType
public interface BundleWiring extends BundleReference, Wiring {
/**
* Returns {@code true} if this bundle wiring is the current bundle wiring.
@@ -113,8 +114,8 @@ public interface BundleWiring extends BundleReference, Wiring {
* an empty list if this bundle wiring provides no capabilities in
* the specified namespace. If this bundle wiring is not
* {@link #isInUse() in use}, {@code null} will be returned. For a
- * given namespace, the list contains the wires in the order the
- * capabilities were specified in the manifests of the
+ * given namespace, the list contains the capabilities in the order
+ * the capabilities were specified in the manifests of the
* {@link #getRevision() bundle revision} and the attached
* fragments<sup>†</sup> of this bundle wiring. There is no
* ordering defined between capabilities in different namespaces.
@@ -143,8 +144,8 @@ public interface BundleWiring extends BundleReference, Wiring {
* or an empty list if this bundle wiring uses no requirements in
* the specified namespace. If this bundle wiring is not
* {@link #isInUse() in use}, {@code null} will be returned. For a
- * given namespace, the list contains the wires in the order the
- * requirements were specified in the manifests of the
+ * given namespace, the list contains the requirements in the order
+ * the requirements were specified in the manifests of the
* {@link #getRevision() bundle revision} and the attached fragments
* of this bundle wiring. There is no ordering defined between
* requirements in different namespaces.
@@ -176,9 +177,10 @@ public interface BundleWiring extends BundleReference, Wiring {
* requirements} in use by this bundle wiring.
*
* <p>
- * This method may return different results if this bundle wiring adds wires
- * to more requirements. For example, dynamically importing a package will
- * establish a new wire to the dynamically imported package.
+ * This method may return different results if this bundle wiring
+ * establishes additional wires to more requirements. For example,
+ * dynamically importing a package will establish a new wire to the
+ * dynamically imported package.
*
* @param namespace The namespace of the requirements for which to return
* wires or {@code null} to return the wires for the requirements in
@@ -191,8 +193,9 @@ public interface BundleWiring extends BundleReference, Wiring {
* given namespace, the list contains the wires in the order the
* requirements were specified in the manifests of the
* {@link #getRevision() bundle revision} and the attached fragments
- * of this bundle wiring. There is no ordering defined between
- * requirements in different namespaces.
+ * of this bundle wiring followed by dynamically established wires,
+ * if any, in the order they were established. There is no ordering
+ * defined between requirements in different namespaces.
*/
List<BundleWire> getRequiredWires(String namespace);
@@ -302,9 +305,9 @@ public interface BundleWiring extends BundleReference, Wiring {
* <li>Only the resource names for resources in bundle wirings will be
* returned. The names of resources visible to a bundle wiring's parent
* class loader, such as the bootstrap class loader, must not be included in
- * the result.
+ * the result.</li>
* <li>Only established wires will be examined for resources. This method
- * must not cause new wires for dynamic imports to be established.
+ * must not cause new wires for dynamic imports to be established.</li>
* </ul>
*
* @param path The path name in which to look. The path is always relative
@@ -405,7 +408,7 @@ public interface BundleWiring extends BundleReference, Wiring {
* @return A list containing a snapshot of the {@link Capability}s, or an
* empty list if this wiring provides no capabilities in the
* specified namespace. For a given namespace, the list contains the
- * wires in the order the capabilities were specified in the
+ * capabilities in the order the capabilities were specified in the
* manifests of the {@link #getResource() resource} and the attached
* fragment resources<sup>†</sup> of this wiring. There is no
* ordering defined between capabilities in different namespaces.
@@ -436,11 +439,11 @@ public interface BundleWiring extends BundleReference, Wiring {
* {@code null} to return the requirements from all namespaces.
* @return A list containing a snapshot of the {@link Requirement}s, or an
* empty list if this wiring uses no requirements in the specified
- * namespace. For a given namespace, the list contains the wires in
- * the order the requirements were specified in the manifests of the
- * {@link #getResource() resource} and the attached fragment
- * resources of this wiring. There is no ordering defined between
- * requirements in different namespaces.
+ * namespace. For a given namespace, the list contains the
+ * requirements in the order the requirements were specified in the
+ * manifests of the {@link #getResource() resource} and the attached
+ * fragment resources of this wiring. There is no ordering defined
+ * between requirements in different namespaces.
* @since 1.1
*/
List<Requirement> getResourceRequirements(String namespace);
diff --git a/src/main/java/org/osgi/framework/wiring/FrameworkWiring.java b/src/main/java/org/osgi/framework/wiring/FrameworkWiring.java
index ce9952c..ee3c548 100644
--- a/src/main/java/org/osgi/framework/wiring/FrameworkWiring.java
+++ b/src/main/java/org/osgi/framework/wiring/FrameworkWiring.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2001, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2001, 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.
@@ -17,9 +17,11 @@
package org.osgi.framework.wiring;
import java.util.Collection;
+import org.osgi.annotation.versioning.ProviderType;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleReference;
import org.osgi.framework.FrameworkListener;
+import org.osgi.resource.Requirement;
/**
* Query and modify wiring information for the framework. The framework wiring
@@ -32,9 +34,9 @@ import org.osgi.framework.FrameworkListener;
* by calling {@link BundleReference#getBundle()}.
*
* @ThreadSafe
- * @noimplement
- * @version $Id: bff4cdf85c632e2946e18c1640a86e80c069dd37 $
+ * @author $Id: 1ab9112badc94f802ccda966f7b73584f2a5c412 $
*/
+ at ProviderType
public interface FrameworkWiring extends BundleReference {
/**
* Refreshes the specified bundles. This forces the update (replacement) or
@@ -53,27 +55,23 @@ public interface FrameworkWiring extends BundleReference {
* <li>Compute the {@link #getDependencyClosure(Collection) dependency
* closure} of the specified bundles. If no bundles are specified, compute
* the dependency closure of the {@link #getRemovalPendingBundles() removal
- * pending} bundles.
- *
+ * pending} bundles.</li>
* <li>Each bundle in the dependency closure that is in the {@code ACTIVE}
- * state will be stopped as described in the {@code Bundle.stop} method.
- *
+ * state will be stopped as described in the {@code Bundle.stop} method.</li>
* <li>Each bundle in the dependency closure that is in the {@code RESOLVED}
* state is unresolved and thus moved to the {@code INSTALLED} state. The
* effect of this step is that bundles in the dependency closure are no
- * longer {@code RESOLVED}.
- *
+ * longer {@code RESOLVED}.</li>
* <li>Each bundle in the dependency closure that is in the
* {@code UNINSTALLED} state is removed from the dependency closure and is
- * now completely removed from the Framework.
- *
+ * now completely removed from the Framework.</li>
* <li>Each bundle in the dependency closure that was in the {@code ACTIVE}
* state prior to Step 2 is started as described in the {@code Bundle.start}
* method, causing all bundles required for the restart to be resolved. It
* is possible that, as a result of the previous steps, packages that were
* previously exported no longer are. Therefore, some bundles may be
* unresolvable until bundles satisfying the dependencies have been
- * installed in the Framework.
+ * installed in the Framework.</li>
* </ol>
*
* <p>
@@ -171,4 +169,34 @@ public interface FrameworkWiring extends BundleReference {
* FrameworkWiring.
*/
Collection<Bundle> getDependencyClosure(Collection<Bundle> bundles);
+
+ /**
+ * Find bundle capabilities that match the given requirement.
+ *
+ * <p>
+ * The returned collection contains {@link BundleCapability} objects where
+ * the revision must be the {@link BundleCapability#getRevision() declaring
+ * revision} of the capability and the revision must either be the current
+ * bundle revision or an {@link BundleWiring#isInUse() in use} bundle
+ * revision.
+ *
+ * <p>
+ * Each returned capability must match the given requirement. This means
+ * that the filter in the requirement must match as well as any namespace
+ * specific directives. For example, the mandatory attributes for the
+ * osgi.wiring.package namespace.
+ *
+ * <p>
+ * The returned collection has not been filtered to remove capabilities that
+ * are non-effective, substituted or for which the providing bundle does not
+ * have permission to provide. No resolve hooks are called to filter
+ * matching capabilities.
+ *
+ * @param requirement The requirement to find matching bundle capabilities.
+ * Must not be {@code null}.
+ * @return A collection of {@link BundleCapability} objects that match the
+ * specified requirement.
+ * @since 1.2
+ */
+ Collection<BundleCapability> findProviders(Requirement requirement);
}
diff --git a/src/main/java/org/osgi/framework/wiring/dto/BundleRevisionDTO.java b/src/main/java/org/osgi/framework/wiring/dto/BundleRevisionDTO.java
new file mode 100644
index 0000000..b9d4580
--- /dev/null
+++ b/src/main/java/org/osgi/framework/wiring/dto/BundleRevisionDTO.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.wiring.dto;
+
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.resource.dto.ResourceDTO;
+
+/**
+ * Data Transfer Object for a BundleRevision.
+ *
+ * <p>
+ * An installed Bundle can be adapted to provide a {@code BundleRevisionDTO} for
+ * the current revision of the Bundle. {@code BundleRevisionDTO} objects for all
+ * in use revisions of the Bundle can be obtained by adapting the bundle to
+ * {@code BundleRevisionDTO[]}.
+ *
+ * @author $Id: BundleRevisionDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class BundleRevisionDTO extends ResourceDTO {
+ /**
+ * The symbolic name of the bundle revision.
+ *
+ * @see BundleRevision#getSymbolicName()
+ */
+ public String symbolicName;
+
+ /**
+ * The type of the bundle revision.
+ *
+ * @see BundleRevision#getTypes()
+ */
+ public int type;
+
+ /**
+ * The version of the bundle revision.
+ *
+ * @see BundleRevision#getVersion()
+ */
+ public String version;
+
+ /**
+ * The id of the bundle associated with the bundle revision.
+ *
+ * @see BundleRevision#getBundle()
+ */
+ public long bundle;
+}
diff --git a/src/main/java/org/osgi/framework/wiring/dto/BundleWireDTO.java b/src/main/java/org/osgi/framework/wiring/dto/BundleWireDTO.java
new file mode 100644
index 0000000..967ece4
--- /dev/null
+++ b/src/main/java/org/osgi/framework/wiring/dto/BundleWireDTO.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.wiring.dto;
+
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.resource.dto.WireDTO;
+import org.osgi.resource.dto.WiringDTO;
+
+/**
+ * Data Transfer Object for a BundleWire.
+ *
+ * <p>
+ * {@code BundleWireDTO}s are referenced {@link BundleWiringDTO.NodeDTO}s.
+ *
+ * @author $Id: BundleWireDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class BundleWireDTO extends WireDTO {
+ /**
+ * The identifier of the provider wiring for the bundle wire.
+ *
+ * @see WiringDTO#id
+ * @see BundleWire#getProviderWiring()
+ */
+ public int providerWiring;
+
+ /**
+ * The identifier of the requiring wiring for the bundle wire.
+ *
+ * @see WiringDTO#id
+ * @see BundleWire#getRequirerWiring()
+ */
+ public int requirerWiring;
+}
diff --git a/src/main/java/org/osgi/framework/wiring/dto/BundleWiringDTO.java b/src/main/java/org/osgi/framework/wiring/dto/BundleWiringDTO.java
new file mode 100644
index 0000000..74f0b35
--- /dev/null
+++ b/src/main/java/org/osgi/framework/wiring/dto/BundleWiringDTO.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.framework.wiring.dto;
+
+import java.util.Set;
+import org.osgi.dto.DTO;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.resource.dto.WiringDTO;
+
+/**
+ * Data Transfer Object for a BundleWiring graph.
+ *
+ * <p>
+ * An installed Bundle can be adapted to provide a {@code BundleWiringDTO} for
+ * the current wiring Bundle. {@code BundleWiringDTO} objects for all in use
+ * wirings of the Bundle can be obtained by adapting the bundle to
+ * {@code BundleWiringDTO[]}.
+ *
+ * @author $Id: BundleWiringDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class BundleWiringDTO extends DTO {
+ /**
+ * The id of the bundle associated with the bundle wiring graph.
+ *
+ * @see BundleWiring#getBundle()
+ */
+ public long bundle;
+
+ /**
+ * The identifier of the root wiring node of the bundle wiring graph.
+ *
+ * @see WiringDTO#id
+ */
+ public int root;
+
+ /**
+ * The set of wiring nodes referenced by the wiring graph.
+ *
+ * <p>
+ * All wiring nodes referenced by wiring node identifiers in the wiring
+ * graph are contained in this set.
+ */
+ public Set<NodeDTO> nodes;
+
+ /**
+ * The set of resources referenced by the wiring graph.
+ *
+ * <p>
+ * All resources referenced by resource identifiers in the wiring graph are
+ * contained in this set.
+ */
+ public Set<BundleRevisionDTO> resources;
+
+ /**
+ * Data Transfer Object for a BundleWiring node.
+ *
+ * <p>
+ * The {@link WiringDTO#providedWires providedWires} field must contain an
+ * array of {@link BundleWireDTO}s. The {@link WiringDTO#requiredWires
+ * requiredWires} field must contain an array of {@link BundleWireDTO}s.
+ *
+ * @NotThreadSafe
+ */
+ public static class NodeDTO extends WiringDTO {
+ /**
+ * The bundle wiring's in use setting indicates that the bundle wiring
+ * is in use.
+ *
+ * @see BundleWiring#isInUse()
+ */
+ public boolean inUse;
+
+ /**
+ * The current state of the bundle wiring. The bundle wiring's current
+ * setting indicates that the bundle wiring is the current bundle wiring
+ * for the bundle.
+ *
+ * @see BundleWiring#isCurrent()
+ */
+ public boolean current;
+ }
+}
diff --git a/src/main/java/org/osgi/framework/wiring/dto/package-info.java b/src/main/java/org/osgi/framework/wiring/dto/package-info.java
new file mode 100644
index 0000000..abfc1a1
--- /dev/null
+++ b/src/main/java/org/osgi/framework/wiring/dto/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). 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.
+ */
+
+/**
+ * OSGi Data Transfer Object Framework Wiring Package Version 1.2.
+ *
+ * <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.framework.wiring.dto; version="[1.2,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.framework.wiring.dto; version="[1.2,1.3)"}
+ *
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+
+ at Version("1.2")
+package org.osgi.framework.wiring.dto;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/framework/wiring/dto/packageinfo b/src/main/java/org/osgi/framework/wiring/dto/packageinfo
new file mode 100644
index 0000000..ef7df68
--- /dev/null
+++ b/src/main/java/org/osgi/framework/wiring/dto/packageinfo
@@ -0,0 +1 @@
+version 1.2
diff --git a/src/main/java/org/osgi/framework/BundleReference.java b/src/main/java/org/osgi/framework/wiring/package-info.java
similarity index 52%
copy from src/main/java/org/osgi/framework/BundleReference.java
copy to src/main/java/org/osgi/framework/wiring/package-info.java
index 97340f7..27c3f94 100644
--- a/src/main/java/org/osgi/framework/BundleReference.java
+++ b/src/main/java/org/osgi/framework/wiring/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2009, 2010). 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.
@@ -14,23 +14,22 @@
* limitations under the License.
*/
-package org.osgi.framework;
-
/**
- * A reference to a Bundle.
+ * Framework Wiring Package Version 1.2.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest. For example:
+ *
+ * <pre>
+ * Import-Package: org.osgi.framework.wiring; version="[1.2,2.0)"
+ * </pre>
*
- * @since 1.5
- * @ThreadSafe
- * @noimplement
- * @version $Id: e61bd3e020264b04022a430fe09a85ee3aabf1a3 $
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
*/
-public interface BundleReference {
- /**
- * Returns the {@code Bundle} object associated with this
- * {@code BundleReference}.
- *
- * @return The {@code Bundle} object associated with this
- * {@code BundleReference}.
- */
- public Bundle getBundle();
-}
+
+ at Version("1.2")
+package org.osgi.framework.wiring;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/framework/wiring/packageinfo b/src/main/java/org/osgi/framework/wiring/packageinfo
new file mode 100644
index 0000000..ef7df68
--- /dev/null
+++ b/src/main/java/org/osgi/framework/wiring/packageinfo
@@ -0,0 +1 @@
+version 1.2
diff --git a/src/main/java/org/osgi/resource/Capability.java b/src/main/java/org/osgi/resource/Capability.java
index bda0ce6..289c973 100644
--- a/src/main/java/org/osgi/resource/Capability.java
+++ b/src/main/java/org/osgi/resource/Capability.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.
@@ -17,6 +17,7 @@
package org.osgi.resource;
import java.util.Map;
+import org.osgi.annotation.versioning.ConsumerType;
/**
* A capability that has been declared from a {@link Resource}.
@@ -27,8 +28,9 @@ import java.util.Map;
* always return the same result.
*
* @ThreadSafe
- * @version $Id: 5f40514f7bf45f6dce59651e8812b0922580e77e $
+ * @author $Id: e79d11402e14e170443c8a2a9da835391cd1ccc8 $
*/
+ at ConsumerType
public interface Capability {
/**
diff --git a/src/main/java/org/osgi/resource/Namespace.java b/src/main/java/org/osgi/resource/Namespace.java
index abda616..a8223b1 100644
--- a/src/main/java/org/osgi/resource/Namespace.java
+++ b/src/main/java/org/osgi/resource/Namespace.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.
@@ -16,6 +16,8 @@
package org.osgi.resource;
+import org.osgi.annotation.versioning.ConsumerType;
+
/**
* Capability and Requirement Namespaces base class.
*
@@ -34,8 +36,9 @@ package org.osgi.resource;
* otherwise indicated.
*
* @Immutable
- * @version $Id: 43c9ff5cea19546d71c4703db71a2b5070a3f2fa $
+ * @author $Id: 95a67250528646012b39e8e5a92775fbb635a8c0 $
*/
+ at ConsumerType
public abstract class Namespace {
/**
diff --git a/src/main/java/org/osgi/resource/Requirement.java b/src/main/java/org/osgi/resource/Requirement.java
index cf931bf..4806faa 100644
--- a/src/main/java/org/osgi/resource/Requirement.java
+++ b/src/main/java/org/osgi/resource/Requirement.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.
@@ -17,6 +17,7 @@
package org.osgi.resource;
import java.util.Map;
+import org.osgi.annotation.versioning.ConsumerType;
/**
* A requirement that has been declared from a {@link Resource} .
@@ -27,8 +28,9 @@ import java.util.Map;
* always return the same result.
*
* @ThreadSafe
- * @version $Id: 212b26179910f98fd2c59c3e1e7dd0d086f42b5d $
+ * @author $Id: 252221aeaaf9b189eef6e0c3798d0076a0032242 $
*/
+ at ConsumerType
public interface Requirement {
/**
* Returns the namespace of this requirement.
diff --git a/src/main/java/org/osgi/resource/Resource.java b/src/main/java/org/osgi/resource/Resource.java
index 455d891..91edcdb 100644
--- a/src/main/java/org/osgi/resource/Resource.java
+++ b/src/main/java/org/osgi/resource/Resource.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.
@@ -17,6 +17,7 @@
package org.osgi.resource;
import java.util.List;
+import org.osgi.annotation.versioning.ConsumerType;
/**
* A resource is the representation of a uniquely identified and typed data. A
@@ -29,8 +30,9 @@ import java.util.List;
* always return the same result.
*
* @ThreadSafe
- * @version $Id: 40958d5777ee269d27d58e9f646a4c91bcc6daa4 $
+ * @author $Id: c7b6462fb53b38ac3071d7ba73af9dad2af6b9ce $
*/
+ at ConsumerType
public interface Resource {
/**
* Returns the capabilities declared by this resource.
diff --git a/src/main/java/org/osgi/resource/Wire.java b/src/main/java/org/osgi/resource/Wire.java
index 18feab8..beba44e 100644
--- a/src/main/java/org/osgi/resource/Wire.java
+++ b/src/main/java/org/osgi/resource/Wire.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.
@@ -16,6 +16,8 @@
package org.osgi.resource;
+import org.osgi.annotation.versioning.ConsumerType;
+
/**
* A wire connecting a {@link Capability} to a {@link Requirement}.
*
@@ -25,8 +27,9 @@ package org.osgi.resource;
* always return the same result.
*
* @ThreadSafe
- * @version $Id: d7ca9a5d3e8dd2277f8243a750e40fbcf79185bd $
+ * @author $Id: 6c248ea2b9b24f3610a14e5e8deec9cd0b7aa1c9 $
*/
+ at ConsumerType
public interface Wire {
/**
* Returns the {@link Capability} for this wire.
diff --git a/src/main/java/org/osgi/resource/Wiring.java b/src/main/java/org/osgi/resource/Wiring.java
index 230fef0..56db2a3 100644
--- a/src/main/java/org/osgi/resource/Wiring.java
+++ b/src/main/java/org/osgi/resource/Wiring.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.
@@ -17,6 +17,7 @@
package org.osgi.resource;
import java.util.List;
+import org.osgi.annotation.versioning.ConsumerType;
/**
* A wiring for a resource. A wiring is associated with a resource and
@@ -28,8 +29,9 @@ import java.util.List;
* always return the same result.
*
* @ThreadSafe
- * @version $Id: b65dec3887cfa1d5731e860db558a01503c0f47d $
+ * @author $Id: 935272fa914a9cc0020549c43a3857acad2c45cc $
*/
+ at ConsumerType
public interface Wiring {
/**
* Returns the capabilities provided by this wiring.
@@ -64,7 +66,7 @@ public interface Wiring {
* @return A list containing a snapshot of the {@link Capability}s, or an
* empty list if this wiring provides no capabilities in the
* specified namespace. For a given namespace, the list contains the
- * wires in the order the capabilities were specified in the
+ * capabilities in the order the capabilities were specified in the
* manifests of the {@link #getResource() resource} and the attached
* fragment resources<sup>†</sup> of this wiring. There is no
* ordering defined between capabilities in different namespaces.
@@ -91,11 +93,11 @@ public interface Wiring {
* {@code null} to return the requirements from all namespaces.
* @return A list containing a snapshot of the {@link Requirement}s, or an
* empty list if this wiring uses no requirements in the specified
- * namespace. For a given namespace, the list contains the wires in
- * the order the requirements were specified in the manifests of the
- * {@link #getResource() resource} and the attached fragment
- * resources of this wiring. There is no ordering defined between
- * requirements in different namespaces.
+ * namespace. For a given namespace, the list contains the
+ * requirements in the order the requirements were specified in the
+ * manifests of the {@link #getResource() resource} and the attached
+ * fragment resources of this wiring. There is no ordering defined
+ * between requirements in different namespaces.
*/
List<Requirement> getResourceRequirements(String namespace);
diff --git a/src/main/java/org/osgi/resource/dto/CapabilityDTO.java b/src/main/java/org/osgi/resource/dto/CapabilityDTO.java
new file mode 100644
index 0000000..941ec8f
--- /dev/null
+++ b/src/main/java/org/osgi/resource/dto/CapabilityDTO.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.resource.dto;
+
+import java.util.Map;
+import org.osgi.dto.DTO;
+import org.osgi.resource.Capability;
+
+/**
+ * Data Transfer Object for a Capability.
+ *
+ * @author $Id: CapabilityDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class CapabilityDTO extends DTO {
+ /**
+ * The unique identifier of the capability.
+ *
+ * <p>
+ * This identifier is transiently assigned and may vary across restarts.
+ */
+ public int id;
+
+ /**
+ * The namespace for the capability.
+ *
+ * @see Capability#getNamespace()
+ */
+ public String namespace;
+
+ /**
+ * The directives for the capability.
+ *
+ * @see Capability#getDirectives()
+ */
+ public Map<String, String> directives;
+
+ /**
+ * The attributes for the capability.
+ *
+ * <p>
+ * The value type must be a numerical type, Boolean, String, DTO or an array
+ * of any of the former.
+ *
+ * @see Capability#getAttributes()
+ */
+ public Map<String, Object> attributes;
+
+ /**
+ * The identifier of the resource declaring the capability.
+ *
+ * @see ResourceDTO#id
+ * @see Capability#getResource()
+ */
+ public int resource;
+}
diff --git a/src/main/java/org/osgi/resource/dto/CapabilityRefDTO.java b/src/main/java/org/osgi/resource/dto/CapabilityRefDTO.java
new file mode 100644
index 0000000..4a94459
--- /dev/null
+++ b/src/main/java/org/osgi/resource/dto/CapabilityRefDTO.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.resource.dto;
+
+import org.osgi.dto.DTO;
+
+/**
+ * Data Transfer Object for a reference to a Capability.
+ *
+ * @author $Id: CapabilityRefDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class CapabilityRefDTO extends DTO {
+ /**
+ * The identifier of the capability in the resource.
+ *
+ * @see CapabilityDTO#id
+ */
+ public int capability;
+
+ /**
+ * The identifier of the resource declaring the capability.
+ *
+ * @see ResourceDTO#id
+ */
+ public int resource;
+}
diff --git a/src/main/java/org/osgi/resource/dto/RequirementDTO.java b/src/main/java/org/osgi/resource/dto/RequirementDTO.java
new file mode 100644
index 0000000..d8e02a0
--- /dev/null
+++ b/src/main/java/org/osgi/resource/dto/RequirementDTO.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.resource.dto;
+
+import java.util.Map;
+import org.osgi.dto.DTO;
+import org.osgi.resource.Requirement;
+
+/**
+ * Data Transfer Object for a Requirement.
+ *
+ * @author $Id: RequirementDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class RequirementDTO extends DTO {
+ /**
+ * The unique identifier of the requirement.
+ *
+ * <p>
+ * This identifier is transiently assigned and may vary across restarts.
+ */
+ public int id;
+
+ /**
+ * The namespace for the requirement.
+ *
+ * @see Requirement#getNamespace()
+ */
+ public String namespace;
+
+ /**
+ * The directives for the requirement.
+ *
+ * @see Requirement#getDirectives()
+ */
+ public Map<String, String> directives;
+
+ /**
+ * The attributes for the requirement.
+ *
+ * <p>
+ * The value type must be a numerical type, Boolean, String, DTO or an array
+ * of any of the former.
+ *
+ * @see Requirement#getAttributes()
+ */
+ public Map<String, Object> attributes;
+
+ /**
+ * The identifier of the resource declaring the requirement.
+ *
+ * @see ResourceDTO#id
+ * @see Requirement#getResource()
+ */
+ public int resource;
+}
diff --git a/src/main/java/org/osgi/resource/dto/RequirementRefDTO.java b/src/main/java/org/osgi/resource/dto/RequirementRefDTO.java
new file mode 100644
index 0000000..9f8c316
--- /dev/null
+++ b/src/main/java/org/osgi/resource/dto/RequirementRefDTO.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) OSGi Alliance (2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.resource.dto;
+
+import org.osgi.dto.DTO;
+
+/**
+ * Data Transfer Object for a reference to a Requirement.
+ *
+ * @author $Id: RequirementRefDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class RequirementRefDTO extends DTO {
+ /**
+ * The identifier of the requirement in the resource.
+ *
+ * @see RequirementDTO#id
+ */
+ public int requirement;
+
+ /**
+ * The identifier of the resource declaring the requirement.
+ *
+ * @see ResourceDTO#id
+ */
+ public int resource;
+}
diff --git a/src/main/java/org/osgi/resource/dto/ResourceDTO.java b/src/main/java/org/osgi/resource/dto/ResourceDTO.java
new file mode 100644
index 0000000..5e35165
--- /dev/null
+++ b/src/main/java/org/osgi/resource/dto/ResourceDTO.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.resource.dto;
+
+import java.util.List;
+import org.osgi.dto.DTO;
+import org.osgi.resource.Resource;
+
+/**
+ * Data Transfer Object for a Resource.
+ *
+ * @author $Id: ResourceDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class ResourceDTO extends DTO {
+ /**
+ * The unique identifier of the resource.
+ *
+ * <p>
+ * This identifier is transiently assigned and may vary across restarts.
+ */
+ public int id;
+
+ /**
+ * The capabilities of the resource.
+ *
+ * @see Resource#getCapabilities(String)
+ */
+ public List<CapabilityDTO> capabilities;
+
+ /**
+ * The requirements of the resource.
+ *
+ * @see Resource#getRequirements(String)
+ */
+ public List<RequirementDTO> requirements;
+}
diff --git a/src/main/java/org/osgi/resource/dto/WireDTO.java b/src/main/java/org/osgi/resource/dto/WireDTO.java
new file mode 100644
index 0000000..00b61d8
--- /dev/null
+++ b/src/main/java/org/osgi/resource/dto/WireDTO.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.resource.dto;
+
+import org.osgi.dto.DTO;
+import org.osgi.resource.Wire;
+
+/**
+ * Data Transfer Object for a Wire.
+ *
+ * @author $Id: WireDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class WireDTO extends DTO {
+ /**
+ * Reference to the Capability for the wire.
+ *
+ * @see Wire#getCapability()
+ */
+ public CapabilityRefDTO capability;
+
+ /**
+ * Reference to the Requirement for the wire.
+ *
+ * @see Wire#getRequirement()
+ */
+ public RequirementRefDTO requirement;
+
+ /**
+ * The identifier of the provider resource for the wire.
+ *
+ * @see ResourceDTO#id
+ * @see Wire#getProvider()
+ */
+ public int provider;
+
+ /**
+ * The identifier of the requiring resource for the wire.
+ *
+ * @see ResourceDTO#id
+ * @see Wire#getRequirer()
+ */
+ public int requirer;
+}
diff --git a/src/main/java/org/osgi/resource/dto/WiringDTO.java b/src/main/java/org/osgi/resource/dto/WiringDTO.java
new file mode 100644
index 0000000..4484658
--- /dev/null
+++ b/src/main/java/org/osgi/resource/dto/WiringDTO.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.osgi.resource.dto;
+
+import java.util.List;
+import org.osgi.dto.DTO;
+import org.osgi.resource.Wiring;
+
+/**
+ * Data Transfer Object for a Wiring node.
+ *
+ * @author $Id: WiringDTO.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ * @NotThreadSafe
+ */
+public class WiringDTO extends DTO {
+ /**
+ * The unique identifier of the wiring node.
+ *
+ * <p>
+ * This identifier is transiently assigned and may vary across restarts.
+ */
+ public int id;
+
+ /**
+ * The references to the capabilities for the wiring node.
+ *
+ * @see Wiring#getResourceCapabilities(String)
+ */
+ public List<CapabilityRefDTO> capabilities;
+
+ /**
+ * The references to the requirements for the wiring node.
+ *
+ * @see Wiring#getResourceRequirements(String)
+ */
+ public List<RequirementRefDTO> requirements;
+
+ /**
+ * The provided wires for the wiring node.
+ *
+ * @see Wiring#getProvidedResourceWires(String)
+ */
+ public List<WireDTO> providedWires;
+
+ /**
+ * The required wires for the wiring node.
+ *
+ * @see Wiring#getRequiredResourceWires(String)
+ */
+ public List<WireDTO> requiredWires;
+
+ /**
+ * The identifier of the resource associated with the wiring node.
+ *
+ * @see ResourceDTO#id
+ * @see Wiring#getResource()
+ */
+ public int resource;
+}
diff --git a/src/main/java/org/osgi/resource/dto/package-info.java b/src/main/java/org/osgi/resource/dto/package-info.java
new file mode 100644
index 0000000..de4e2c9
--- /dev/null
+++ b/src/main/java/org/osgi/resource/dto/package-info.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) OSGi Alliance (2012, 2014). 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.
+ */
+
+/**
+ * OSGi Data Transfer Object Resource 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.resource.dto; version="[1.0,2.0)"}
+ * <p>
+ * Example import for providers implementing the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.resource.dto; version="[1.0,1.1)"}
+ *
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+
+ at Version("1.0")
+package org.osgi.resource.dto;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/resource/dto/packageinfo b/src/main/java/org/osgi/resource/dto/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/src/main/java/org/osgi/resource/dto/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/src/main/java/org/osgi/framework/BundleReference.java b/src/main/java/org/osgi/resource/package-info.java
similarity index 53%
copy from src/main/java/org/osgi/framework/BundleReference.java
copy to src/main/java/org/osgi/resource/package-info.java
index 97340f7..c0349ff 100644
--- a/src/main/java/org/osgi/framework/BundleReference.java
+++ b/src/main/java/org/osgi/resource/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2009, 2010). 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.
@@ -14,23 +14,22 @@
* limitations under the License.
*/
-package org.osgi.framework;
-
/**
- * A reference to a Bundle.
+ * Resource Package Version 1.0.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest. For example:
+ *
+ * <pre>
+ * Import-Package: org.osgi.resource; version="[1.0,2.0)"
+ * </pre>
*
- * @since 1.5
- * @ThreadSafe
- * @noimplement
- * @version $Id: e61bd3e020264b04022a430fe09a85ee3aabf1a3 $
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
*/
-public interface BundleReference {
- /**
- * Returns the {@code Bundle} object associated with this
- * {@code BundleReference}.
- *
- * @return The {@code Bundle} object associated with this
- * {@code BundleReference}.
- */
- public Bundle getBundle();
-}
+
+ at Version("1.0")
+package org.osgi.resource;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/resource/packageinfo b/src/main/java/org/osgi/resource/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/src/main/java/org/osgi/resource/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/src/main/java/org/osgi/service/packageadmin/ExportedPackage.java b/src/main/java/org/osgi/service/packageadmin/ExportedPackage.java
index 4dd3a3a..4b2001d 100644
--- a/src/main/java/org/osgi/service/packageadmin/ExportedPackage.java
+++ b/src/main/java/org/osgi/service/packageadmin/ExportedPackage.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2001, 2011). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2001, 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.
@@ -45,7 +45,7 @@ import org.osgi.framework.Version;
* @noimplement
* @deprecated The PackageAdmin service has been replaced by the
* <code>org.osgi.framework.wiring</code> package.
- * @version $Id: 22ce5e8e388107b04edba3aea2f3036b8026798d $
+ * @author $Id: e04a2beb3de2afff4cb01747e589c04b5e0f0cc8 $
*/
public interface ExportedPackage {
/**
diff --git a/src/main/java/org/osgi/service/packageadmin/PackageAdmin.java b/src/main/java/org/osgi/service/packageadmin/PackageAdmin.java
index 2c57890..03ca2e5 100644
--- a/src/main/java/org/osgi/service/packageadmin/PackageAdmin.java
+++ b/src/main/java/org/osgi/service/packageadmin/PackageAdmin.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2001, 2010). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2001, 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.
@@ -29,7 +29,7 @@ import org.osgi.framework.Bundle;
*
* @ThreadSafe
* @noimplement
- * @version $Id: a268c3bdc986080fa16bdb2f56ba1d3800d030dd $
+ * @author $Id: 4aad25d2f145d9a2d24825bc481dcc254b74ed51 $
* @deprecated This service has been replaced by the
* <code>org.osgi.framework.wiring</code> package.
* @see org.osgi.service.packageadmin.ExportedPackage
@@ -104,30 +104,28 @@ public interface PackageAdmin {
* graph any bundle that is wired to a package that is currently exported by
* a bundle in the graph. The graph is fully constructed when there is no
* bundle outside the graph that is wired to a bundle in the graph. The
- * graph may contain {@code UNINSTALLED} bundles that are currently
- * still exporting packages.
+ * graph may contain {@code UNINSTALLED} bundles that are currently still
+ * exporting packages.</li>
*
- * <li>Each bundle in the graph that is in the {@code ACTIVE} state
- * will be stopped as described in the {@code Bundle.stop} method.
+ * <li>Each bundle in the graph that is in the {@code ACTIVE} state will be
+ * stopped as described in the {@code Bundle.stop} method.</li>
*
- * <li>Each bundle in the graph that is in the {@code RESOLVED} state
- * is unresolved and thus moved to the {@code INSTALLED} state. The
- * effect of this step is that bundles in the graph are no longer
- * {@code RESOLVED}.
+ * <li>Each bundle in the graph that is in the {@code RESOLVED} state is
+ * unresolved and thus moved to the {@code INSTALLED} state. The effect of
+ * this step is that bundles in the graph are no longer {@code RESOLVED}.</li>
*
- * <li>Each bundle in the graph that is in the {@code UNINSTALLED}
- * state is removed from the graph and is now completely removed from the
- * Framework.
+ * <li>Each bundle in the graph that is in the {@code UNINSTALLED} state is
+ * removed from the graph and is now completely removed from the Framework.</li>
*
- * <li>Each bundle in the graph that was in the {@code ACTIVE} state
- * prior to Step 2 is started as described in the {@code Bundle.start}
- * method, causing all bundles required for the restart to be resolved. It
- * is possible that, as a result of the previous steps, packages that were
+ * <li>Each bundle in the graph that was in the {@code ACTIVE} state prior
+ * to Step 2 is started as described in the {@code Bundle.start} method,
+ * causing all bundles required for the restart to be resolved. It is
+ * possible that, as a result of the previous steps, packages that were
* previously exported no longer are. Therefore, some bundles may be
* unresolvable until another bundle offering a compatible package for
- * export has been installed in the Framework.
- * <li>A framework event of type
- * {@code FrameworkEvent.PACKAGES_REFRESHED} is fired.
+ * export has been installed in the Framework.</li>
+ * <li>A framework event of type {@code FrameworkEvent.PACKAGES_REFRESHED}
+ * is fired.</li>
* </ol>
*
* <p>
@@ -277,7 +275,7 @@ public interface PackageAdmin {
* Returns the special type of the specified bundle. The bundle type values
* are:
* <ul>
- * <li>{@link #BUNDLE_TYPE_FRAGMENT}
+ * <li>{@link #BUNDLE_TYPE_FRAGMENT}</li>
* </ul>
*
* A bundle may be more than one type at a time. A type code is used to
diff --git a/src/main/java/org/osgi/service/packageadmin/RequiredBundle.java b/src/main/java/org/osgi/service/packageadmin/RequiredBundle.java
index 34c0b08..2434dce 100644
--- a/src/main/java/org/osgi/service/packageadmin/RequiredBundle.java
+++ b/src/main/java/org/osgi/service/packageadmin/RequiredBundle.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2004, 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.
@@ -46,7 +46,7 @@ import org.osgi.framework.Version;
* @noimplement
* @deprecated The PackageAdmin service has been replaced by the
* <code>org.osgi.framework.wiring</code> package.
- * @version $Id: 1606b0422cae6769b7eedc2d565df61841da1e22 $
+ * @author $Id: 08ab9c1a6f4a9af2060293d2c2972e4e07e2a238 $
*/
public interface RequiredBundle {
/**
diff --git a/src/main/java/org/osgi/service/packageadmin/package-info.java b/src/main/java/org/osgi/service/packageadmin/package-info.java
new file mode 100644
index 0000000..88a3adb
--- /dev/null
+++ b/src/main/java/org/osgi/service/packageadmin/package-info.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+/**
+ * Package Admin Package Version 1.2.
+ *
+ * <p>
+ * <b>Deprecated.</b>
+ * <i>This package is deprecated and has been replaced by the
+ * {@code org.osgi.framework.wiring} package.</i>
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.packageadmin; version="[1.2,2.0)"}
+ *
+ * @version 1.2
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+
+package org.osgi.service.packageadmin;
diff --git a/src/main/java/org/osgi/service/packageadmin/packageinfo b/src/main/java/org/osgi/service/packageadmin/packageinfo
new file mode 100644
index 0000000..ef7df68
--- /dev/null
+++ b/src/main/java/org/osgi/service/packageadmin/packageinfo
@@ -0,0 +1 @@
+version 1.2
diff --git a/src/main/java/org/osgi/service/startlevel/StartLevel.java b/src/main/java/org/osgi/service/startlevel/StartLevel.java
index b4b8816..2e299ed 100644
--- a/src/main/java/org/osgi/service/startlevel/StartLevel.java
+++ b/src/main/java/org/osgi/service/startlevel/StartLevel.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2002, 2011). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 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.
@@ -68,7 +68,7 @@ import org.osgi.framework.Bundle;
*
* @ThreadSafe
* @noimplement
- * @version $Id: ec0295bdf246c0258261374b3ac0e4aef11f7315 $
+ * @author $Id: 42f3c6bbf682a69ea3914c737d5b0001694383db $
* @deprecated This service has been replaced by the
* <code>org.osgi.framework.startlevel</code> package.
*/
@@ -100,14 +100,13 @@ public interface StartLevel {
* At each intermediate start level value on the way to and including the
* target start level, the Framework must:
* <ol>
- * <li>Change the active start level to the intermediate start level value.
- * <li>Start bundles at the intermediate start level whose autostart
- * setting indicate they must be started. They are started as described in
- * the {@link Bundle#start(int)} method using the
- * {@link Bundle#START_TRANSIENT} option. The
- * {@link Bundle#START_ACTIVATION_POLICY} option must also be used if
- * {@link #isBundleActivationPolicyUsed(Bundle)} returns {@code true}
- * for the bundle.
+ * <li>Change the active start level to the intermediate start level value.</li>
+ * <li>Start bundles at the intermediate start level whose autostart setting
+ * indicate they must be started. They are started as described in the
+ * {@link Bundle#start(int)} method using the {@link Bundle#START_TRANSIENT}
+ * option. The {@link Bundle#START_ACTIVATION_POLICY} option must also be
+ * used if {@link #isBundleActivationPolicyUsed(Bundle)} returns
+ * {@code true} for the bundle.</li>
* </ol>
* When this process completes after the specified start level is reached,
* the Framework will fire a Framework event of type
@@ -124,8 +123,8 @@ public interface StartLevel {
* <ol>
* <li>Stop bundles at the intermediate start level as described in the
* {@link Bundle#stop(int)} method using the {@link Bundle#STOP_TRANSIENT}
- * option.
- * <li>Change the active start level to the intermediate start level value.
+ * option.</li>
+ * <li>Change the active start level to the intermediate start level value.</li>
* </ol>
* When this process completes after the specified start level is reached,
* the Framework will fire a Framework event of type
diff --git a/src/main/java/org/osgi/service/startlevel/package-info.java b/src/main/java/org/osgi/service/startlevel/package-info.java
new file mode 100644
index 0000000..0b2927a
--- /dev/null
+++ b/src/main/java/org/osgi/service/startlevel/package-info.java
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+/**
+ * Start Level Package Version 1.1.
+ *
+ * <p>
+ * <b>Deprecated.</b>
+ * <i>This package is deprecated and has been replaced by the
+ * {@code org.osgi.framework.startlevel} package.</i>
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.startlevel; version="[1.1,2.0)"}
+ *
+ * @version 1.1
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
+ */
+
+package org.osgi.service.startlevel;
diff --git a/src/main/java/org/osgi/service/startlevel/packageinfo b/src/main/java/org/osgi/service/startlevel/packageinfo
new file mode 100644
index 0000000..3987f9c
--- /dev/null
+++ b/src/main/java/org/osgi/service/startlevel/packageinfo
@@ -0,0 +1 @@
+version 1.1
diff --git a/src/main/java/org/osgi/service/url/AbstractURLStreamHandlerService.java b/src/main/java/org/osgi/service/url/AbstractURLStreamHandlerService.java
index 679583c..e641366 100644
--- a/src/main/java/org/osgi/service/url/AbstractURLStreamHandlerService.java
+++ b/src/main/java/org/osgi/service/url/AbstractURLStreamHandlerService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2002, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 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.
@@ -16,7 +16,11 @@
package org.osgi.service.url;
-import java.net.*;
+import java.net.InetAddress;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+import org.osgi.annotation.versioning.ConsumerType;
/**
* Abstract implementation of the {@code URLStreamHandlerService} interface. All
@@ -27,12 +31,14 @@ import java.net.*;
* {@code setURL} and {@code parseURL(URLStreamHandlerSetter,...)} methods.
*
* @ThreadSafe
- * @version $Id: b86572a4f13b7bb4a343ac4d6b6fb3487e01bd31 $
+ * @author $Id: 79cfc45d97b037436d50bda26111109bd5d42a37 $
*/
+ at ConsumerType
public abstract class AbstractURLStreamHandlerService extends URLStreamHandler implements URLStreamHandlerService {
/**
* @see "java.net.URLStreamHandler.openConnection"
*/
+ @Override
public abstract URLConnection openConnection(URL u) throws java.io.IOException;
/**
@@ -50,7 +56,7 @@ public abstract class AbstractURLStreamHandlerService extends URLStreamHandler i
* invoked for the specified URL.
* @see "java.net.URLStreamHandler.parseURL"
*/
- public void parseURL(URLStreamHandlerSetter realHandler, URL u, String spec, int start, int limit) {
+ public void parseURL(@SuppressWarnings("hiding") URLStreamHandlerSetter realHandler, URL u, String spec, int start, int limit) {
this.realHandler = realHandler;
parseURL(u, spec, start, limit);
}
@@ -60,6 +66,7 @@ public abstract class AbstractURLStreamHandlerService extends URLStreamHandler i
*
* @see "java.net.URLStreamHandler.toExternalForm"
*/
+ @Override
public String toExternalForm(URL u) {
return super.toExternalForm(u);
}
@@ -69,6 +76,7 @@ public abstract class AbstractURLStreamHandlerService extends URLStreamHandler i
*
* @see "java.net.URLStreamHandler.equals(URL,URL)"
*/
+ @Override
public boolean equals(URL u1, URL u2) {
return super.equals(u1, u2);
}
@@ -78,6 +86,7 @@ public abstract class AbstractURLStreamHandlerService extends URLStreamHandler i
*
* @see "java.net.URLStreamHandler.getDefaultPort"
*/
+ @Override
public int getDefaultPort() {
return super.getDefaultPort();
}
@@ -87,6 +96,7 @@ public abstract class AbstractURLStreamHandlerService extends URLStreamHandler i
*
* @see "java.net.URLStreamHandler.getHostAddress"
*/
+ @Override
public InetAddress getHostAddress(URL u) {
return super.getHostAddress(u);
}
@@ -96,6 +106,7 @@ public abstract class AbstractURLStreamHandlerService extends URLStreamHandler i
*
* @see "java.net.URLStreamHandler.hashCode(URL)"
*/
+ @Override
public int hashCode(URL u) {
return super.hashCode(u);
}
@@ -105,6 +116,7 @@ public abstract class AbstractURLStreamHandlerService extends URLStreamHandler i
*
* @see "java.net.URLStreamHandler.hostsEqual"
*/
+ @Override
public boolean hostsEqual(URL u1, URL u2) {
return super.hostsEqual(u1, u2);
}
@@ -114,6 +126,7 @@ public abstract class AbstractURLStreamHandlerService extends URLStreamHandler i
*
* @see "java.net.URLStreamHandler.sameFile"
*/
+ @Override
public boolean sameFile(URL u1, URL u2) {
return super.sameFile(u1, u2);
}
@@ -126,6 +139,7 @@ public abstract class AbstractURLStreamHandlerService extends URLStreamHandler i
* @deprecated This method is only for compatibility with handlers written
* for JDK 1.1.
*/
+ @SuppressWarnings("javadoc")
protected void setURL(URL u, String proto, String host, int port, String file, String ref) {
realHandler.setURL(u, proto, host, port, file, ref);
}
@@ -137,6 +151,7 @@ public abstract class AbstractURLStreamHandlerService extends URLStreamHandler i
*
* @see "java.net.URLStreamHandler.setURL(URL,String,String,int,String,String,String,String)"
*/
+ @Override
protected void setURL(URL u, String proto, String host, int port, String auth, String user, String path, String query, String ref) {
realHandler.setURL(u, proto, host, port, auth, user, path, query, ref);
}
diff --git a/src/main/java/org/osgi/service/url/URLConstants.java b/src/main/java/org/osgi/service/url/URLConstants.java
index 493f352..522c1b8 100644
--- a/src/main/java/org/osgi/service/url/URLConstants.java
+++ b/src/main/java/org/osgi/service/url/URLConstants.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2002, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 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.
@@ -16,6 +16,8 @@
package org.osgi.service.url;
+import org.osgi.annotation.versioning.ProviderType;
+
/**
* Defines standard names for property keys associated with
* {@link URLStreamHandlerService} and {@code java.net.ContentHandler} services.
@@ -24,9 +26,9 @@ package org.osgi.service.url;
* The values associated with these keys are of type {@code java.lang.String[]}
* or {@code java.lang.String}, unless otherwise indicated.
*
- * @noimplement
- * @version $Id: ac2b9670972d6e41d989c51067219ff7be459831 $
+ * @author $Id: 490baaad326523bcb3915ef04572d3c28560db0b $
*/
+ at ProviderType
public interface URLConstants {
/**
* Service property naming the protocols serviced by a
diff --git a/src/main/java/org/osgi/service/url/URLStreamHandlerService.java b/src/main/java/org/osgi/service/url/URLStreamHandlerService.java
index e6dd098..5ba4f7b 100644
--- a/src/main/java/org/osgi/service/url/URLStreamHandlerService.java
+++ b/src/main/java/org/osgi/service/url/URLStreamHandlerService.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2002, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 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.
@@ -16,7 +16,10 @@
package org.osgi.service.url;
-import java.net.*;
+import java.net.InetAddress;
+import java.net.URL;
+import java.net.URLConnection;
+import org.osgi.annotation.versioning.ConsumerType;
/**
* Service interface with public versions of the protected
@@ -33,12 +36,14 @@ import java.net.*;
* @see AbstractURLStreamHandlerService
*
* @ThreadSafe
- * @version $Id: 4a453f61b9acdc6449df389b2a0538d0ccb33ed2 $
+ * @author $Id: 810d8718f5ad689981fbb2c22886ad2695f17297 $
*/
+ at ConsumerType
public interface URLStreamHandlerService {
/**
* @see "java.net.URLStreamHandler.openConnection"
*/
+ @SuppressWarnings("javadoc")
public URLConnection openConnection(URL u) throws java.io.IOException;
/**
@@ -50,40 +55,48 @@ public interface URLStreamHandlerService {
* this URL.
* @see "java.net.URLStreamHandler.parseURL"
*/
+ @SuppressWarnings("javadoc")
public void parseURL(URLStreamHandlerSetter realHandler, URL u, String spec, int start, int limit);
/**
* @see "java.net.URLStreamHandler.toExternalForm"
*/
+ @SuppressWarnings("javadoc")
public String toExternalForm(URL u);
/**
* @see "java.net.URLStreamHandler.equals(URL, URL)"
*/
+ @SuppressWarnings("javadoc")
public boolean equals(URL u1, URL u2);
/**
* @see "java.net.URLStreamHandler.getDefaultPort"
*/
+ @SuppressWarnings("javadoc")
public int getDefaultPort();
/**
* @see "java.net.URLStreamHandler.getHostAddress"
*/
+ @SuppressWarnings("javadoc")
public InetAddress getHostAddress(URL u);
/**
* @see "java.net.URLStreamHandler.hashCode(URL)"
*/
+ @SuppressWarnings("javadoc")
public int hashCode(URL u);
/**
* @see "java.net.URLStreamHandler.hostsEqual"
*/
+ @SuppressWarnings("javadoc")
public boolean hostsEqual(URL u1, URL u2);
/**
* @see "java.net.URLStreamHandler.sameFile"
*/
+ @SuppressWarnings("javadoc")
public boolean sameFile(URL u1, URL u2);
}
diff --git a/src/main/java/org/osgi/service/url/URLStreamHandlerSetter.java b/src/main/java/org/osgi/service/url/URLStreamHandlerSetter.java
index 90feae6..d7e222a 100644
--- a/src/main/java/org/osgi/service/url/URLStreamHandlerSetter.java
+++ b/src/main/java/org/osgi/service/url/URLStreamHandlerSetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2002, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2002, 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.
@@ -17,6 +17,7 @@
package org.osgi.service.url;
import java.net.URL;
+import org.osgi.annotation.versioning.ConsumerType;
/**
* Interface used by {@code URLStreamHandlerService} objects to call the
@@ -31,8 +32,9 @@ import java.net.URL;
* {@code java.net.URL} for the protocol.
*
* @ThreadSafe
- * @version $Id: 90f25e3961fea2150cfd31117a2237304f1518f9 $
+ * @author $Id: 96648b48a7ce8fb4baf50c7b118a0339f4efcf35 $
*/
+ at ConsumerType
public interface URLStreamHandlerSetter {
/**
* @see "java.net.URLStreamHandler.setURL(URL,String,String,int,String,String)"
@@ -40,10 +42,12 @@ public interface URLStreamHandlerSetter {
* @deprecated This method is only for compatibility with handlers written
* for JDK 1.1.
*/
+ @SuppressWarnings("javadoc")
public void setURL(URL u, String protocol, String host, int port, String file, String ref);
/**
* @see "java.net.URLStreamHandler.setURL(URL,String,String,int,String,String,String,String)"
*/
+ @SuppressWarnings("javadoc")
public void setURL(URL u, String protocol, String host, int port, String authority, String userInfo, String path, String query, String ref);
}
diff --git a/src/main/java/org/osgi/framework/BundleReference.java b/src/main/java/org/osgi/service/url/package-info.java
similarity index 50%
copy from src/main/java/org/osgi/framework/BundleReference.java
copy to src/main/java/org/osgi/service/url/package-info.java
index 97340f7..3e73e2b 100644
--- a/src/main/java/org/osgi/framework/BundleReference.java
+++ b/src/main/java/org/osgi/service/url/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2009, 2010). 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.
@@ -14,23 +14,23 @@
* limitations under the License.
*/
-package org.osgi.framework;
-
/**
- * A reference to a Bundle.
+ * URL Stream and Content Handlers 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.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.service.url; version="[1.0,2.0)"}
*
- * @since 1.5
- * @ThreadSafe
- * @noimplement
- * @version $Id: e61bd3e020264b04022a430fe09a85ee3aabf1a3 $
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
*/
-public interface BundleReference {
- /**
- * Returns the {@code Bundle} object associated with this
- * {@code BundleReference}.
- *
- * @return The {@code Bundle} object associated with this
- * {@code BundleReference}.
- */
- public Bundle getBundle();
-}
+
+ at Version("1.0")
+package org.osgi.service.url;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/service/url/packageinfo b/src/main/java/org/osgi/service/url/packageinfo
new file mode 100644
index 0000000..7c8de03
--- /dev/null
+++ b/src/main/java/org/osgi/service/url/packageinfo
@@ -0,0 +1 @@
+version 1.0
diff --git a/src/main/java/org/osgi/util/tracker/AbstractTracked.java b/src/main/java/org/osgi/util/tracker/AbstractTracked.java
index f3ddddc..9aa0bd4 100644
--- a/src/main/java/org/osgi/util/tracker/AbstractTracked.java
+++ b/src/main/java/org/osgi/util/tracker/AbstractTracked.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2007, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2007, 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.
@@ -34,7 +34,7 @@ import java.util.Map;
* @param <T> The value mapped to the tracked item.
* @param <R> The reason the tracked item is being tracked or untracked.
* @ThreadSafe
- * @version $Id: 16340086b98d308c2d12f13bcd87fc6467a5a367 $
+ * @author $Id: 5988d793936c25139421a95bad2d3cd96e2ab355 $
* @since 1.4
*/
abstract class AbstractTracked<S, T, R> {
diff --git a/src/main/java/org/osgi/util/tracker/BundleTracker.java b/src/main/java/org/osgi/util/tracker/BundleTracker.java
index 7e1bb53..18eaa99 100644
--- a/src/main/java/org/osgi/util/tracker/BundleTracker.java
+++ b/src/main/java/org/osgi/util/tracker/BundleTracker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2007, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2007, 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.
@@ -44,7 +44,7 @@ import org.osgi.framework.SynchronousBundleListener;
*
* @param <T> The type of the tracked object.
* @ThreadSafe
- * @version $Id: f21db4fe54284d4810bd9b5fa2528957804e3a21 $
+ * @author $Id: 9a1b57568a8be735292700584f4eb936fc80f2ff $
* @since 1.4
*/
public class BundleTracker<T> implements BundleTrackerCustomizer<T> {
@@ -218,6 +218,7 @@ public class BundleTracker<T> implements BundleTrackerCustomizer<T> {
* @see BundleTrackerCustomizer#addingBundle(Bundle, BundleEvent)
*/
public T addingBundle(Bundle bundle, BundleEvent event) {
+ @SuppressWarnings("unchecked")
T result = (T) bundle;
return result;
}
@@ -463,6 +464,7 @@ public class BundleTracker<T> implements BundleTrackerCustomizer<T> {
* @return Customized object for the tracked item or {@code null} if the
* item is not to be tracked.
*/
+ @Override
T customizerAdding(final Bundle item, final BundleEvent related) {
return customizer.addingBundle(item, related);
}
@@ -475,6 +477,7 @@ public class BundleTracker<T> implements BundleTrackerCustomizer<T> {
* @param related Action related object.
* @param object Customized object for the tracked item.
*/
+ @Override
void customizerModified(final Bundle item, final BundleEvent related, final T object) {
customizer.modifiedBundle(item, related, object);
}
@@ -487,6 +490,7 @@ public class BundleTracker<T> implements BundleTrackerCustomizer<T> {
* @param related Action related object.
* @param object Customized object for the tracked item.
*/
+ @Override
void customizerRemoved(final Bundle item, final BundleEvent related, final T object) {
customizer.removedBundle(item, related, object);
}
diff --git a/src/main/java/org/osgi/util/tracker/BundleTrackerCustomizer.java b/src/main/java/org/osgi/util/tracker/BundleTrackerCustomizer.java
index b0bb297..8a62f2c 100644
--- a/src/main/java/org/osgi/util/tracker/BundleTrackerCustomizer.java
+++ b/src/main/java/org/osgi/util/tracker/BundleTrackerCustomizer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2007, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2007, 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.
@@ -16,6 +16,7 @@
package org.osgi.util.tracker;
+import org.osgi.annotation.versioning.ConsumerType;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleEvent;
@@ -42,9 +43,10 @@ import org.osgi.framework.BundleEvent;
*
* @param <T> The type of the tracked object.
* @ThreadSafe
- * @version $Id: 727e757d2fa2940c88c9b74c8d299de6b3a7d0d0 $
+ * @author $Id: 031b2979522768150d23ee70dfe62528432c19f7 $
* @since 1.4
*/
+ at ConsumerType
public interface BundleTrackerCustomizer<T> {
/**
* A bundle is being added to the {@code BundleTracker}.
diff --git a/src/main/java/org/osgi/util/tracker/ServiceTracker.java b/src/main/java/org/osgi/util/tracker/ServiceTracker.java
index 0c8022d..3ba97ab 100644
--- a/src/main/java/org/osgi/util/tracker/ServiceTracker.java
+++ b/src/main/java/org/osgi/util/tracker/ServiceTracker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2000, 2012). All Rights Reserved.
+ * Copyright (c) OSGi Alliance (2000, 2014). 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.
@@ -52,7 +52,7 @@ import org.osgi.framework.ServiceReference;
* @param <S> The type of the service being tracked.
* @param <T> The type of the tracked object.
* @ThreadSafe
- * @version $Id: 21926ad8717a91633face6bbf570febfcd23b1c7 $
+ * @author $Id: a0af979aa9c88a89f220c1b2d8d7c060ced41006 $
*/
public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
/* set this to true to compile in debug messages */
@@ -298,6 +298,7 @@ public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
} else {
if (trackReference != null) {
if (trackReference.getBundle() != null) {
+ @SuppressWarnings("unchecked")
ServiceReference<S>[] single = new ServiceReference[] {trackReference};
references = single;
}
@@ -331,6 +332,7 @@ public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
* invalid syntax.
*/
private ServiceReference<S>[] getInitialReferences(boolean trackAllServices, String className, String filterString) throws InvalidSyntaxException {
+ @SuppressWarnings("unchecked")
ServiceReference<S>[] result = (ServiceReference<S>[]) ((trackAllServices) ? context.getAllServiceReferences(className, filterString) : context.getServiceReferences(className, filterString));
return result;
}
@@ -408,6 +410,7 @@ public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
* @see ServiceTrackerCustomizer#addingService(ServiceReference)
*/
public T addingService(ServiceReference<S> reference) {
+ @SuppressWarnings("unchecked")
T result = (T) context.getService(reference);
return result;
}
@@ -527,6 +530,7 @@ public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
if (length == 0) {
return null;
}
+ @SuppressWarnings("unchecked")
ServiceReference<S>[] result = new ServiceReference[length];
return t.copyKeys(result);
}
@@ -540,7 +544,7 @@ public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
* If multiple services are being tracked, the service with the highest
* ranking (as specified in its {@code service.ranking} property) is
* returned. If there is a tie in ranking, the service with the lowest
- * service ID (as specified in its {@code service.id} property); that is,
+ * service id (as specified in its {@code service.id} property); that is,
* the service that was registered first is returned. This is the same
* algorithm used by {@code BundleContext.getServiceReference}.
*
@@ -843,7 +847,9 @@ public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
return array;
}
if (length > array.length) {
- array = (T[]) Array.newInstance(array.getClass().getComponentType(), length);
+ @SuppressWarnings("unchecked")
+ T[] newInstance = (T[]) Array.newInstance(array.getClass().getComponentType(), length);
+ array = newInstance;
}
for (int i = 0; i < length; i++) {
array[i] = getService(references[i]);
@@ -883,6 +889,7 @@ public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
if (closed) {
return;
}
+ @SuppressWarnings("unchecked")
final ServiceReference<S> reference = (ServiceReference<S>) event.getServiceReference();
if (DEBUG) {
System.out.println("ServiceTracker.Tracked.serviceChanged[" + event.getType() + "]: " + reference);
@@ -914,6 +921,7 @@ public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
*
* @GuardedBy this
*/
+ @Override
final void modified() {
super.modified(); /* increment the modification count */
ServiceTracker.this.modified();
@@ -928,6 +936,7 @@ public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
* @return Customized object for the tracked item or {@code null} if the
* item is not to be tracked.
*/
+ @Override
final T customizerAdding(final ServiceReference<S> item, final ServiceEvent related) {
return customizer.addingService(item);
}
@@ -940,6 +949,7 @@ public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
* @param related Action related object.
* @param object Customized object for the tracked item.
*/
+ @Override
final void customizerModified(final ServiceReference<S> item, final ServiceEvent related, final T object) {
customizer.modifiedService(item, object);
}
@@ -952,6 +962,7 @@ public class ServiceTracker<S, T> implements ServiceTrackerCustomizer<S, T> {
* @param related Action related object.
* @param object Customized object for the tracked item.
*/
+ @Override
final void customizerRemoved(final ServiceReference<S> item, final ServiceEvent related, final T object) {
customizer.removedService(item, object);
}
diff --git a/src/main/java/org/osgi/util/tracker/ServiceTrackerCustomizer.java b/src/main/java/org/osgi/util/tracker/ServiceTrackerCustomizer.java
index 72bec7a..6aa95cb 100644
--- a/src/main/java/org/osgi/util/tracker/ServiceTrackerCustomizer.java
+++ b/src/main/java/org/osgi/util/tracker/ServiceTrackerCustomizer.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.
@@ -16,6 +16,7 @@
package org.osgi.util.tracker;
+import org.osgi.annotation.versioning.ConsumerType;
import org.osgi.framework.ServiceReference;
/**
@@ -45,8 +46,9 @@ import org.osgi.framework.ServiceReference;
* @param <S> The type of the service being tracked.
* @param <T> The type of the tracked object.
* @ThreadSafe
- * @version $Id: c14b8d47026b6bd4ba1f2db7bf7e755d00fc6f6a $
+ * @author $Id: 0c3333455f7d80a7793c77ac9671baa4a02a89b9 $
*/
+ at ConsumerType
public interface ServiceTrackerCustomizer<S, T> {
/**
* A service is being added to the {@code ServiceTracker}.
diff --git a/src/main/java/org/osgi/framework/BundleReference.java b/src/main/java/org/osgi/util/tracker/package-info.java
similarity index 51%
copy from src/main/java/org/osgi/framework/BundleReference.java
copy to src/main/java/org/osgi/util/tracker/package-info.java
index 97340f7..f91b7f1 100644
--- a/src/main/java/org/osgi/framework/BundleReference.java
+++ b/src/main/java/org/osgi/util/tracker/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) OSGi Alliance (2009, 2010). 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.
@@ -14,23 +14,23 @@
* limitations under the License.
*/
-package org.osgi.framework;
-
/**
- * A reference to a Bundle.
+ * Tracker Package Version 1.5.
+ *
+ * <p>
+ * Bundles wishing to use this package must list the package in the
+ * Import-Package header of the bundle's manifest.
+ *
+ * <p>
+ * Example import for consumers using the API in this package:
+ * <p>
+ * {@code Import-Package: org.osgi.util.tracker; version="[1.5,2.0)"}
*
- * @since 1.5
- * @ThreadSafe
- * @noimplement
- * @version $Id: e61bd3e020264b04022a430fe09a85ee3aabf1a3 $
+ * @author $Id: package-info.java 1614569 2014-07-30 07:22:32Z cziegeler $
*/
-public interface BundleReference {
- /**
- * Returns the {@code Bundle} object associated with this
- * {@code BundleReference}.
- *
- * @return The {@code Bundle} object associated with this
- * {@code BundleReference}.
- */
- public Bundle getBundle();
-}
+
+ at Version("1.5.1")
+package org.osgi.util.tracker;
+
+import org.osgi.annotation.versioning.Version;
+
diff --git a/src/main/java/org/osgi/util/tracker/packageinfo b/src/main/java/org/osgi/util/tracker/packageinfo
new file mode 100644
index 0000000..1213efd
--- /dev/null
+++ b/src/main/java/org/osgi/util/tracker/packageinfo
@@ -0,0 +1 @@
+version 1.5.1
diff --git a/src/main/resources/default.properties b/src/main/resources/default.properties
index dd2f6ad..5c3497c 100644
--- a/src/main/resources/default.properties
+++ b/src/main/resources/default.properties
@@ -22,9 +22,57 @@
# New-style generic execution environment capabilities.
org.osgi.framework.system.capabilities= \
${dollar}{eecap-${dollar}{java.specification.version}}
+
+# Native Processor Aliases. Format is felix.native.processor.alias.<normalized Processor Name>=alias1,alias2
+felix.native.processor.alias.68k=
+felix.native.processor.alias.arm=
+felix.native.processor.alias.arm_le=
+felix.native.processor.alias.arm_be=
+felix.native.processor.alias.alpha=
+felix.native.processor.alias.ignite=psc1k
+felix.native.processor.alias.mips=
+felix.native.processor.alias.parisc=
+felix.native.processor.alias.powerpc=power,ppc
+felix.native.processor.alias.x86=pentium,i386,i486,i586,i686
+felix.native.processor.alias.x86-64=amd64,em64t,x86_64
+felix.native.processor.alias.sparc=
+
+# Native Operating System Name Aliases. Format is felix.native.osname.alias.<normalized OS Name>=alias1,alias2
+felix.native.osname.alias.aix=
+felix.native.osname.alias.digitalunix=
+felix.native.osname.alias.epoc32=symbianos
+felix.native.osname.alias.hpux=hp-ux
+felix.native.osname.alias.irix=
+felix.native.osname.alias.linux=
+felix.native.osname.alias.macos=mac os
+felix.native.osname.alias.macosx=mac os x
+felix.native.osname.alias.netbsd=
+felix.native.osname.alias.netware=
+felix.native.osname.alias.openbsd=
+felix.native.osname.alias.os2=os/2
+felix.native.osname.alias.qnx=procnto
+felix.native.osname.alias.solaris=
+felix.native.osname.alias.sunos=
+felix.native.osname.alias.vxworks=
+felix.native.osname.alias.windows95=win95,windows 95,win32
+felix.native.osname.alias.windows98=win98,windows 98,win32
+felix.native.osname.alias.windowsnt=winnt,windows nt,win32
+felix.native.osname.alias.windowsce=wince,windows ce
+felix.native.osname.alias.windows2000=win2000,windows 2000,win32
+felix.native.osname.alias.windows2003=win2003,windows 2003,win32,windows server 2003
+felix.native.osname.alias.windowsxp=winxp,windows xp,win32
+felix.native.osname.alias.windowsvista=winvista,windows vista,win32
+felix.native.osname.alias.windows7=windows 7,win32
+felix.native.osname.alias.windows8=windows 8,win32
+felix.native.osname.alias.windows9=windows 9,win32
+felix.native.osname.alias.windowsserver2008=windows server 2008,win32
+felix.native.osname.alias.win32=
eecap-1.8= osgi.ee; osgi.ee="OSGi/Minimum"; version:List<Version>="1.0,1.1,1.2", \
- osgi.ee; osgi.ee="JavaSE"; version:List<Version>="1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8"
+ osgi.ee; osgi.ee="JavaSE"; version:List<Version>="1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7,1.8", \
+ osgi.ee; osgi.ee="JavaSE/compact1"; version:List<Version>="1.8", \
+ osgi.ee; osgi.ee="JavaSE/compact2"; version:List<Version>="1.8", \
+ osgi.ee; osgi.ee="JavaSE/compact3"; version:List<Version>="1.8"
eecap-1.7= osgi.ee; osgi.ee="OSGi/Minimum"; version:List<Version>="1.0,1.1,1.2", \
osgi.ee; osgi.ee="JavaSE"; version:List<Version>="1.0,1.1,1.2,1.3,1.4,1.5,1.6,1.7"
eecap-1.6= osgi.ee; osgi.ee="OSGi/Minimum"; version:List<Version>="1.0,1.1,1.2", \
@@ -58,16 +106,21 @@ ee-1.3=J2SE-1.3,J2SE-1.2,JRE-1.1,JRE-1.0,OSGi/Minimum-1.1,OSGi/Minimum-1.0
ee-1.2=J2SE-1.2,JRE-1.1,JRE-1.0,OSGi/Minimum-1.1,OSGi/Minimum-1.0
# Default packages exported by system bundle.
-org.osgi.framework.system.packages=org.osgi.framework; version=1.7.0, \
+org.osgi.framework.system.packages=org.osgi.dto; version=1.0.0, \
+ org.osgi.framework; version=1.8.0, \
+ org.osgi.framework.dto; version=1.8.0, \
org.osgi.framework.hooks.bundle; version=1.1.0, \
org.osgi.framework.hooks.resolver; version=1.0.0, \
org.osgi.framework.hooks.service; version=1.1.0, \
- org.osgi.framework.hooks.weaving; version=1.0.0, \
- org.osgi.framework.launch; version=1.1.0, \
- org.osgi.framework.namespace; version=1.0.0, \
+ org.osgi.framework.hooks.weaving; version=1.1.0, \
+ org.osgi.framework.launch; version=1.2.0, \
+ org.osgi.framework.namespace; version=1.1.0, \
org.osgi.framework.startlevel; version=1.0.0, \
- org.osgi.framework.wiring; version=1.1.0, \
+ org.osgi.framework.startlevel.dto; version=1.0.0, \
+ org.osgi.framework.wiring; version=1.2.0, \
+ org.osgi.framework.wiring.dto; version=1.2.0, \
org.osgi.resource; version=1.0.0, \
+ org.osgi.resource.dto; version=1.0.0, \
org.osgi.service.packageadmin; version=1.2.0, \
org.osgi.service.startlevel; version=1.1.0, \
org.osgi.service.url; version=1.0.0, \
diff --git a/src/test/java/org/apache/felix/framework/BundleWiringImplTest.java b/src/test/java/org/apache/felix/framework/BundleWiringImplTest.java
new file mode 100644
index 0000000..a2ddf68
--- /dev/null
+++ b/src/test/java/org/apache/felix/framework/BundleWiringImplTest.java
@@ -0,0 +1,464 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.*;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.framework.BundleWiringImpl.BundleClassLoader;
+import org.apache.felix.framework.BundleWiringImpl.BundleClassLoaderJava5;
+import org.apache.felix.framework.cache.Content;
+import org.junit.Test;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.FieldNode;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.hooks.weaving.WeavingException;
+import org.osgi.framework.hooks.weaving.WeavingHook;
+import org.osgi.framework.hooks.weaving.WovenClass;
+import org.osgi.framework.hooks.weaving.WovenClassListener;
+import org.osgi.framework.wiring.BundleRevision;
+import org.osgi.framework.wiring.BundleWire;
+
+public class BundleWiringImplTest
+{
+
+ private BundleWiringImpl bundleWiring;
+
+ private StatefulResolver mockResolver;
+
+ private BundleRevisionImpl mockRevisionImpl;
+
+ private BundleImpl mockBundle;
+
+ @SuppressWarnings("rawtypes")
+ public void initializeSimpleBundleWiring() throws Exception
+ {
+
+ mockResolver = mock(StatefulResolver.class);
+ mockRevisionImpl = mock(BundleRevisionImpl.class);
+ mockBundle = mock(BundleImpl.class);
+
+ Logger logger = new Logger();
+ Map configMap = new HashMap();
+ List<BundleRevision> fragments = new ArrayList<BundleRevision>();
+ List<BundleWire> wires = new ArrayList<BundleWire>();
+ Map<String, BundleRevision> importedPkgs = new HashMap<String, BundleRevision>();
+ Map<String, List<BundleRevision>> requiredPkgs = new HashMap<String, List<BundleRevision>>();
+
+ when(mockRevisionImpl.getBundle()).thenReturn(mockBundle);
+ when(mockBundle.getBundleId()).thenReturn(Long.valueOf(1));
+
+ bundleWiring = new BundleWiringImpl(logger, configMap, mockResolver,
+ mockRevisionImpl, fragments, wires, importedPkgs, requiredPkgs);
+ }
+
+ @Test
+ public void testBundleClassLoader() throws Exception
+ {
+ bundleWiring = mock(BundleWiringImpl.class);
+ BundleClassLoader bundleClassLoader = createBundleClassLoader(
+ BundleClassLoader.class, bundleWiring);
+ assertNotNull(bundleClassLoader);
+ }
+
+ @Test
+ public void testBundleClassLoaderJava5() throws Exception
+ {
+ bundleWiring = mock(BundleWiringImpl.class);
+ BundleClassLoader bundleClassLoader = createBundleClassLoader(
+ BundleClassLoaderJava5.class, bundleWiring);
+ assertNotNull(bundleClassLoader);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Test
+ public void testFindClassNonExistant() throws Exception
+ {
+ initializeSimpleBundleWiring();
+
+ BundleClassLoader bundleClassLoader = createBundleClassLoader(
+ BundleClassLoaderJava5.class, bundleWiring);
+ assertNotNull(bundleClassLoader);
+ Class foundClass = null;
+ try
+ {
+ foundClass = bundleClassLoader
+ .findClass("org.apache.felix.test.NonExistant");
+ } catch (ClassNotFoundException e)
+ {
+ fail("Class should not throw exception");
+ }
+ assertNull("Nonexistant Class Should be null", foundClass);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Test
+ public void testFindClassExistant() throws Exception
+ {
+ Felix mockFramework = mock(Felix.class);
+ Content mockContent = mock(Content.class);
+ Class testClass = TestClass.class;
+ String testClassName = testClass.getName();
+ String testClassAsPath = testClassName.replace('.', '/') + ".class";
+ byte[] testClassBytes = createTestClassBytes(testClass, testClassAsPath);
+
+ List<Content> contentPath = new ArrayList<Content>();
+ contentPath.add(mockContent);
+ initializeSimpleBundleWiring();
+
+ when(mockBundle.getFramework()).thenReturn(mockFramework);
+ when(mockFramework.getBootPackages()).thenReturn(new String[0]);
+
+ when(mockRevisionImpl.getContentPath()).thenReturn(contentPath);
+ when(mockContent.getEntryAsBytes(testClassAsPath)).thenReturn(
+ testClassBytes);
+
+ BundleClassLoader bundleClassLoader = createBundleClassLoader(
+ BundleClassLoaderJava5.class, bundleWiring);
+ assertNotNull(bundleClassLoader);
+ Class foundClass = null;
+ try
+ {
+
+ foundClass = bundleClassLoader.findClass(TestClass.class.getName());
+ } catch (ClassNotFoundException e)
+ {
+ fail("Class should not throw exception");
+ }
+ assertNotNull("Class Should be found in this classloader", foundClass);
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testFindClassWeave() throws Exception
+ {
+ Felix mockFramework = mock(Felix.class);
+ Content mockContent = mock(Content.class);
+ ServiceReference<WeavingHook> mockServiceReferenceWeavingHook = mock(ServiceReference.class);
+ ServiceReference<WovenClassListener> mockServiceReferenceWovenClassListener = mock(ServiceReference.class);
+
+ Set<ServiceReference<WeavingHook>> hooks = new HashSet<ServiceReference<WeavingHook>>();
+ hooks.add(mockServiceReferenceWeavingHook);
+
+ DummyWovenClassListener dummyWovenClassListener = new DummyWovenClassListener();
+
+ Set<ServiceReference<WovenClassListener>> listeners = new HashSet<ServiceReference<WovenClassListener>>();
+ listeners.add(mockServiceReferenceWovenClassListener);
+
+ Class testClass = TestClass.class;
+ String testClassName = testClass.getName();
+ String testClassAsPath = testClassName.replace('.', '/') + ".class";
+ byte[] testClassBytes = createTestClassBytes(testClass, testClassAsPath);
+
+ List<Content> contentPath = new ArrayList<Content>();
+ contentPath.add(mockContent);
+ initializeSimpleBundleWiring();
+
+ when(mockBundle.getFramework()).thenReturn(mockFramework);
+ when(mockFramework.getBootPackages()).thenReturn(new String[0]);
+
+ when(mockRevisionImpl.getContentPath()).thenReturn(contentPath);
+ when(mockContent.getEntryAsBytes(testClassAsPath)).thenReturn(
+ testClassBytes);
+
+ when(mockFramework.getHooks(WeavingHook.class)).thenReturn(hooks);
+ when(
+ mockFramework.getService(mockFramework,
+ mockServiceReferenceWeavingHook, false)).thenReturn(
+ new GoodDummyWovenHook());
+
+ when(mockFramework.getHooks(WovenClassListener.class)).thenReturn(
+ listeners);
+ when(
+ mockFramework.getService(mockFramework,
+ mockServiceReferenceWovenClassListener, false))
+ .thenReturn(dummyWovenClassListener);
+
+ BundleClassLoader bundleClassLoader = createBundleClassLoader(
+ BundleClassLoaderJava5.class, bundleWiring);
+ assertNotNull(bundleClassLoader);
+ Class foundClass = null;
+ try
+ {
+
+ foundClass = bundleClassLoader.findClass(TestClass.class.getName());
+ } catch (ClassNotFoundException e)
+ {
+ fail("Class should not throw exception");
+ }
+ assertNotNull("Class Should be found in this classloader", foundClass);
+ assertEquals("Weaving should have added a field", 1,
+ foundClass.getFields().length);
+ assertEquals("There should be 2 state changes fired by the weaving", 2,
+ dummyWovenClassListener.stateList.size());
+ assertEquals("The first state change should transform the class",
+ WovenClass.TRANSFORMED,
+ dummyWovenClassListener.stateList.get(0));
+ assertEquals("The second state change should define the class",
+ WovenClass.DEFINED, dummyWovenClassListener.stateList.get(1));
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testFindClassBadWeave() throws Exception
+ {
+ Felix mockFramework = mock(Felix.class);
+ Content mockContent = mock(Content.class);
+ ServiceReference<WeavingHook> mockServiceReferenceWeavingHook = mock(ServiceReference.class);
+ ServiceReference<WovenClassListener> mockServiceReferenceWovenClassListener = mock(ServiceReference.class);
+
+ Set<ServiceReference<WeavingHook>> hooks = new HashSet<ServiceReference<WeavingHook>>();
+ hooks.add(mockServiceReferenceWeavingHook);
+
+ DummyWovenClassListener dummyWovenClassListener = new DummyWovenClassListener();
+
+ Set<ServiceReference<WovenClassListener>> listeners = new HashSet<ServiceReference<WovenClassListener>>();
+ listeners.add(mockServiceReferenceWovenClassListener);
+
+ Class testClass = TestClass.class;
+ String testClassName = testClass.getName();
+ String testClassAsPath = testClassName.replace('.', '/') + ".class";
+ byte[] testClassBytes = createTestClassBytes(testClass, testClassAsPath);
+
+ List<Content> contentPath = new ArrayList<Content>();
+ contentPath.add(mockContent);
+ initializeSimpleBundleWiring();
+
+ when(mockBundle.getFramework()).thenReturn(mockFramework);
+ when(mockFramework.getBootPackages()).thenReturn(new String[0]);
+
+ when(mockRevisionImpl.getContentPath()).thenReturn(contentPath);
+ when(mockContent.getEntryAsBytes(testClassAsPath)).thenReturn(
+ testClassBytes);
+
+ when(mockFramework.getHooks(WeavingHook.class)).thenReturn(hooks);
+ when(
+ mockFramework.getService(mockFramework,
+ mockServiceReferenceWeavingHook, false)).thenReturn(
+ new BadDummyWovenHook());
+
+ when(mockFramework.getHooks(WovenClassListener.class)).thenReturn(
+ listeners);
+ when(
+ mockFramework.getService(mockFramework,
+ mockServiceReferenceWovenClassListener, false))
+ .thenReturn(dummyWovenClassListener);
+
+ BundleClassLoader bundleClassLoader = createBundleClassLoader(
+ BundleClassLoaderJava5.class, bundleWiring);
+ assertNotNull(bundleClassLoader);
+
+ try
+ {
+
+ bundleClassLoader.findClass(TestClass.class.getName());
+ fail("Class should throw exception");
+ } catch (Error e)
+ {
+ // This is expected
+ }
+
+ assertEquals("There should be 1 state changes fired by the weaving", 1,
+ dummyWovenClassListener.stateList.size());
+ assertEquals(
+ "The only state change should be a failed transform on the class",
+ WovenClass.TRANSFORMING_FAILED,
+ dummyWovenClassListener.stateList.get(0));
+
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void testFindClassWeaveDefineError() throws Exception
+ {
+ Felix mockFramework = mock(Felix.class);
+ Content mockContent = mock(Content.class);
+ ServiceReference<WeavingHook> mockServiceReferenceWeavingHook = mock(ServiceReference.class);
+ ServiceReference<WovenClassListener> mockServiceReferenceWovenClassListener = mock(ServiceReference.class);
+
+ Set<ServiceReference<WeavingHook>> hooks = new HashSet<ServiceReference<WeavingHook>>();
+ hooks.add(mockServiceReferenceWeavingHook);
+
+ DummyWovenClassListener dummyWovenClassListener = new DummyWovenClassListener();
+
+ Set<ServiceReference<WovenClassListener>> listeners = new HashSet<ServiceReference<WovenClassListener>>();
+ listeners.add(mockServiceReferenceWovenClassListener);
+
+ Class testClass = TestClass.class;
+ String testClassName = testClass.getName();
+ String testClassAsPath = testClassName.replace('.', '/') + ".class";
+ byte[] testClassBytes = createTestClassBytes(testClass, testClassAsPath);
+
+ List<Content> contentPath = new ArrayList<Content>();
+ contentPath.add(mockContent);
+ initializeSimpleBundleWiring();
+
+ when(mockBundle.getFramework()).thenReturn(mockFramework);
+ when(mockFramework.getBootPackages()).thenReturn(new String[0]);
+
+ when(mockRevisionImpl.getContentPath()).thenReturn(contentPath);
+ when(mockContent.getEntryAsBytes(testClassAsPath)).thenReturn(
+ testClassBytes);
+
+ when(mockFramework.getHooks(WeavingHook.class)).thenReturn(hooks);
+ when(
+ mockFramework.getService(mockFramework,
+ mockServiceReferenceWeavingHook, false)).thenReturn(
+ new BadDefineWovenHook());
+
+ when(mockFramework.getHooks(WovenClassListener.class)).thenReturn(
+ listeners);
+ when(
+ mockFramework.getService(mockFramework,
+ mockServiceReferenceWovenClassListener, false))
+ .thenReturn(dummyWovenClassListener);
+
+ BundleClassLoader bundleClassLoader = createBundleClassLoader(
+ BundleClassLoaderJava5.class, bundleWiring);
+ assertNotNull(bundleClassLoader);
+ try
+ {
+
+ bundleClassLoader.findClass(TestClass.class.getName());
+ fail("Class should throw exception");
+ } catch (Throwable e)
+ {
+
+ }
+ assertEquals("There should be 2 state changes fired by the weaving", 2,
+ dummyWovenClassListener.stateList.size());
+ assertEquals("The first state change should transform the class",
+ WovenClass.TRANSFORMED,
+ dummyWovenClassListener.stateList.get(0));
+ assertEquals("The second state change failed the define on the class",
+ WovenClass.DEFINE_FAILED,
+ dummyWovenClassListener.stateList.get(1));
+ }
+
+ @SuppressWarnings("rawtypes")
+ private byte[] createTestClassBytes(Class testClass, String testClassAsPath)
+ throws IOException
+ {
+ InputStream testClassResourceStream = testClass.getClassLoader()
+ .getResourceAsStream(testClassAsPath);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ int curByte;
+ while ((curByte = testClassResourceStream.read()) != -1)
+ {
+ baos.write(curByte);
+ }
+ byte[] testClassBytes = baos.toByteArray();
+ return testClassBytes;
+ }
+
+ @SuppressWarnings("rawtypes")
+ private BundleClassLoader createBundleClassLoader(
+ Class bundleClassLoaderClass, BundleWiringImpl bundleWiring)
+ throws Exception
+ {
+ Logger logger = new Logger();
+ Constructor ctor = BundleRevisionImpl.getSecureAction().getConstructor(
+ bundleClassLoaderClass,
+ new Class[] { BundleWiringImpl.class, ClassLoader.class,
+ Logger.class });
+ BundleClassLoader bundleClassLoader = (BundleClassLoader) BundleRevisionImpl
+ .getSecureAction().invoke(
+ ctor,
+ new Object[] { bundleWiring,
+ this.getClass().getClassLoader(), logger });
+ return bundleClassLoader;
+ }
+
+ class TestClass
+ {
+ // An empty test class to weave.
+ }
+
+ class GoodDummyWovenHook implements WeavingHook
+ {
+ // Adds the awesomePublicField to a class
+ @SuppressWarnings("unchecked")
+ public void weave(WovenClass wovenClass)
+ {
+ byte[] wovenClassBytes = wovenClass.getBytes();
+ ClassNode classNode = new ClassNode();
+ ClassReader reader = new ClassReader(wovenClassBytes);
+ reader.accept(classNode, 0);
+ classNode.fields.add(new FieldNode(Opcodes.ACC_PUBLIC,
+ "awesomePublicField", "Ljava/lang/String;", null, null));
+ ClassWriter writer = new ClassWriter(reader, Opcodes.ASM4);
+ classNode.accept(writer);
+ wovenClass.setBytes(writer.toByteArray());
+ }
+ }
+
+ class BadDefineWovenHook implements WeavingHook
+ {
+ // Adds the awesomePublicField twice to the class. This is bad java.
+ @SuppressWarnings("unchecked")
+ public void weave(WovenClass wovenClass)
+ {
+ byte[] wovenClassBytes = wovenClass.getBytes();
+ ClassNode classNode = new ClassNode();
+ ClassReader reader = new ClassReader(wovenClassBytes);
+ reader.accept(classNode, 0);
+ classNode.fields.add(new FieldNode(Opcodes.ACC_PUBLIC,
+ "awesomePublicField", "Ljava/lang/String;", null, null));
+ classNode.fields.add(new FieldNode(Opcodes.ACC_PUBLIC,
+ "awesomePublicField", "Ljava/lang/String;", null, null));
+ ClassWriter writer = new ClassWriter(reader, Opcodes.ASM4);
+ classNode.accept(writer);
+ wovenClass.setBytes(writer.toByteArray());
+ }
+ }
+
+ class BadDummyWovenHook implements WeavingHook
+ {
+ // Just Blow up
+ public void weave(WovenClass wovenClass)
+ {
+ throw new WeavingException("Bad Weaver!");
+ }
+ }
+
+ class DummyWovenClassListener implements WovenClassListener
+ {
+ public List<Integer> stateList = new ArrayList<Integer>();
+
+ public void modified(WovenClass wovenClass)
+ {
+ stateList.add(wovenClass.getState());
+ }
+ }
+}
diff --git a/src/test/java/org/apache/felix/framework/CollisionHookTest.java b/src/test/java/org/apache/felix/framework/CollisionHookTest.java
index 31eafd0..63496a5 100644
--- a/src/test/java/org/apache/felix/framework/CollisionHookTest.java
+++ b/src/test/java/org/apache/felix/framework/CollisionHookTest.java
@@ -66,7 +66,7 @@ public class CollisionHookTest extends TestCase
{
differentBundle, identicalBundle
});
- Mockito.when(felixMock.getService(felixMock, chRef)).thenReturn(testCollisionHook);
+ Mockito.when(felixMock.getService(felixMock, chRef, false)).thenReturn(testCollisionHook);
// Mock the archive of the bundle being installed
Map<String, String> headerMap = new HashMap<String, String>();
@@ -129,7 +129,7 @@ public class CollisionHookTest extends TestCase
{
differentBundle, identicalBundle
});
- Mockito.when(felixMock.getService(felixMock, chRef)).thenReturn(testCollisionHook);
+ Mockito.when(felixMock.getService(felixMock, chRef, false)).thenReturn(testCollisionHook);
// Mock the archive of the bundle being installed
Map<String, String> headerMap = new HashMap<String, String>();
@@ -185,7 +185,7 @@ public class CollisionHookTest extends TestCase
{
differentBundle, identicalBundle
});
- Mockito.when(felixMock.getService(felixMock, chRef)).thenReturn(testCollisionHook);
+ Mockito.when(felixMock.getService(felixMock, chRef, false)).thenReturn(testCollisionHook);
// Mock the archive of the bundle being installed
Map<String, String> headerMap = new HashMap<String, String>();
diff --git a/src/test/java/org/apache/felix/framework/DTOFactoryTest.java b/src/test/java/org/apache/felix/framework/DTOFactoryTest.java
new file mode 100644
index 0000000..fc897bf
--- /dev/null
+++ b/src/test/java/org/apache/felix/framework/DTOFactoryTest.java
@@ -0,0 +1,272 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import org.apache.felix.framework.Felix;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.dto.ServiceReferenceDTO;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.namespace.BundleNamespace;
+import org.osgi.framework.namespace.HostNamespace;
+import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.startlevel.BundleStartLevel;
+import org.osgi.framework.startlevel.dto.BundleStartLevelDTO;
+import org.osgi.framework.wiring.dto.BundleRevisionDTO;
+import org.osgi.framework.wiring.dto.BundleWiringDTO;
+import org.osgi.resource.dto.CapabilityDTO;
+
+public class DTOFactoryTest
+{
+ private int counter;
+ private Framework framework;
+ private File testDir;
+
+ @Before
+ public void setUp() throws Exception
+ {
+ String path = "/" + getClass().getName().replace('.', '/') + ".class";
+ String url = getClass().getResource(path).getFile();
+ String baseDir = url.substring(0, url.length() - path.length());
+ String rndStr = Long.toString(System.nanoTime(), Character.MAX_RADIX);
+ rndStr = rndStr.substring(rndStr.length() - 6, rndStr.length() - 1);
+ testDir = new File(baseDir, getClass().getSimpleName() + "_" + rndStr);
+
+ File cacheDir = new File(testDir, "cache");
+ cacheDir.mkdirs();
+ String cache = cacheDir.getAbsolutePath();
+
+ Map<String, Object> params = new HashMap<String, Object>();
+ params.put("felix.cache.profiledir", cache);
+ params.put("felix.cache.dir", cache);
+ params.put(Constants.FRAMEWORK_STORAGE, cache);
+
+ framework = new Felix(params);
+ framework.init();
+ framework.start();
+ }
+
+ @After
+ public void tearDown() throws Exception
+ {
+ framework.stop();
+ }
+
+ @Test
+ public void testBundleStartLevelDTO() throws Exception
+ {
+ String mf = "Bundle-SymbolicName: tb1\n"
+ + "Bundle-Version: 1.0.0\n"
+ + "Bundle-ManifestVersion: 2\n";
+ File bf = createBundle(mf);
+ Bundle bundle = framework.getBundleContext().installBundle(bf.toURI().toURL().toExternalForm());
+
+ BundleStartLevel sl = bundle.adapt(BundleStartLevel.class);
+ sl.setStartLevel(7);
+
+ BundleStartLevelDTO dto = bundle.adapt(BundleStartLevelDTO.class);
+ assertEquals(bundle.getBundleId(), dto.bundle);
+ assertEquals(7, dto.startLevel);
+ }
+
+ @Test
+ public void testServiceReferenceDTOArray() throws Exception
+ {
+ ServiceRegistration<String> reg = framework.getBundleContext().registerService(String.class, "hi", null);
+ Long sid = (Long) reg.getReference().getProperty(Constants.SERVICE_ID);
+
+ ServiceReferenceDTO[] dtos = framework.adapt(ServiceReferenceDTO[].class);
+ assertTrue(dtos.length > 0);
+
+ boolean found = false;
+ for (ServiceReferenceDTO dto : dtos)
+ {
+ if (dto.id == sid)
+ {
+ found = true;
+ assertEquals(0L, dto.bundle);
+ assertEquals(sid, dto.properties.get(Constants.SERVICE_ID));
+ assertTrue(Arrays.equals(new String [] {String.class.getName()},
+ (String []) dto.properties.get(Constants.OBJECTCLASS)));
+ assertEquals(0L, dto.properties.get(Constants.SERVICE_BUNDLEID));
+ assertEquals(Constants.SCOPE_SINGLETON, dto.properties.get(Constants.SERVICE_SCOPE));
+ assertEquals(0, dto.usingBundles.length);
+ }
+ }
+ assertTrue(found);
+ }
+
+ @Test
+ public void testBundleRevisionDTO() throws Exception
+ {
+ String mf = "Bundle-SymbolicName: tb2\n"
+ + "Bundle-Version: 1.2.3\n"
+ + "Bundle-ManifestVersion: 2\n"
+ + "Import-Package: org.osgi.framework;version=\"[1.1,2)\"";
+ File bf = createBundle(mf);
+ Bundle bundle = framework.getBundleContext().installBundle(bf.toURI().toURL().toExternalForm());
+ bundle.start();
+ assertEquals("Precondition", Bundle.ACTIVE, bundle.getState());
+
+ BundleRevisionDTO dto = bundle.adapt(BundleRevisionDTO.class);
+ assertEquals(bundle.getBundleId(), dto.bundle);
+ assertTrue(dto.id != 0);
+ assertEquals("tb2", dto.symbolicName);
+ assertEquals("1.2.3", dto.version);
+ assertEquals(0, dto.type);
+
+ boolean foundBundle = false;
+ boolean foundHost = false;
+ boolean foundIdentity = false;
+ int resource = 0;
+ for (CapabilityDTO cap : dto.capabilities)
+ {
+ assertTrue(cap.id != 0);
+ if (resource == 0)
+ resource = cap.resource;
+ else
+ assertEquals(resource, cap.resource);
+
+ if (BundleNamespace.BUNDLE_NAMESPACE.equals(cap.namespace))
+ {
+ foundBundle = true;
+ assertEquals("tb2", cap.attributes.get(BundleNamespace.BUNDLE_NAMESPACE));
+ assertEquals("1.2.3", cap.attributes.get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE));
+ }
+ else if (HostNamespace.HOST_NAMESPACE.equals(cap.namespace))
+ {
+ foundHost = true;
+ assertEquals("tb2", cap.attributes.get(HostNamespace.HOST_NAMESPACE));
+ assertEquals("1.2.3", cap.attributes.get(HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE));
+ }
+ else if (IdentityNamespace.IDENTITY_NAMESPACE.equals(cap.namespace))
+ {
+ foundIdentity = true;
+ assertEquals("tb2", cap.attributes.get(IdentityNamespace.IDENTITY_NAMESPACE));
+ assertEquals("1.2.3", cap.attributes.get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE));
+ assertEquals(IdentityNamespace.TYPE_BUNDLE, cap.attributes.get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
+ }
+ }
+ assertTrue(foundBundle);
+ assertTrue(foundHost);
+ assertTrue(foundIdentity);
+ }
+
+ @Test
+ public void testBundleRevisionDTOArray() throws Exception {
+ String mf = "Bundle-SymbolicName: tb2\n"
+ + "Bundle-Version: 1.2.3\n"
+ + "Bundle-ManifestVersion: 2\n"
+ + "Import-Package: org.osgi.framework;version=\"[1.1,2)\"";
+ File bf = createBundle(mf);
+ Bundle bundle = framework.getBundleContext().installBundle(bf.toURI().toURL().toExternalForm());
+ bundle.start();
+ assertEquals("Precondition", Bundle.ACTIVE, bundle.getState());
+
+ BundleRevisionDTO[] dtos = bundle.adapt(BundleRevisionDTO[].class);
+ assertEquals(1, dtos.length);
+ BundleRevisionDTO dto = dtos[0];
+
+ assertEquals(bundle.getBundleId(), dto.bundle);
+ assertTrue(dto.id != 0);
+ assertEquals("tb2", dto.symbolicName);
+ assertEquals("1.2.3", dto.version);
+ assertEquals(0, dto.type);
+
+ boolean foundBundle = false;
+ boolean foundHost = false;
+ boolean foundIdentity = false;
+ int resource = 0;
+ for (CapabilityDTO cap : dto.capabilities)
+ {
+ assertTrue(cap.id != 0);
+ if (resource == 0)
+ resource = cap.resource;
+ else
+ assertEquals(resource, cap.resource);
+
+ if (BundleNamespace.BUNDLE_NAMESPACE.equals(cap.namespace))
+ {
+ foundBundle = true;
+ assertEquals("tb2", cap.attributes.get(BundleNamespace.BUNDLE_NAMESPACE));
+ assertEquals("1.2.3", cap.attributes.get(BundleNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE));
+ }
+ else if (HostNamespace.HOST_NAMESPACE.equals(cap.namespace))
+ {
+ foundHost = true;
+ assertEquals("tb2", cap.attributes.get(HostNamespace.HOST_NAMESPACE));
+ assertEquals("1.2.3", cap.attributes.get(HostNamespace.CAPABILITY_BUNDLE_VERSION_ATTRIBUTE));
+ }
+ else if (IdentityNamespace.IDENTITY_NAMESPACE.equals(cap.namespace))
+ {
+ foundIdentity = true;
+ assertEquals("tb2", cap.attributes.get(IdentityNamespace.IDENTITY_NAMESPACE));
+ assertEquals("1.2.3", cap.attributes.get(IdentityNamespace.CAPABILITY_VERSION_ATTRIBUTE));
+ assertEquals(IdentityNamespace.TYPE_BUNDLE, cap.attributes.get(IdentityNamespace.CAPABILITY_TYPE_ATTRIBUTE));
+ }
+ }
+ assertTrue(foundBundle);
+ assertTrue(foundHost);
+ assertTrue(foundIdentity);
+ }
+
+ @Test
+ public void testBundleWiringDTO() throws Exception {
+ String mf = "Bundle-SymbolicName: tb2\n"
+ + "Bundle-Version: 1.2.3\n"
+ + "Bundle-ManifestVersion: 2\n"
+ + "Import-Package: org.osgi.framework;version=\"[1.1,2)\"";
+ File bf = createBundle(mf);
+ Bundle bundle = framework.getBundleContext().installBundle(bf.toURI().toURL().toExternalForm());
+ bundle.start();
+ assertEquals("Precondition", Bundle.ACTIVE, bundle.getState());
+
+ BundleWiringDTO dto = bundle.adapt(BundleWiringDTO.class);
+ assertEquals(bundle.getBundleId(), dto.bundle);
+ }
+
+ private File createBundle(String manifest) throws IOException
+ {
+ File f = File.createTempFile("felix-bundle" + counter++, ".jar", testDir);
+
+ Manifest mf = new Manifest(new ByteArrayInputStream(manifest.getBytes("utf-8")));
+ mf.getMainAttributes().putValue("Manifest-Version", "1.0");
+ JarOutputStream os = new JarOutputStream(new FileOutputStream(f), mf);
+
+ os.close();
+ return f;
+ }
+}
diff --git a/src/test/java/org/apache/felix/framework/ExtensionManagerTest.java b/src/test/java/org/apache/felix/framework/ExtensionManagerTest.java
new file mode 100644
index 0000000..c59910f
--- /dev/null
+++ b/src/test/java/org/apache/felix/framework/ExtensionManagerTest.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.zip.ZipEntry;
+
+import org.apache.felix.framework.util.FelixConstants;
+import org.apache.felix.framework.util.manifestparser.NativeLibraryClause;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.framework.launch.Framework;
+import org.osgi.framework.namespace.NativeNamespace;
+import org.osgi.framework.wiring.BundleCapability;
+
+/**
+ *
+ * Test Classes for the ExtentionManager
+ *
+ */
+public class ExtensionManagerTest {
+ private int counter;
+ private File testDir;
+
+ @Before
+ public void setUp() throws Exception {
+ String path = "/" + getClass().getName().replace('.', '/') + ".class";
+ String url = getClass().getResource(path).getFile();
+ String baseDir = url.substring(0, url.length() - path.length());
+ String rndStr = Long.toString(System.nanoTime(), Character.MAX_RADIX);
+ rndStr = rndStr.substring(rndStr.length() - 6, rndStr.length() - 1);
+ testDir = new File(baseDir, getClass().getSimpleName() + "_" + rndStr);
+ }
+
+ /**
+ *
+ *
+ * Ensure Native Bundle Capabilities are properly formed based on
+ * Framework properties.
+ *
+ */
+ @Test
+ public void testBuildNativeCapabilities() {
+ Logger logger = new Logger();
+ Map<String, String> configMap = new HashMap<String, String>();
+ configMap.put(FelixConstants.FELIX_VERSION_PROPERTY, "1.0");
+ configMap.put(FelixConstants.FRAMEWORK_LANGUAGE, "en");
+ configMap.put(FelixConstants.FRAMEWORK_PROCESSOR, "x86_64");
+ configMap.put(FelixConstants.FRAMEWORK_OS_NAME, "windows8");
+ configMap.put(FelixConstants.FRAMEWORK_OS_VERSION, "6.3");
+ configMap.put(FelixConstants.NATIVE_OS_NAME_ALIAS_PREFIX + ".windows8", "windows 8,win32");
+ configMap.put(FelixConstants.NATIVE_PROC_NAME_ALIAS_PREFIX + ".x86-64", "amd64,em64t,x86_64");
+ NativeLibraryClause.initializeNativeAliases(configMap);
+ ExtensionManager extensionManager = new ExtensionManager(logger,
+ configMap, null);
+ BundleCapability nativeBundleCapability = extensionManager
+ .buildNativeCapabilites();
+ assertEquals(
+ "Native Language should be same as framework Language",
+ "en",
+ nativeBundleCapability.getAttributes().get(
+ NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE));
+ assertTrue(
+ "Native Processor should be same as framework Processor",
+ Arrays.asList("x86-64", "amd64", "em64t", "x86_64").containsAll((List)
+ nativeBundleCapability.getAttributes().get(
+ NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE)));
+ assertTrue(
+ "Native OS Name should be the same as the framework os name",
+ Arrays.asList("windows8", "windows 8", "win32").containsAll((List)
+ nativeBundleCapability.getAttributes().get(
+ NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE)));
+ assertEquals(
+ "Native OS Version should be the same as the framework OS Version",
+ new Version("6.3"),
+ nativeBundleCapability.getAttributes().get(
+ NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE));
+ }
+
+ @Test
+ public void testExtensionBundleActivator() throws Exception {
+ File cacheDir = new File(testDir, "cache");
+ cacheDir.mkdirs();
+ String cache = cacheDir.getAbsolutePath();
+
+ Map<String, Object> params = new HashMap<String, Object>();
+ params.put("felix.cache.profiledir", cache);
+ params.put("felix.cache.dir", cache);
+ params.put(Constants.FRAMEWORK_STORAGE, cache);
+
+ Framework framework = new Felix(params);
+ framework.init();
+ framework.start();
+
+ try {
+ File ebf = createExtensionBundle();
+
+ assertEquals("Precondition", 0, activatorCalls.length());
+ framework.getBundleContext().installBundle(
+ ebf.toURI().toURL().toExternalForm());
+
+ assertEquals("start", activatorCalls.toString());
+ } finally {
+ framework.stop();
+ }
+
+ framework.waitForStop(10000);
+ assertEquals("startstop", activatorCalls.toString());
+ }
+
+ private File createExtensionBundle() throws IOException {
+ File f = File.createTempFile("felix-bundle" + counter++, ".jar", testDir);
+
+ Manifest mf = new Manifest();
+ mf.getMainAttributes().putValue("Manifest-Version", "1.0");
+ mf.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, "extension-bundle");
+ mf.getMainAttributes().putValue(Constants.BUNDLE_VERSION, "3.2.1");
+ mf.getMainAttributes().putValue(Constants.FRAGMENT_HOST, "system.bundle;extension:=framework");
+ mf.getMainAttributes().putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
+ mf.getMainAttributes().putValue(Constants.EXTENSION_BUNDLE_ACTIVATOR, TestActivator.class.getName());
+ JarOutputStream os = new JarOutputStream(new FileOutputStream(f), mf);
+
+ String path = TestActivator.class.getName().replace('.', '/') + ".class";
+ os.putNextEntry(new ZipEntry(path));
+
+ InputStream is = TestActivator.class.getClassLoader().getResourceAsStream(path);
+ pumpStreams(is, os);
+
+ is.close();
+ os.close();
+ return f;
+ }
+
+ static void pumpStreams(InputStream is, OutputStream os) throws IOException {
+ byte[] bytes = new byte[16384];
+
+ int length = 0;
+ int offset = 0;
+
+ while ((length = is.read(bytes, offset, bytes.length - offset)) != -1) {
+ offset += length;
+
+ if (offset == bytes.length) {
+ os.write(bytes, 0, bytes.length);
+ offset = 0;
+ }
+ }
+ if (offset != 0) {
+ os.write(bytes, 0, offset);
+ }
+ }
+
+ private static StringBuilder activatorCalls = new StringBuilder();
+ public static class TestActivator implements BundleActivator {
+ public void start(BundleContext context) throws Exception {
+ activatorCalls.append("start");
+ }
+
+ public void stop(BundleContext context) throws Exception {
+ activatorCalls.append("stop");
+ }
+ }
+}
diff --git a/src/test/java/org/apache/felix/framework/FrameworkVersionTest.java b/src/test/java/org/apache/felix/framework/FrameworkVersionTest.java
new file mode 100644
index 0000000..c230922
--- /dev/null
+++ b/src/test/java/org/apache/felix/framework/FrameworkVersionTest.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework;
+
+import java.lang.reflect.Method;
+
+import junit.framework.TestCase;
+
+import org.osgi.framework.Version;
+
+public class FrameworkVersionTest extends TestCase
+{
+ public void testFrameworkVersion() throws Exception
+ {
+ testFrameworkVersion("1.0.0", "1");
+ testFrameworkVersion("2.3.0", "2.3");
+ testFrameworkVersion("1.0.0", "1.0.0");
+ testFrameworkVersion("5.0.0.SNAPSHOT", "5-SNAPSHOT");
+ testFrameworkVersion("1.0.0.SNAPSHOT", "1.0-SNAPSHOT");
+ testFrameworkVersion("1.2.3.SNAPSHOT", "1.2.3-SNAPSHOT");
+ testFrameworkVersion("1.2.3.foo-123", "1.2.3.foo-123");
+ testFrameworkVersion("1.2.3.foo-123-hello", "1.2.3.foo-123-hello");
+ }
+
+ private void testFrameworkVersion(String out, String in) throws Exception
+ {
+ Method method = Felix.class.getDeclaredMethod("cleanMavenVersion", new Class [] {StringBuffer.class});
+ method.setAccessible(true);
+
+ StringBuffer sb = new StringBuffer(in);
+ assertEquals(new Version(out), new Version((String) method.invoke(null, sb)));
+ }
+}
diff --git a/src/test/java/org/apache/felix/framework/PackageAdminImplTest.java b/src/test/java/org/apache/felix/framework/PackageAdminImplTest.java
new file mode 100644
index 0000000..bc295ba
--- /dev/null
+++ b/src/test/java/org/apache/felix/framework/PackageAdminImplTest.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import junit.framework.TestCase;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.service.packageadmin.ExportedPackage;
+
+public class PackageAdminImplTest extends TestCase
+{
+ private File tempDir;
+ private Felix felix;
+ private File cacheDir;
+
+ @Override
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ tempDir = File.createTempFile("felix-temp", ".dir");
+ assertTrue("precondition", tempDir.delete());
+ assertTrue("precondition", tempDir.mkdirs());
+
+ cacheDir = new File(tempDir, "felix-cache");
+ assertTrue("precondition", cacheDir.mkdir());
+
+ String cache = cacheDir.getPath();
+
+ Map<String,String> params = new HashMap<String, String>();
+ params.put("felix.cache.profiledir", cache);
+ params.put("felix.cache.dir", cache);
+ params.put(Constants.FRAMEWORK_STORAGE, cache);
+
+ felix = new Felix(params);
+ felix.init();
+ felix.start();
+ }
+
+ @Override
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+
+ felix.stop(); // Note that this method is async
+ felix = null;
+
+ deleteDir(tempDir);
+ tempDir = null;
+ cacheDir = null;
+ }
+
+ public void testExportedPackages() throws Exception
+ {
+ String bmf = "Bundle-SymbolicName: pkg.bundle\n"
+ + "Bundle-Version: 1\n"
+ + "Bundle-ManifestVersion: 2\n"
+ + "Export-Package: org.foo.bundle\n";
+ File bundleFile = createBundle(bmf);
+
+ String fmf = "Bundle-SymbolicName: pkg.frag\n"
+ + "Bundle-Version: 1\n"
+ + "Fragment-Host: pkg.bundle\n"
+ + "Bundle-ManifestVersion: 2\n"
+ + "Export-Package: org.foo.fragment;version=\"2.0.0\"\n";
+ File fragFile = createBundle(fmf);
+
+ Bundle b = felix.getBundleContext().installBundle(bundleFile.toURI().toASCIIString());
+ Bundle f = felix.getBundleContext().installBundle(fragFile.toURI().toASCIIString());
+ b.start();
+
+ try
+ {
+ PackageAdminImpl pa = new PackageAdminImpl(felix);
+ assertEquals(b, pa.getExportedPackage("org.foo.bundle").getExportingBundle());
+ assertEquals(b, pa.getExportedPackage("org.foo.fragment").getExportingBundle());
+
+ Set<String> expected = new HashSet<String>();
+ expected.addAll(Arrays.asList("org.foo.bundle", "org.foo.fragment"));
+
+ Set<String> actual = new HashSet<String>();
+ for (ExportedPackage ep : pa.getExportedPackages(b))
+ {
+ actual.add(ep.getName());
+ assertEquals(b, ep.getExportingBundle());
+ }
+ assertEquals(expected, actual);
+
+ ExportedPackage[] bundlePkgs = pa.getExportedPackages("org.foo.bundle");
+ assertEquals(1, bundlePkgs.length);
+ assertEquals(b, bundlePkgs[0].getExportingBundle());
+ assertEquals(new Version("0"), bundlePkgs[0].getVersion());
+
+ ExportedPackage[] fragPkgs = pa.getExportedPackages("org.foo.fragment");
+ assertEquals(1, fragPkgs.length);
+ assertEquals("The fragment package should be exposed through the bundle",
+ b, fragPkgs[0].getExportingBundle());
+ assertEquals(new Version("2"), fragPkgs[0].getVersion());
+ }
+ finally
+ {
+ b.stop();
+ b.uninstall();
+ f.uninstall();
+ }
+ }
+
+ private File createBundle(String manifest) throws IOException
+ {
+ File f = File.createTempFile("felix-bundle", ".jar", tempDir);
+
+ Manifest mf = new Manifest(new ByteArrayInputStream(manifest.getBytes("UTF-8")));
+ mf.getMainAttributes().putValue("Manifest-Version", "1.0");
+ JarOutputStream os = new JarOutputStream(new FileOutputStream(f), mf);
+ os.close();
+ return f;
+ }
+
+ private static void deleteDir(File root) throws IOException
+ {
+ if (root.isDirectory())
+ {
+ File[] files = root.listFiles();
+ if (files != null)
+ {
+ for (File file : files)
+ {
+ deleteDir(file);
+ }
+ }
+ }
+ root.delete();
+ }
+}
diff --git a/src/test/java/org/apache/felix/framework/RequirementsCapabilitiesTest.java b/src/test/java/org/apache/felix/framework/RequirementsCapabilitiesTest.java
index 8cc34e6..ecb3941 100644
--- a/src/test/java/org/apache/felix/framework/RequirementsCapabilitiesTest.java
+++ b/src/test/java/org/apache/felix/framework/RequirementsCapabilitiesTest.java
@@ -192,6 +192,30 @@ public class RequirementsCapabilitiesTest extends TestCase
assertCapsEquals(expectedFWCap, bwpCaps2.get(0));
}
+ public void testIdentityCapabilityFrameworkExtension() throws Exception
+ {
+ String femf = "Bundle-SymbolicName: fram.ext\n"
+ + "Bundle-Version: 1.2.3.test\n"
+ + "Fragment-Host: system.bundle; extension:=framework\n"
+ + "Bundle-ManifestVersion: 2\n"
+ + "Export-Package: org.foo.bar;version=\"2.0.0\"\n";
+ File feFile = createBundle(femf);
+
+ Bundle fe = felix.getBundleContext().installBundle(feFile.toURI().toASCIIString());
+
+ BundleRevision fbr = fe.adapt(BundleRevision.class);
+
+ List<Capability> feCaps = fbr.getCapabilities("osgi.identity");
+ assertEquals(1, feCaps.size());
+ Map<String, Object> expectedFEAttrs = new HashMap<String, Object>();
+ expectedFEAttrs.put("osgi.identity", "fram.ext");
+ expectedFEAttrs.put("type", "osgi.fragment");
+ expectedFEAttrs.put("version", Version.parseVersion("1.2.3.test"));
+ Capability expectedFICap = new TestCapability("osgi.identity",
+ expectedFEAttrs, Collections.<String, String>emptyMap());
+ assertCapsEquals(expectedFICap, feCaps.get(0));
+ }
+
private File createBundle(String manifest) throws IOException
{
File f = File.createTempFile("felix-bundle", ".jar", tempDir);
diff --git a/src/test/java/org/apache/felix/framework/StartBundleTest.java b/src/test/java/org/apache/felix/framework/StartBundleTest.java
new file mode 100644
index 0000000..1e201b7
--- /dev/null
+++ b/src/test/java/org/apache/felix/framework/StartBundleTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework;
+
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+import org.apache.felix.framework.util.FelixConstants;
+import org.mockito.Mockito;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.wiring.BundleRevision;
+
+public class StartBundleTest extends TestCase
+{
+ public void testTransientExeption() throws Exception
+ {
+ HashMap<String, String> config = new HashMap<String, String>();
+ config.put(FelixConstants.BUNDLE_STARTLEVEL_PROP, "1");
+ final Felix f = new Felix(config);
+
+ BundleImpl b = Mockito.mock(BundleImpl.class);
+ Mockito.when(b.isLockable()).thenReturn(true);
+ Mockito.when(b.getState()).thenReturn(Bundle.INSTALLED);
+ Mockito.when(b.getStartLevel(1)).thenReturn(3);
+
+ BundleRevisionImpl br = new BundleRevisionImpl(b, "test");
+ Mockito.when(b.adapt(BundleRevision.class)).thenReturn(br);
+
+ try
+ {
+ f.startBundle(b, Bundle.START_TRANSIENT);
+ fail("Should have thrown a Bundle Exception");
+ }
+ catch (BundleException e)
+ {
+ assertEquals(BundleException.START_TRANSIENT_ERROR, e.getType());
+ }
+ }
+}
diff --git a/src/test/java/org/apache/felix/framework/StartStopBundleTest.java b/src/test/java/org/apache/felix/framework/StartStopBundleTest.java
index 315606c..4607b3f 100644
--- a/src/test/java/org/apache/felix/framework/StartStopBundleTest.java
+++ b/src/test/java/org/apache/felix/framework/StartStopBundleTest.java
@@ -119,6 +119,7 @@ public class StartStopBundleTest extends TestCase
assertTrue((t1 - t0) > DELAY / 2);
} finally {
f.stop();
+ Thread.sleep(DELAY);
deleteDir(cacheDir);
}
}
diff --git a/src/test/java/org/apache/felix/framework/util/manifestparser/ManifestParserTest.java b/src/test/java/org/apache/felix/framework/util/manifestparser/ManifestParserTest.java
index 1373f8c..6fee6e6 100644
--- a/src/test/java/org/apache/felix/framework/util/manifestparser/ManifestParserTest.java
+++ b/src/test/java/org/apache/felix/framework/util/manifestparser/ManifestParserTest.java
@@ -18,17 +18,27 @@
*/
package org.apache.felix.framework.util.manifestparser;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
+import static org.mockito.Mockito.*;
import junit.framework.TestCase;
+import org.apache.felix.framework.util.FelixConstants;
import org.osgi.framework.BundleException;
import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.Version;
import org.osgi.framework.namespace.IdentityNamespace;
+import org.osgi.framework.namespace.NativeNamespace;
import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleRequirement;
+import org.osgi.framework.wiring.BundleRevision;
public class ManifestParserTest extends TestCase
{
@@ -73,6 +83,65 @@ public class ManifestParserTest extends TestCase
assertEquals(1, ic.getDirectives().size());
assertEquals("true", ic.getDirectives().get(IdentityNamespace.CAPABILITY_SINGLETON_DIRECTIVE));
}
+
+ @SuppressWarnings("unchecked")
+ public void testNativeCapability() throws BundleException {
+ Map<String, String> headers = new HashMap<String, String>();
+ headers.put(Constants.BUNDLE_MANIFESTVERSION, "2");
+ headers.put(Constants.BUNDLE_SYMBOLICNAME, FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
+ headers.put(Constants.PROVIDE_CAPABILITY, " osgi.native;" +
+ "osgi.native.osname:List<String>=\"Windows7,Windows 7,Win7,Win32\";"+
+ "osgi.native.osversion:Version=\"7.0\";"+
+ "osgi.native.processor:List<String>=\"x86-64,amd64,em64t,x86_64\";"+
+ "osgi.native.language=\"en\"");
+ BundleRevision mockBundleRevision = mock(BundleRevision.class);
+ when(mockBundleRevision.getSymbolicName()).thenReturn(FelixConstants.SYSTEM_BUNDLE_SYMBOLICNAME);
+
+ ManifestParser mp = new ManifestParser(null, null, mockBundleRevision, headers);
+
+ BundleCapability ic = findCapability(mp.getCapabilities(), NativeNamespace.NATIVE_NAMESPACE);
+
+ assertEquals("en", ic.getAttributes().get(NativeNamespace.CAPABILITY_LANGUAGE_ATTRIBUTE));
+ List<String> osList = (List<String>) ic.getAttributes().get(NativeNamespace.CAPABILITY_OSNAME_ATTRIBUTE);
+ assertEquals(4, osList.size());
+ assertEquals(new Version("7.0"), ic.getAttributes().get(NativeNamespace.CAPABILITY_OSVERSION_ATTRIBUTE));
+ List<String> nativeProcesserList = (List<String>) ic.getAttributes().get(NativeNamespace.CAPABILITY_PROCESSOR_ATTRIBUTE);
+ assertEquals(4, nativeProcesserList.size());
+
+ }
+
+ public void testConvertNativeCode() throws InvalidSyntaxException
+ {
+ List<NativeLibraryClause> nativeLibraryClauses = new ArrayList<NativeLibraryClause>();
+ String[] libraryFiles = {"lib/http.dll", "lib/zlib.dll"};
+ String[] osNames = {"Windows95", "Windows98", "WindowsNT"};
+ String[] processors = {"x86"};
+ String[] osVersions = null;
+ String[] languages = {"en", "se"};
+ String selectionFilter = "(com.acme.windowing=win32)";
+ NativeLibraryClause clause = new NativeLibraryClause(libraryFiles, osNames, processors, osVersions, languages, selectionFilter);
+ BundleRevision owner = mock(BundleRevision.class);
+ nativeLibraryClauses.add(clause);
+
+ List<BundleRequirement> nativeBundleReq = ManifestParser.convertNativeCode(owner, nativeLibraryClauses, false);
+
+ BundleRequirement ir = findRequirement(nativeBundleReq, NativeNamespace.NATIVE_NAMESPACE);
+
+ String filterStr = (String)ir.getDirectives().get(NativeNamespace.REQUIREMENT_FILTER_DIRECTIVE);
+
+ Filter actualFilter = FrameworkUtil.createFilter(filterStr);
+
+ Filter expectedFilter = FrameworkUtil.createFilter("(&(|" +
+ "(osgi.native.osname~=windows95)(osgi.native.osname~=windows98)(osgi.native.osname~=windowsnt)" +
+ ")" +
+ "(osgi.native.processor~=x86)" +
+ "(|(osgi.native.language~=en)" +
+ "(osgi.native.language~=se)" +
+ ")"+
+ "(com.acme.windowing=win32))");
+ assertEquals("Filter Should contain native requirements", expectedFilter, actualFilter);
+
+ }
private BundleCapability findCapability(Collection<BundleCapability> capabilities, String namespace)
{
@@ -85,4 +154,16 @@ public class ManifestParserTest extends TestCase
}
return null;
}
+
+ private BundleRequirement findRequirement(Collection<BundleRequirement> requirements, String namespace)
+ {
+ for(BundleRequirement requirement: requirements)
+ {
+ if(namespace.equals(requirement.getNamespace()))
+ {
+ return requirement;
+ }
+ }
+ return null;
+ }
}
diff --git a/src/test/java/org/apache/felix/framework/util/manifestparser/NativeLibraryClauseTest.java b/src/test/java/org/apache/felix/framework/util/manifestparser/NativeLibraryClauseTest.java
new file mode 100644
index 0000000..cb24c56
--- /dev/null
+++ b/src/test/java/org/apache/felix/framework/util/manifestparser/NativeLibraryClauseTest.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.framework.util.manifestparser;
+
+import junit.framework.TestCase;
+
+public class NativeLibraryClauseTest extends TestCase {
+ public void testNormalizeOSName() {
+ assertEquals("win32", NativeLibraryClause.normalizeOSName("win 32"));
+ assertEquals("win32", NativeLibraryClause.normalizeOSName("Win*"));
+ assertEquals("windows95", NativeLibraryClause.normalizeOSName("Windows 95"));
+ assertEquals("windows98", NativeLibraryClause.normalizeOSName("Windows 98"));
+ assertEquals("windowsnt", NativeLibraryClause.normalizeOSName("WinNT"));
+ assertEquals("windows2000", NativeLibraryClause.normalizeOSName("Win2000"));
+ assertEquals("windows2003", NativeLibraryClause.normalizeOSName("Win2003"));
+ assertEquals("windowsserver2008", NativeLibraryClause.normalizeOSName("Windows Server 2008"));
+ assertEquals("windowsserver2012", NativeLibraryClause.normalizeOSName("Windows Server 2012"));
+ assertEquals("windowsxp", NativeLibraryClause.normalizeOSName("WinXP"));
+ assertEquals("windowsce", NativeLibraryClause.normalizeOSName("WinCE"));
+ assertEquals("windowsvista", NativeLibraryClause.normalizeOSName("WinVista"));
+ assertEquals("windows7", NativeLibraryClause.normalizeOSName("Windows 7"));
+ assertEquals("windows8", NativeLibraryClause.normalizeOSName("Win8"));
+ assertEquals("linux", NativeLibraryClause.normalizeOSName("Linux1.2.3"));
+ assertEquals("aix", NativeLibraryClause.normalizeOSName("AIX-4.5.6"));
+ assertEquals("digitalunix", NativeLibraryClause.normalizeOSName("digitalunix_blah"));
+ assertEquals("hpux", NativeLibraryClause.normalizeOSName("HPUX-999"));
+ assertEquals("irix", NativeLibraryClause.normalizeOSName("Irixxxx"));
+ assertEquals("macosx", NativeLibraryClause.normalizeOSName("mac OS X"));
+ assertEquals("netware", NativeLibraryClause.normalizeOSName("Netware"));
+ assertEquals("openbsd", NativeLibraryClause.normalizeOSName("OpenBSD-0000"));
+ assertEquals("netbsd", NativeLibraryClause.normalizeOSName("netbsd "));
+ assertEquals("os2", NativeLibraryClause.normalizeOSName("os/2"));
+ assertEquals("qnx", NativeLibraryClause.normalizeOSName("procnto"));
+ assertEquals("solaris", NativeLibraryClause.normalizeOSName("Solaris 9"));
+ assertEquals("sunos", NativeLibraryClause.normalizeOSName("SunOS8"));
+ assertEquals("vxworks", NativeLibraryClause.normalizeOSName("VxWorks"));
+
+ // Try all the already normalized names
+ assertEquals("aix", NativeLibraryClause.normalizeOSName("aix"));
+ assertEquals("digitalunix", NativeLibraryClause.normalizeOSName("digitalunix"));
+ assertEquals("hpux", NativeLibraryClause.normalizeOSName("hpux"));
+ assertEquals("irix", NativeLibraryClause.normalizeOSName("irix"));
+ assertEquals("linux", NativeLibraryClause.normalizeOSName("linux"));
+ assertEquals("macos", NativeLibraryClause.normalizeOSName("macos"));
+ assertEquals("netbsd", NativeLibraryClause.normalizeOSName("netbsd"));
+ assertEquals("netware", NativeLibraryClause.normalizeOSName("netware"));
+ assertEquals("openbsd", NativeLibraryClause.normalizeOSName("openbsd"));
+ assertEquals("os2", NativeLibraryClause.normalizeOSName("os2"));
+ assertEquals("qnx", NativeLibraryClause.normalizeOSName("qnx"));
+ assertEquals("solaris", NativeLibraryClause.normalizeOSName("solaris"));
+ assertEquals("sunos", NativeLibraryClause.normalizeOSName("sunos"));
+ assertEquals("vxworks", NativeLibraryClause.normalizeOSName("vxworks"));
+ assertEquals("windows2000", NativeLibraryClause.normalizeOSName("windows2000"));
+ assertEquals("windows2003", NativeLibraryClause.normalizeOSName("windows2003"));
+ assertEquals("windows7", NativeLibraryClause.normalizeOSName("windows7"));
+ assertEquals("windows8", NativeLibraryClause.normalizeOSName("windows8"));
+ assertEquals("windows9", NativeLibraryClause.normalizeOSName("windows9"));
+ assertEquals("windows95", NativeLibraryClause.normalizeOSName("windows95"));
+ assertEquals("windows98", NativeLibraryClause.normalizeOSName("windows98"));
+ assertEquals("windowsce", NativeLibraryClause.normalizeOSName("windowsce"));
+ assertEquals("windowsnt", NativeLibraryClause.normalizeOSName("windowsnt"));
+ assertEquals("windowsserver2008", NativeLibraryClause.normalizeOSName("windowsserver2008"));
+ assertEquals("windowsserver2012", NativeLibraryClause.normalizeOSName("windowsserver2012"));
+ assertEquals("windowsvista", NativeLibraryClause.normalizeOSName("windowsvista"));
+ assertEquals("windowsxp", NativeLibraryClause.normalizeOSName("windowsxp"));
+ assertEquals("win32", NativeLibraryClause.normalizeOSName("win32"));
+ }
+
+ public void testgetOsNameWithAliases() {
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("win 32").contains("win32"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Win*").contains("win32"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Windows 95").contains("windows95"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Windows 98").contains("windows98"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("WinNT").contains("windowsnt"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Win2000").contains("windows2000"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Win2003").contains("windows2003"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Windows Server 2008").contains("windowsserver2008"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Windows Server 2012").contains("windowsserver2012"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("WinXP").contains("windowsxp"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("WinCE").contains("windowsce"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("WinVista").contains("windowsvista"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Windows 7").contains("windows7"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Windows7").contains("windows7"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Win8").contains("windows8"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Linux1.2.3").contains("linux"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("AIX-4.5.6").contains("aix"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("digitalunix_blah").contains("digitalunix"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("HPUX-999").contains("hpux"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Irixxxx").contains("irix"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("mac OS X").contains("mac os x"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Netware").contains("netware"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("OpenBSD-0000").contains("openbsd"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("netbsd ").contains("netbsd"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("os/2").contains("os2"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("procnto").contains("qnx"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("Solaris 9").contains("solaris"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("SunOS8").contains("sunos"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("VxWorks").contains("vxworks"));
+
+ // Try all the already normalized names
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("aix").contains("aix"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("digitalunix").contains("digitalunix"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("hpux").contains("hpux"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("irix").contains("irix"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("linux").contains("linux"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("mac os").contains("mac os"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("netbsd").contains("netbsd"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("netware").contains("netware"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("openbsd").contains("openbsd"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("os2").contains("os2"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("qnx").contains("qnx"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("solaris").contains("solaris"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("sunos").contains("sunos"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("vxworks").contains("vxworks"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windows2000").contains("windows2000"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windows2003").contains("windows2003"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windows7").contains("windows7"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windows8").contains("windows8"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windows9").contains("windows9"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windows95").contains("windows95"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windows98").contains("windows98"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windowsce").contains("windowsce"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windowsnt").contains("windowsnt"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windowsserver2008").contains("windowsserver2008"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windowsserver2012").contains("windowsserver2012"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windowsvista").contains("windowsvista"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("windowsxp").contains("windowsxp"));
+ assertTrue(NativeLibraryClause.getOsNameWithAliases("win32").contains("win32"));
+ }
+}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/felix-framework.git
More information about the pkg-java-commits
mailing list