[maven-release-plugin] copy for tag org.apache.aries.blueprint.noosgi-1.0.0
git-svn-id: https://svn.apache.org/repos/asf/aries/tags/org.apache.aries.blueprint.noosgi-1.0.0@1463436 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 6b0b127..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,203 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- 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.
-
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index 424644d..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,8 +0,0 @@
-
-Apache Aries
-Copyright 2009-2011 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
-
-
diff --git a/pom.xml b/pom.xml
index 33ac633..a6364ca 100644
--- a/pom.xml
+++ b/pom.xml
@@ -26,35 +26,25 @@
</parent>
<groupId>org.apache.aries.blueprint</groupId>
- <artifactId>org.apache.aries.blueprint.cm</artifactId>
- <packaging>bundle</packaging>
- <version>1.0.2-SNAPSHOT</version>
- <name>Apache Aries Blueprint CM</name>
+ <artifactId>org.apache.aries.blueprint.noosgi</artifactId>
+ <packaging>jar</packaging>
+ <version>1.0.0</version>
+ <name>Apache Aries Blueprint no-OSGI</name>
<description>
- This bundle contains the ConfigAdmin namespace for blueprint.
+ This jar contains everything needed to run Blueprint outside OSGi.
</description>
<scm>
- <connection>scm:svn:http://svn.apache.org/repos/asf/aries/trunk/blueprint/blueprint-cm</connection>
- <developerConnection>scm:svn:https://svn.apache.org/repos/asf/aries/trunk/blueprint/blueprint-cm</developerConnection>
- <url>http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-cm</url>
+ <connection>scm:svn:http://svn.apache.org/repos/asf/aries/tags/org.apache.aries.blueprint.noosgi-1.0.0</connection>
+ <developerConnection>scm:svn:https://svn.apache.org/repos/asf/aries/tags/org.apache.aries.blueprint.noosgi-1.0.0</developerConnection>
+ <url>http://svn.apache.org/viewvc/aries/tags/org.apache.aries.blueprint.noosgi-1.0.0</url>
</scm>
<properties>
- <!-- Export package versions are maintained in packageinfo files -->
- <aries.osgi.export.pkg />
- <aries.osgi.import.pkg>
- org.apache.aries.blueprint;provide:=true;version="[1.0,1.2)",
- org.apache.aries.blueprint.ext;provide:=true;version="[1.0,1.2)",
- *
- </aries.osgi.import.pkg>
- <aries.osgi.private.pkg>
- org.apache.aries.blueprint.compendium.cm
- </aries.osgi.private.pkg>
-
<blueprint.api.version>1.0.0</blueprint.api.version>
<blueprint.core.version>1.0.0</blueprint.core.version>
<blueprint.parser.version>1.0.0</blueprint.parser.version>
+ <proxy.impl.version>1.0.0</proxy.impl.version>
</properties>
<profiles>
@@ -66,6 +56,12 @@
<blueprint.parser.version>1.0.1-SNAPSHOT</blueprint.parser.version>
</properties>
</profile>
+ <profile>
+ <id>apache-release</id>
+ <properties>
+ <createSourcesJar>true</createSourcesJar>
+ </properties>
+ </profile>
</profiles>
<dependencies>
@@ -84,36 +80,30 @@
<groupId>org.apache.aries.blueprint</groupId>
<artifactId>org.apache.aries.blueprint.core</artifactId>
<version>${blueprint.core.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.aries.quiesce</groupId>
+ <artifactId>org.apache.aries.quiesce.api</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.apache.aries</groupId>
+ <artifactId>org.apache.aries.util</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
+ <!--
<dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.core</artifactId>
- <scope>provided</scope>
+ <groupId>org.apache.aries.proxy</groupId>
+ <artifactId>org.apache.aries.proxy.impl</artifactId>
+ <version>${proxy.impl.version}</version>
</dependency>
- <dependency>
- <groupId>org.osgi</groupId>
- <artifactId>org.osgi.compendium</artifactId>
- <scope>provided</scope>
- <version>4.1.0</version>
- </dependency>
+ -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>com.googlecode.pojosr</groupId>
- <artifactId>de.kalpatec.pojosr.framework</artifactId>
- <version>0.1.6</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.ops4j.pax.swissbox</groupId>
- <artifactId>pax-swissbox-tinybundles</artifactId>
- <version>1.3.1</version>
- <scope>test</scope>
- </dependency>
- <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.7</version>
@@ -131,34 +121,66 @@
<version>1.5.11</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>org.apache.aries.proxy</groupId>
- <artifactId>org.apache.aries.proxy.impl</artifactId>
- <version>1.0.0</version>
- <scope>test</scope>
- </dependency>
- <dependency>
- <groupId>org.apache.felix</groupId>
- <artifactId>org.apache.felix.configadmin</artifactId>
- <version>1.2.8</version>
- <scope>test</scope>
- </dependency>
</dependencies>
<build>
<plugins>
<plugin>
- <groupId>org.apache.aries.versioning</groupId>
- <artifactId>org.apache.aries.versioning.plugin</artifactId>
- <version>0.1.0</version>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
- <id>default-verify</id>
- <phase>verify</phase>
+ <phase>package</phase>
<goals>
- <goal>version-check</goal>
+ <goal>shade</goal>
</goals>
<configuration>
- <oldArtifact>org.apache.aries.blueprint:org.apache.aries.blueprint.cm:1.0.1</oldArtifact>
+ <filters>
+ <filter>
+ <artifact>org.apache.aries.blueprint:org.apache.aries.blueprint.core</artifact>
+ <excludes>
+ <exclude>org/apache/aries/blueprint/container/AbstractServiceReferenceRecipe*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/BlueprintContainerImpl*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/BlueprintEventDispatcher*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/BlueprintExtender*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/BlueprintQuiesceParticipant*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/BlueprintThreadFactory*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/GenericType*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/NamespaceHandlerRegistry*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/ParserServiceImpl*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/QuiesceInterceptor*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/ReferenceListRecipe*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/ReferenceRecipe*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/SatisfiableRecipe*.class</exclude>
+ <exclude>org/apache/aries/blueprint/container/ServiceRecipe*.class</exclude>
+ <exclude>org/apache/aries/blueprint/ext/AbstractPropertyPlaceholder$LateBindingValueMetadata.class</exclude>
+ <exclude>org/apache/aries/blueprint/ext/AbstractPropertyPlaceholder.class</exclude>
+ <!--
+ <exclude>org/apache/aries/blueprint/mutable/MutableReference*.class</exclude>
+ <exclude>org/apache/aries/blueprint/mutable/MutableRegistrationListener.class</exclude>
+ <exclude>org/apache/aries/blueprint/mutable/MutableService*.class</exclude>
+ <exclude>org/apache/aries/blueprint/reflect/Reference*.class</exclude>
+ <exclude>org/apache/aries/blueprint/reflect/Service*.class</exclude>
+ -->
+ <exclude>org/apache/aries/blueprint/services/ExtendedBlueprintContainer.class</exclude>
+ <exclude>org/apache/aries/blueprint/namespace/**</exclude>
+ <!--
+ - Check if we can exclude proxy
+ <exclude>org/apache/aries/blueprint/proxy/**</exclude>
+ -->
+ <exclude>org/apache/aries/blueprint/utils/ServiceListener.class</exclude>
+ <exclude>org/apache/aries/blueprint/utils/threading/**</exclude>
+ </excludes>
+ </filter>
+ <filter>
+ <artifact>org.apache.aries.proxy:org.apache.aries.proxy.api</artifact>
+ <excludes>
+ <exclude>org/apache/aries/proxy/weavinghook/**</exclude>
+ </excludes>
+ </filter>
+ </filters>
+ <createSourcesJar>${createSourcesJar}</createSourcesJar>
+ <promoteTransitiveDependencies>true</promoteTransitiveDependencies>
+ <createDependencyReducedPom>true</createDependencyReducedPom>
</configuration>
</execution>
</executions>
diff --git a/src/main/appended-resources/META-INF/NOTICE.vm b/src/main/appended-resources/META-INF/NOTICE.vm
deleted file mode 100644
index 3e5ad36..0000000
--- a/src/main/appended-resources/META-INF/NOTICE.vm
+++ /dev/null
@@ -1,2 +0,0 @@
-This product includes software developed at
-the OSGi Alliance (http://www.osgi.org/).
\ No newline at end of file
diff --git a/src/main/java/org/apache/aries/blueprint/compendium/cm/BaseManagedServiceFactory.java b/src/main/java/org/apache/aries/blueprint/compendium/cm/BaseManagedServiceFactory.java
deleted file mode 100644
index 9393349..0000000
--- a/src/main/java/org/apache/aries/blueprint/compendium/cm/BaseManagedServiceFactory.java
+++ /dev/null
@@ -1,233 +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.aries.blueprint.compendium.cm;
-
-import java.util.Dictionary;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.apache.aries.blueprint.utils.JavaUtils;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedServiceFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class BaseManagedServiceFactory<T> implements ManagedServiceFactory {
-
- public static final long DEFAULT_TIMEOUT_BEFORE_INTERRUPT = 30000;
-
- public static final int CONFIGURATION_ADMIN_OBJECT_DELETED = 1;
-
- public static final int BUNDLE_STOPPING = 2;
-
- public static final int INTERNAL_ERROR = 4;
-
- protected final Logger LOGGER = LoggerFactory.getLogger(getClass());
-
- private final BundleContext context;
- private final String name;
- private final long timeoutBeforeInterrupt;
- private final AtomicBoolean destroyed;
- private final ExecutorService executor;
- private final Map<String, Pair<T, ServiceRegistration>> services;
- private final Map<ServiceRegistration, T> registrations;
-
- public BaseManagedServiceFactory(BundleContext context, String name) {
- this(context, name, DEFAULT_TIMEOUT_BEFORE_INTERRUPT);
- }
-
- public BaseManagedServiceFactory(BundleContext context, String name, long timeoutBeforeInterrupt) {
- this.context = context;
- this.name = name;
- this.timeoutBeforeInterrupt = timeoutBeforeInterrupt;
- this.destroyed = new AtomicBoolean(false);
- this.executor = Executors.newSingleThreadExecutor();
- this.services = new ConcurrentHashMap<String, Pair<T, ServiceRegistration>>();
- this.registrations = new ConcurrentHashMap<ServiceRegistration, T>();
- }
-
- public String getName() {
- return name;
- }
-
- public Map<ServiceRegistration, T> getServices() {
- return registrations;
- }
-
- public void updated(final String pid, final Dictionary properties) throws ConfigurationException {
- if (destroyed.get()) {
- return;
- }
- checkConfiguration(pid, properties);
- executor.submit(new Runnable() {
- public void run() {
- try {
- internalUpdate(pid, properties);
- } catch (Throwable t) {
- LOGGER.warn("Error destroying service for ManagedServiceFactory " + getName(), t);
- }
- }
- });
- }
-
- public void deleted(final String pid) {
- if (destroyed.get()) {
- return;
- }
- executor.submit(new Runnable() {
- public void run() {
- try {
- internalDelete(pid, CONFIGURATION_ADMIN_OBJECT_DELETED);
- } catch (Throwable throwable) {
- LOGGER.warn("Error destroying service for ManagedServiceFactory " + getName(), throwable);
- }
- }
- });
- }
-
- protected void checkConfiguration(String pid, Dictionary properties) throws ConfigurationException {
- // Do nothing
- }
-
- protected abstract T doCreate(Dictionary properties) throws Exception;
-
- protected abstract T doUpdate(T t, Dictionary properties) throws Exception;
-
- protected abstract void doDestroy(T t, Dictionary properties, int code) throws Exception;
-
- protected abstract String[] getExposedClasses(T t);
-
- private void internalUpdate(String pid, Dictionary properties) {
- Pair<T, ServiceRegistration> pair = services.get(pid);
- if (pair != null) {
- try {
- T t = doUpdate(pair.getFirst(), properties);
- pair.setFirst(t);
- pair.getSecond().setProperties(properties);
- } catch (Throwable throwable) {
- internalDelete(pid, INTERNAL_ERROR);
- LOGGER.warn("Error updating service for ManagedServiceFactory " + getName(), throwable);
- }
- } else {
- if (destroyed.get()) {
- return;
- }
- try {
- T t = doCreate(properties);
- try {
- if (destroyed.get()) {
- throw new IllegalStateException("ManagedServiceFactory has been destroyed");
- }
- ServiceRegistration registration = context.registerService(getExposedClasses(t), t, properties);
- services.put(pid, new Pair<T, ServiceRegistration>(t, registration));
- registrations.put(registration, t);
- postRegister(t, properties, registration);
- } catch (Throwable throwable1) {
- try {
- doDestroy(t, properties, INTERNAL_ERROR);
- } catch (Throwable throwable2) {
- // Ignore
- }
- throw throwable1;
- }
- } catch (Throwable throwable) {
- LOGGER.warn("Error creating service for ManagedServiceFactory " + getName(), throwable);
- }
- }
- }
-
- protected void postRegister(T t, Dictionary properties, ServiceRegistration registration) {
- // Place holder
- }
-
- protected void preUnregister(T t, Dictionary properties, ServiceRegistration registration) {
- // Place holder
- }
-
- private void internalDelete(String pid, int code) {
- Pair<T, ServiceRegistration> pair = services.remove(pid);
- if (pair != null) {
- registrations.remove(pair.getSecond());
- Dictionary properties = JavaUtils.getProperties(pair.getSecond().getReference());
- try {
- preUnregister(pair.getFirst(), properties, pair.getSecond());
- pair.getSecond().unregister();
- } catch (Throwable t) {
- LOGGER.info("Error unregistering service", t);
- }
- try {
- doDestroy(pair.getFirst(), properties, code);
- } catch (Throwable t) {
- LOGGER.info("Error destroying service", t);
- }
- }
- }
-
- public void destroy() {
- if (destroyed.compareAndSet(false, true)) {
- executor.shutdown();
- try {
- executor.awaitTermination(timeoutBeforeInterrupt, TimeUnit.MILLISECONDS);
- } catch (InterruptedException e) {
- throw new RuntimeException("Shutdown interrupted");
- }
- if (!executor.isTerminated()) {
- executor.shutdownNow();
- try {
- executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
- } catch (InterruptedException e) {
- throw new RuntimeException("Shutdown interrupted");
- }
- }
-
- while (!services.isEmpty()) {
- String pid = services.keySet().iterator().next();
- internalDelete(pid, BUNDLE_STOPPING);
- }
- }
- }
-
- static class Pair<U,V> {
- private U first;
- private V second;
- public Pair(U first, V second) {
- this.first = first;
- this.second = second;
- }
- public U getFirst() {
- return first;
- }
- public V getSecond() {
- return second;
- }
- public void setFirst(U first) {
- this.first = first;
- }
- public void setSecond(V second) {
- this.second = second;
- }
- }
-
-}
diff --git a/src/main/java/org/apache/aries/blueprint/compendium/cm/CmManagedProperties.java b/src/main/java/org/apache/aries/blueprint/compendium/cm/CmManagedProperties.java
deleted file mode 100644
index 1622689..0000000
--- a/src/main/java/org/apache/aries/blueprint/compendium/cm/CmManagedProperties.java
+++ /dev/null
@@ -1,283 +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.aries.blueprint.compendium.cm;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
-import org.apache.aries.blueprint.BeanProcessor;
-import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
-import org.apache.aries.blueprint.utils.ReflectionUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.osgi.service.blueprint.container.ReifiedType;
-import org.osgi.service.blueprint.reflect.BeanMetadata;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * TODO
- *
- * @version $Rev$, $Date$
- */
-public class CmManagedProperties implements ManagedObject, BeanProcessor {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(CmManagedProperties.class);
-
- private ExtendedBlueprintContainer blueprintContainer;
- private ConfigurationAdmin configAdmin;
- private ManagedObjectManager managedObjectManager;
- private String persistentId;
- private String updateStrategy;
- private String updateMethod;
- private String beanName;
-
- private final Object lock = new Object();
- private final Set<Object> beans = new HashSet<Object>();
- private Dictionary<String,Object> properties;
-
- public ExtendedBlueprintContainer getBlueprintContainer() {
- return blueprintContainer;
- }
-
- public void setBlueprintContainer(ExtendedBlueprintContainer blueprintContainer) {
- this.blueprintContainer = blueprintContainer;
- }
-
- public ConfigurationAdmin getConfigAdmin() {
- return configAdmin;
- }
-
- public void setConfigAdmin(ConfigurationAdmin configAdmin) {
- this.configAdmin = configAdmin;
- }
-
- public void setManagedObjectManager(ManagedObjectManager managedObjectManager) {
- this.managedObjectManager = managedObjectManager;
- }
-
- public ManagedObjectManager getManagedObjectManager() {
- return managedObjectManager;
- }
-
- public Bundle getBundle() {
- return blueprintContainer.getBundleContext().getBundle();
- }
-
- public String getPersistentId() {
- return persistentId;
- }
-
- public void setPersistentId(String persistentId) {
- this.persistentId = persistentId;
- }
-
- public String getUpdateStrategy() {
- return updateStrategy;
- }
-
- public void setUpdateStrategy(String updateStrategy) {
- this.updateStrategy = updateStrategy;
- }
-
- public String getUpdateMethod() {
- return updateMethod;
- }
-
- public void setUpdateMethod(String updateMethod) {
- this.updateMethod = updateMethod;
- }
-
- public String getBeanName() {
- return beanName;
- }
-
- public void setBeanName(String beanName) {
- this.beanName = beanName;
- }
-
- public void init() throws Exception {
- LOGGER.debug("Initializing CmManagedProperties for bean={} / pid={}", beanName, persistentId);
-
- Properties props = new Properties();
- props.put(Constants.SERVICE_PID, persistentId);
- Bundle bundle = blueprintContainer.getBundleContext().getBundle();
- props.put(Constants.BUNDLE_SYMBOLICNAME, bundle.getSymbolicName());
- props.put(Constants.BUNDLE_VERSION, bundle.getHeaders().get(Constants.BUNDLE_VERSION));
-
- synchronized (lock) {
- managedObjectManager.register(this, props);
- Configuration config = CmUtils.getConfiguration(configAdmin, persistentId);
- if (config != null) {
- properties = config.getProperties();
- }
- }
- }
-
- public void destroy() {
- managedObjectManager.unregister(this);
- }
-
- public void updated(final Dictionary props) {
- LOGGER.debug("Configuration updated for bean={} / pid={}", beanName, persistentId);
- synchronized (lock) {
- properties = props;
- for (Object bean : beans) {
- inject(bean, false);
- }
- }
- }
-
- public Object beforeInit(Object bean, String beanName, BeanCreator beanCreator, BeanMetadata beanData) {
- if (beanName != null && beanName.equals(this.beanName)) {
- LOGGER.debug("Adding bean for bean={} / pid={}", beanName, persistentId);
- synchronized (lock) {
- beans.add(bean);
- inject(bean, true);
- }
- }
- return bean;
- }
-
- public Object afterInit(Object bean, String beanName, BeanCreator beanCreator, BeanMetadata beanData) {
- return bean;
- }
-
- public void beforeDestroy(Object bean, String beanName) {
- if (beanName.equals(this.beanName)) {
- LOGGER.debug("Removing bean for bean={} / pid={}", beanName, persistentId);
- synchronized (lock) {
- beans.remove(bean);
- }
- }
- }
-
- public void afterDestroy(Object bean, String beanName) {
- }
-
- private void inject(Object bean, boolean initial) {
- LOGGER.debug("Injecting bean for bean={} / pid={}", beanName, persistentId);
- LOGGER.debug("Configuration: {}", properties);
- if (initial || "container-managed".equals(updateStrategy)) {
- if (properties != null) {
- for (Enumeration<String> e = properties.keys(); e.hasMoreElements();) {
- String key = e.nextElement();
- Object val = properties.get(key);
- String setterName = "set" + Character.toUpperCase(key.charAt(0));
- if (key.length() > 0) {
- setterName += key.substring(1);
- }
- Set<Method> validSetters = new LinkedHashSet<Method>();
- List<Method> methods = new ArrayList<Method>(Arrays.asList(bean.getClass().getMethods()));
- methods.addAll(Arrays.asList(bean.getClass().getDeclaredMethods()));
- for (Method method : methods) {
- if (method.getName().equals(setterName)) {
- if (method.getParameterTypes().length == 0) {
- LOGGER.debug("Setter takes no parameters: {}", method);
- continue;
- }
- if (method.getParameterTypes().length > 1) {
- LOGGER.debug("Setter takes more than one parameter: {}", method);
- continue;
- }
- if (method.getReturnType() != Void.TYPE) {
- LOGGER.debug("Setter returns a value: {}", method);
- continue;
- }
- if (Modifier.isAbstract(method.getModifiers())) {
- LOGGER.debug("Setter is abstract: {}", method);
- continue;
- }
- if (!Modifier.isPublic(method.getModifiers())) {
- LOGGER.debug("Setter is not public: {}", method);
- continue;
- }
- if (Modifier.isStatic(method.getModifiers())) {
- LOGGER.debug("Setter is static: {}", method);
- continue;
- }
- Class methodParameterType = method.getParameterTypes()[0];
- Object propertyValue;
- try {
- propertyValue = blueprintContainer.getConverter().convert(val, new ReifiedType(methodParameterType));
- } catch (Throwable t) {
- LOGGER.debug("Unable to convert value for setter: " + method, t);
- continue;
- }
- if (methodParameterType.isPrimitive() && propertyValue == null) {
- LOGGER.debug("Null can not be assigned to {}: {}", methodParameterType.getName(), method);
- continue;
- }
- if (validSetters.add(method)) {
- try {
- method.invoke(bean, propertyValue);
- } catch (Exception t) {
- LOGGER.debug("Setter can not be invoked: " + method, getRealCause(t));
- }
- }
- }
- }
- if (validSetters.isEmpty()) {
- LOGGER.debug("Unable to find a valid setter method for property {} and value {}", key, val);
- }
- }
- }
- } else if ("component-managed".equals(updateStrategy) && updateMethod != null) {
- List<Method> methods = ReflectionUtils.findCompatibleMethods(bean.getClass(), updateMethod, new Class[] { Map.class });
- Map map = null;
- if (properties != null) {
- map = new HashMap();
- for (Enumeration<String> e = properties.keys(); e.hasMoreElements();) {
- String key = e.nextElement();
- Object val = properties.get(key);
- map.put(key, val);
- }
- }
- for (Method method : methods) {
- try {
- method.invoke(bean, map);
- } catch (Throwable t) {
- LOGGER.warn("Unable to call method " + method + " on bean " + beanName, getRealCause(t));
- }
- }
- }
- }
-
- private static Throwable getRealCause(Throwable t) {
- if (t instanceof InvocationTargetException && t.getCause() != null) {
- return t.getCause();
- }
- return t;
- }
-
-}
diff --git a/src/main/java/org/apache/aries/blueprint/compendium/cm/CmManagedServiceFactory.java b/src/main/java/org/apache/aries/blueprint/compendium/cm/CmManagedServiceFactory.java
deleted file mode 100644
index 9600eca..0000000
--- a/src/main/java/org/apache/aries/blueprint/compendium/cm/CmManagedServiceFactory.java
+++ /dev/null
@@ -1,273 +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.aries.blueprint.compendium.cm;
-
-import java.lang.reflect.Method;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
-import org.apache.aries.blueprint.BeanProcessor;
-import org.apache.aries.blueprint.ServiceProcessor;
-import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
-import org.apache.aries.blueprint.utils.JavaUtils;
-import org.apache.aries.blueprint.utils.ReflectionUtils;
-import org.apache.aries.blueprint.utils.ServiceListener;
-import org.apache.aries.util.AriesFrameworkUtil;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.blueprint.reflect.ServiceMetadata;
-import org.osgi.service.cm.ManagedServiceFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * TODO: if we need to make those exported services tied to their references as for other <service/> elements
- * TODO: it becomes a problem as currently we would have to create a specific recipe or something like that
- *
- * @version $Rev$, $Date$
- */
-public class CmManagedServiceFactory extends BaseManagedServiceFactory<Object> {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(CmManagedServiceFactory.class);
-
- private ExtendedBlueprintContainer blueprintContainer;
- private String id;
- private String factoryPid;
- private List<String> interfaces;
- private int autoExport;
- private int ranking;
- private Map<Object,Object> serviceProperties;
- private String managedComponentName;
- private String componentDestroyMethod;
- private List<ServiceListener> listeners;
-
- private ServiceRegistration registration;
-
- public CmManagedServiceFactory(ExtendedBlueprintContainer blueprintContainer) {
- super(blueprintContainer.getBundleContext(), null);
- this.blueprintContainer = blueprintContainer;
- }
-
- public void init() throws Exception {
- LOGGER.debug("Initializing CmManagedServiceFactory for factoryPid={}", factoryPid);
- Properties props = new Properties();
- props.put(Constants.SERVICE_PID, factoryPid);
- Bundle bundle = blueprintContainer.getBundleContext().getBundle();
- props.put(Constants.BUNDLE_SYMBOLICNAME, bundle.getSymbolicName());
- props.put(Constants.BUNDLE_VERSION, bundle.getHeaders().get(Constants.BUNDLE_VERSION));
-
- registration = blueprintContainer.getBundleContext().registerService(ManagedServiceFactory.class.getName(), this, props);
- }
-
- public void destroy() {
- AriesFrameworkUtil.safeUnregisterService(registration);
- super.destroy();
- }
-
- public Map<ServiceRegistration, Object> getServiceMap() {
- return Collections.unmodifiableMap(getServices());
- }
-
- public void setListeners(List<ServiceListener> listeners) {
- this.listeners = listeners;
- }
-
- public void setId(String id) {
- this.id = id;
- }
-
- public void setFactoryPid(String factoryPid) {
- this.factoryPid = factoryPid;
- }
-
- public void setInterfaces(List<String> interfaces) {
- this.interfaces = interfaces;
- }
-
- public void setAutoExport(int autoExport) {
- this.autoExport = autoExport;
- }
-
- public void setRanking(int ranking) {
- this.ranking = ranking;
- }
-
- public void setServiceProperties(Map serviceProperties) {
- this.serviceProperties = serviceProperties;
- }
-
- public void setManagedComponentName(String managedComponentName) {
- this.managedComponentName = managedComponentName;
- }
-
- public void setComponentDestroyMethod(String componentDestroyMethod) {
- this.componentDestroyMethod = componentDestroyMethod;
- }
-
- private void getRegistrationProperties(Dictionary properties, boolean update) {
- String pid = (String) properties.get(Constants.SERVICE_PID);
- CmProperties cm = findServiceProcessor();
- if (cm == null) {
- while (!properties.isEmpty()) {
- properties.remove(properties.keys().nextElement());
- }
- } else {
- if (!cm.getUpdate()) {
- if (update) {
- while (!properties.isEmpty()) {
- properties.remove(properties.keys().nextElement());
- }
- for (Map.Entry entry : cm.getProperties().entrySet()) {
- properties.put(entry.getKey(), entry.getValue());
- }
- } else {
- cm.updated(properties);
- }
- }
- }
- if (serviceProperties != null) {
- for (Map.Entry entry : serviceProperties.entrySet()) {
- properties.put(entry.getKey(), entry.getValue());
- }
- }
- properties.put(Constants.SERVICE_RANKING, ranking);
- properties.put(Constants.SERVICE_PID, pid);
- }
-
- private void updateComponentProperties(Dictionary props) {
- CmManagedProperties cm = findBeanProcessor();
- if (cm != null) {
- cm.updated(props);
- }
- }
-
- private CmManagedProperties findBeanProcessor() {
- for (BeanProcessor beanProcessor : blueprintContainer.getProcessors(BeanProcessor.class)) {
- if (beanProcessor instanceof CmManagedProperties) {
- CmManagedProperties cm = (CmManagedProperties) beanProcessor;
- if (managedComponentName.equals(cm.getBeanName()) && "".equals(cm.getPersistentId())) {
- return cm;
- }
- }
- }
- return null;
- }
-
- private CmProperties findServiceProcessor() {
- for (ServiceProcessor processor : blueprintContainer.getProcessors(ServiceProcessor.class)) {
- if (processor instanceof CmProperties) {
- CmProperties cm = (CmProperties) processor;
- if (id.equals(cm.getServiceId())) {
- return cm;
- }
- }
- }
- return null;
- }
-
- private Method findDestroyMethod(Class clazz) {
- Method method = null;
- if (componentDestroyMethod != null && componentDestroyMethod.length() > 0) {
- List<Method> methods = ReflectionUtils.findCompatibleMethods(clazz, componentDestroyMethod, new Class [] { int.class });
- if (methods != null && !methods.isEmpty()) {
- method = methods.get(0);
- }
- }
- return method;
- }
-
- protected Object doCreate(Dictionary properties) throws Exception {
- updateComponentProperties(copy(properties));
- Object component = blueprintContainer.getComponentInstance(managedComponentName);
- getRegistrationProperties(properties, false);
- return component;
- }
-
- protected Object doUpdate(Object service, Dictionary properties) throws Exception {
- updateComponentProperties(copy(properties));
- getRegistrationProperties(properties, true);
- return service;
- }
-
- protected void doDestroy(Object service, Dictionary properties, int code) throws Exception {
- Method method = findDestroyMethod(service.getClass());
- if (method != null) {
- try {
- method.invoke(service, new Object [] { code });
- } catch (Exception e) {
- LOGGER.info("Error destroying component", e);
- }
- }
- }
-
- protected void postRegister(Object service, Dictionary properties, ServiceRegistration registration) {
- if (listeners != null && !listeners.isEmpty()) {
- Hashtable props = new Hashtable();
- JavaUtils.copy(properties, props);
- for (ServiceListener listener : listeners) {
- listener.register(service, props);
- }
- }
- }
-
- protected void preUnregister(Object service, Dictionary properties, ServiceRegistration registration) {
- if (listeners != null && !listeners.isEmpty()) {
- Hashtable props = new Hashtable();
- JavaUtils.copy(properties, props);
- for (ServiceListener listener : listeners) {
- listener.unregister(service, props);
- }
- }
- }
-
- protected String[] getExposedClasses(Object service) {
- Class serviceClass = service.getClass();
- Set<String> classes;
- switch (autoExport) {
- case ServiceMetadata.AUTO_EXPORT_INTERFACES:
- classes = ReflectionUtils.getImplementedInterfaces(new HashSet<String>(), serviceClass);
- break;
- case ServiceMetadata.AUTO_EXPORT_CLASS_HIERARCHY:
- classes = ReflectionUtils.getSuperClasses(new HashSet<String>(), serviceClass);
- break;
- case ServiceMetadata.AUTO_EXPORT_ALL_CLASSES:
- classes = ReflectionUtils.getSuperClasses(new HashSet<String>(), serviceClass);
- classes = ReflectionUtils.getImplementedInterfaces(classes, serviceClass);
- break;
- default:
- classes = new HashSet<String>(interfaces);
- break;
- }
- return classes.toArray(new String[classes.size()]);
- }
-
- private Hashtable copy(Dictionary source) {
- Hashtable ht = new Hashtable();
- JavaUtils.copy(ht, source);
- return ht;
- }
-
-}
diff --git a/src/main/java/org/apache/aries/blueprint/compendium/cm/CmNamespaceHandler.java b/src/main/java/org/apache/aries/blueprint/compendium/cm/CmNamespaceHandler.java
deleted file mode 100644
index 34e2909..0000000
--- a/src/main/java/org/apache/aries/blueprint/compendium/cm/CmNamespaceHandler.java
+++ /dev/null
@@ -1,645 +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.aries.blueprint.compendium.cm;
-
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Properties;
-import java.util.Set;
-
-import org.apache.aries.blueprint.ComponentDefinitionRegistry;
-import org.apache.aries.blueprint.NamespaceHandler;
-import org.apache.aries.blueprint.ParserContext;
-import org.apache.aries.blueprint.ext.PlaceholdersUtils;
-import org.apache.aries.blueprint.mutable.MutableBeanMetadata;
-import org.apache.aries.blueprint.mutable.MutableCollectionMetadata;
-import org.apache.aries.blueprint.mutable.MutableComponentMetadata;
-import org.apache.aries.blueprint.mutable.MutableIdRefMetadata;
-import org.apache.aries.blueprint.mutable.MutableMapMetadata;
-import org.apache.aries.blueprint.mutable.MutableRefMetadata;
-import org.apache.aries.blueprint.mutable.MutableReferenceMetadata;
-import org.apache.aries.blueprint.mutable.MutableValueMetadata;
-import org.apache.aries.blueprint.utils.ServiceListener;
-import org.osgi.service.blueprint.container.ComponentDefinitionException;
-import org.osgi.service.blueprint.reflect.BeanMetadata;
-import org.osgi.service.blueprint.reflect.BeanProperty;
-import org.osgi.service.blueprint.reflect.CollectionMetadata;
-import org.osgi.service.blueprint.reflect.ComponentMetadata;
-import org.osgi.service.blueprint.reflect.IdRefMetadata;
-import org.osgi.service.blueprint.reflect.MapMetadata;
-import org.osgi.service.blueprint.reflect.Metadata;
-import org.osgi.service.blueprint.reflect.RefMetadata;
-import org.osgi.service.blueprint.reflect.ReferenceMetadata;
-import org.osgi.service.blueprint.reflect.RegistrationListener;
-import org.osgi.service.blueprint.reflect.ServiceMetadata;
-import org.osgi.service.blueprint.reflect.ValueMetadata;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.CharacterData;
-import org.w3c.dom.Comment;
-import org.w3c.dom.Element;
-import org.w3c.dom.EntityReference;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-/**
- * Namespace handler for the Config Admin service.
- * This handler will parse the various elements defined and populate / modify the registry
- * accordingly.
- *
- * @see CmManagedProperties
- * @see CmManagedServiceFactory
- * @see CmProperties
- * @see CmPropertyPlaceholder
- *
- * @version $Rev$, $Date$
- */
-public class CmNamespaceHandler implements NamespaceHandler {
-
- public static final String BLUEPRINT_NAMESPACE = "http://www.osgi.org/xmlns/blueprint/v1.0.0";
- public static final String BLUEPRINT_CM_NAMESPACE_1_0 = "http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0";
- public static final String BLUEPRINT_CM_NAMESPACE_1_1 = "http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0";
- public static final String BLUEPRINT_CM_NAMESPACE_1_2 = "http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.2.0";
- public static final String BLUEPRINT_EXT_NAMESPACE_V1_0 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0";
- public static final String BLUEPRINT_EXT_NAMESPACE_V1_1 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.1.0";
- public static final String BLUEPRINT_EXT_NAMESPACE_V1_2 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.2.0";
-
- public static final String PROPERTY_PLACEHOLDER_ELEMENT = "property-placeholder";
- public static final String MANAGED_PROPERTIES_ELEMENT = "managed-properties";
- public static final String MANAGED_SERVICE_FACTORY_ELEMENT = "managed-service-factory";
- public static final String CM_PROPERTIES_ELEMENT = "cm-properties";
- public static final String DEFAULT_PROPERTIES_ELEMENT = "default-properties";
- public static final String PROPERTY_ELEMENT = "property";
- public static final String INTERFACES_ELEMENT = "interfaces";
- public static final String VALUE_ELEMENT = "value";
- public static final String MANAGED_COMPONENT_ELEMENT = "managed-component";
- public static final String LOCATION_ELEMENT = "location";
- public static final String SERVICE_PROPERTIES_ELEMENT = "service-properties";
- public static final String REGISTRATION_LISTENER_ELEMENT = "registration-listener";
-
- public static final String ID_ATTRIBUTE = "id";
- public static final String SYSTEM_PROPERTIES_NEVER = "never";
- public static final String PERSISTENT_ID_ATTRIBUTE = "persistent-id";
- public static final String PLACEHOLDER_PREFIX_ATTRIBUTE = "placeholder-prefix";
- public static final String PLACEHOLDER_SUFFIX_ATTRIBUTE = "placeholder-suffix";
- public static final String DEFAULTS_REF_ATTRIBUTE = "defaults-ref";
- public static final String UPDATE_STRATEGY_ATTRIBUTE = "update-strategy";
- public static final String UPDATE_METHOD_ATTRIBUTE = "update-method";
- public static final String FACTORY_PID_ATTRIBUTE = "factory-pid";
- public static final String AUTO_EXPORT_ATTRIBUTE = "auto-export";
- public static final String RANKING_ATTRIBUTE = "ranking";
- public static final String INTERFACE_ATTRIBUTE = "interface";
- public static final String UPDATE_ATTRIBUTE = "update";
- public static final String SYSTEM_PROPERTIES_ATTRIBUTE = "system-properties";
- public static final String IGNORE_MISSING_LOCATIONS_ATTRIBUTE = "ignore-missing-locations";
-
- public static final String AUTO_EXPORT_DISABLED = "disabled";
- public static final String AUTO_EXPORT_INTERFACES = "interfaces";
- public static final String AUTO_EXPORT_CLASS_HIERARCHY = "class-hierarchy";
- public static final String AUTO_EXPORT_ALL = "all-classes";
- public static final String AUTO_EXPORT_DEFAULT = AUTO_EXPORT_DISABLED;
- public static final String RANKING_DEFAULT = "0";
-
- private static final String MANAGED_OBJECT_MANAGER_NAME = "org.apache.aries.managedObjectManager";
-
- private static final Logger LOGGER = LoggerFactory.getLogger(CmNamespaceHandler.class);
-
- // This property is static but it should be ok since there will be only a single instance
- // of this class for the bundle
- private static ConfigurationAdmin configAdmin;
-
- private int idCounter;
-
- public int getIdCounter() {
- return idCounter;
- }
-
- public void setIdCounter(int idCounter) {
- this.idCounter = idCounter;
- }
-
- public static ConfigurationAdmin getConfigAdmin() {
- return configAdmin;
- }
-
- public void setConfigAdmin(ConfigurationAdmin configAdmin) {
- this.configAdmin = configAdmin;
- }
-
- public URL getSchemaLocation(String namespace) {
- if (BLUEPRINT_CM_NAMESPACE_1_2.equals(namespace)) {
- return getClass().getResource("blueprint-cm-1.2.0.xsd");
- } else if (BLUEPRINT_CM_NAMESPACE_1_1.equals(namespace)) {
- return getClass().getResource("blueprint-cm-1.1.0.xsd");
- } else if (BLUEPRINT_CM_NAMESPACE_1_0.equals(namespace)) {
- return getClass().getResource("blueprint-cm-1.0.0.xsd");
- } else {
- return null;
- }
- }
-
- public Set<Class> getManagedClasses() {
- return new HashSet<Class>(Arrays.asList(
- CmPropertyPlaceholder.class,
- CmManagedServiceFactory.class,
- CmManagedProperties.class,
- CmProperties.class
- ));
- }
-
- public Metadata parse(Element element, ParserContext context) {
- LOGGER.debug("Parsing element {{}}{}", element.getNamespaceURI(), element.getLocalName());
- ComponentDefinitionRegistry registry = context.getComponentDefinitionRegistry();
- registerManagedObjectManager(context, registry);
- if (nodeNameEquals(element, PROPERTY_PLACEHOLDER_ELEMENT)) {
- return parsePropertyPlaceholder(context, element);
- } else if (nodeNameEquals(element, MANAGED_SERVICE_FACTORY_ELEMENT)) {
- return parseManagedServiceFactory(context, element);
- } else if (nodeNameEquals(element, CM_PROPERTIES_ELEMENT)) {
- return parseCmProperties(context, element);
- } else {
- throw new ComponentDefinitionException("Unsupported element: " + element.getNodeName());
- }
- }
-
- public ComponentMetadata decorate(Node node, ComponentMetadata component, ParserContext context) {
- LOGGER.debug("Decorating node {{}}{}", node.getNamespaceURI(), node.getLocalName());
- ComponentDefinitionRegistry registry = context.getComponentDefinitionRegistry();
- registerManagedObjectManager(context, registry);
- if (node instanceof Element) {
- if (nodeNameEquals(node, MANAGED_PROPERTIES_ELEMENT)) {
- return decorateManagedProperties(context, (Element) node, component);
- } else if (nodeNameEquals(node, CM_PROPERTIES_ELEMENT)) {
- return decorateCmProperties(context, (Element) node, component);
- } else {
- throw new ComponentDefinitionException("Unsupported element: " + node.getNodeName());
- }
- } else {
- throw new ComponentDefinitionException("Illegal use of blueprint cm namespace");
- }
- }
-
- private ComponentMetadata parseCmProperties(ParserContext context, Element element) {
- String id = getId(context, element);
-
- MutableBeanMetadata factoryMetadata = context.createMetadata(MutableBeanMetadata.class);
- generateIdIfNeeded(context, factoryMetadata);
- factoryMetadata.setScope(BeanMetadata.SCOPE_SINGLETON);
- factoryMetadata.setRuntimeClass(CmProperties.class);
- factoryMetadata.setInitMethod("init");
- factoryMetadata.setDestroyMethod("destroy");
- factoryMetadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
- factoryMetadata.addProperty("configAdmin", createConfigurationAdminRef(context));
- factoryMetadata.addProperty("managedObjectManager", createRef(context, MANAGED_OBJECT_MANAGER_NAME));
- String persistentId = element.getAttribute(PERSISTENT_ID_ATTRIBUTE);
- factoryMetadata.addProperty("persistentId", createValue(context, persistentId));
- context.getComponentDefinitionRegistry().registerComponentDefinition(factoryMetadata);
-
- MutableBeanMetadata propertiesMetadata = context.createMetadata(MutableBeanMetadata.class);
- propertiesMetadata.setId(id);
- propertiesMetadata.setScope(BeanMetadata.SCOPE_SINGLETON);
- propertiesMetadata.setRuntimeClass(Properties.class);
- propertiesMetadata.setFactoryComponent(createRef(context, factoryMetadata.getId()));
- propertiesMetadata.setFactoryComponent(factoryMetadata);
- propertiesMetadata.setFactoryMethod("getProperties");
- // Work around ARIES-877
- propertiesMetadata.setDependsOn(Arrays.asList(factoryMetadata.getId()));
-
- return propertiesMetadata;
- }
-
- private ComponentMetadata parsePropertyPlaceholder(ParserContext context, Element element) {
- MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
- metadata.setProcessor(true);
- metadata.setId(getId(context, element));
- metadata.setScope(BeanMetadata.SCOPE_SINGLETON);
- metadata.setRuntimeClass(CmPropertyPlaceholder.class);
- metadata.setInitMethod("init");
- metadata.setDestroyMethod("destroy");
- metadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
- metadata.addProperty("configAdmin", createConfigurationAdminRef(context));
- metadata.addProperty("persistentId", createValue(context, element.getAttribute(PERSISTENT_ID_ATTRIBUTE)));
- String prefix = element.hasAttribute(PLACEHOLDER_PREFIX_ATTRIBUTE)
- ? element.getAttribute(PLACEHOLDER_PREFIX_ATTRIBUTE)
- : "${";
- metadata.addProperty("placeholderPrefix", createValue(context, prefix));
- String suffix = element.hasAttribute(PLACEHOLDER_SUFFIX_ATTRIBUTE)
- ? element.getAttribute(PLACEHOLDER_SUFFIX_ATTRIBUTE)
- : "}";
- metadata.addProperty("placeholderSuffix", createValue(context, suffix));
- String defaultsRef = element.hasAttribute(DEFAULTS_REF_ATTRIBUTE) ? element.getAttribute(DEFAULTS_REF_ATTRIBUTE) : null;
- if (defaultsRef != null) {
- metadata.addProperty("defaultProperties", createRef(context, defaultsRef));
- }
- String ignoreMissingLocations = extractIgnoreMissingLocations(element);
- if (ignoreMissingLocations != null) {
- metadata.addProperty("ignoreMissingLocations", createValue(context, ignoreMissingLocations));
- }
- String systemProperties = extractSystemPropertiesAttribute(element);
- if (systemProperties == null) {
- systemProperties = SYSTEM_PROPERTIES_NEVER;
- }
- metadata.addProperty("systemProperties", createValue(context, systemProperties));
- String updateStrategy = element.getAttribute(UPDATE_STRATEGY_ATTRIBUTE);
- if (updateStrategy != null) {
- metadata.addProperty("updateStrategy", createValue(context, updateStrategy));
- }
- metadata.addProperty("managedObjectManager", createRef(context, MANAGED_OBJECT_MANAGER_NAME));
- // Parse elements
- List<String> locations = new ArrayList<String>();
- NodeList nl = element.getChildNodes();
- for (int i = 0; i < nl.getLength(); i++) {
- Node node = nl.item(i);
- if (node instanceof Element) {
- Element e = (Element) node;
- if (isCmNamespace(e.getNamespaceURI())) {
- if (nodeNameEquals(e, DEFAULT_PROPERTIES_ELEMENT)) {
- if (defaultsRef != null) {
- throw new ComponentDefinitionException("Only one of " + DEFAULTS_REF_ATTRIBUTE + " attribute or " + DEFAULT_PROPERTIES_ELEMENT + " element is allowed");
- }
- Metadata props = parseDefaultProperties(context, metadata, e);
- metadata.addProperty("defaultProperties", props);
- }
- } else if (isExtNamespace(e.getNamespaceURI())) {
- if (nodeNameEquals(e, LOCATION_ELEMENT)) {
- locations.add(getTextValue(e));
- }
- }
- }
- }
- if (!locations.isEmpty()) {
- metadata.addProperty("locations", createList(context, locations));
- }
-
- PlaceholdersUtils.validatePlaceholder(metadata, context.getComponentDefinitionRegistry());
-
- return metadata;
- }
-
- private String extractSystemPropertiesAttribute(Element element) {
- String systemProperties = null;
-
- if (element.hasAttributeNS(BLUEPRINT_EXT_NAMESPACE_V1_0, SYSTEM_PROPERTIES_ATTRIBUTE)) {
- systemProperties = element.getAttributeNS(BLUEPRINT_EXT_NAMESPACE_V1_0, SYSTEM_PROPERTIES_ATTRIBUTE);
- } else if (element.hasAttributeNS(BLUEPRINT_EXT_NAMESPACE_V1_1, SYSTEM_PROPERTIES_ATTRIBUTE)) {
- systemProperties = element.getAttributeNS(BLUEPRINT_EXT_NAMESPACE_V1_1, SYSTEM_PROPERTIES_ATTRIBUTE);
- } else if (element.hasAttributeNS(BLUEPRINT_EXT_NAMESPACE_V1_2, SYSTEM_PROPERTIES_ATTRIBUTE)) {
- systemProperties = element.getAttributeNS(BLUEPRINT_EXT_NAMESPACE_V1_2, SYSTEM_PROPERTIES_ATTRIBUTE);
- }
- return systemProperties;
- }
-
- private String extractIgnoreMissingLocations(Element element) {
- String ignoreMissingLocations = null;
- if (element.hasAttributeNS(BLUEPRINT_EXT_NAMESPACE_V1_0, IGNORE_MISSING_LOCATIONS_ATTRIBUTE)) {
- ignoreMissingLocations = element.getAttributeNS(BLUEPRINT_EXT_NAMESPACE_V1_0, IGNORE_MISSING_LOCATIONS_ATTRIBUTE);
- } else if (element.hasAttributeNS(BLUEPRINT_EXT_NAMESPACE_V1_1, IGNORE_MISSING_LOCATIONS_ATTRIBUTE)) {
- ignoreMissingLocations = element.getAttributeNS(BLUEPRINT_EXT_NAMESPACE_V1_1, IGNORE_MISSING_LOCATIONS_ATTRIBUTE);
- } else if (element.hasAttributeNS(BLUEPRINT_EXT_NAMESPACE_V1_2, IGNORE_MISSING_LOCATIONS_ATTRIBUTE)) {
- ignoreMissingLocations = element.getAttributeNS(BLUEPRINT_EXT_NAMESPACE_V1_1, IGNORE_MISSING_LOCATIONS_ATTRIBUTE);
- }
- return ignoreMissingLocations;
- }
-
- private Metadata parseDefaultProperties(ParserContext context, MutableBeanMetadata enclosingComponent, Element element) {
- MutableMapMetadata props = context.createMetadata(MutableMapMetadata.class);
- NodeList nl = element.getChildNodes();
- for (int i = 0; i < nl.getLength(); i++) {
- Node node = nl.item(i);
- if (node instanceof Element) {
- Element e = (Element) node;
- if (isCmNamespace(e.getNamespaceURI())) {
- if (nodeNameEquals(e, PROPERTY_ELEMENT)) {
- BeanProperty prop = context.parseElement(BeanProperty.class, enclosingComponent, e);
- props.addEntry(createValue(context, prop.getName(), String.class.getName()), prop.getValue());
- }
- }
- }
- }
- return props;
- }
-
- private ComponentMetadata parseManagedServiceFactory(ParserContext context, Element element) {
- String id = getId(context, element);
-
- MutableBeanMetadata factoryMetadata = context.createMetadata(MutableBeanMetadata.class);
- generateIdIfNeeded(context, factoryMetadata);
- factoryMetadata.addProperty("id", createValue(context, factoryMetadata.getId()));
- factoryMetadata.setScope(BeanMetadata.SCOPE_SINGLETON);
- factoryMetadata.setRuntimeClass(CmManagedServiceFactory.class);
- factoryMetadata.setInitMethod("init");
- factoryMetadata.setDestroyMethod("destroy");
- factoryMetadata.addArgument(createRef(context, "blueprintContainer"), null, 0);
- factoryMetadata.addProperty("factoryPid", createValue(context, element.getAttribute(FACTORY_PID_ATTRIBUTE)));
- String autoExport = element.hasAttribute(AUTO_EXPORT_ATTRIBUTE) ? element.getAttribute(AUTO_EXPORT_ATTRIBUTE) : AUTO_EXPORT_DEFAULT;
- if (AUTO_EXPORT_DISABLED.equals(autoExport)) {
- autoExport = Integer.toString(ServiceMetadata.AUTO_EXPORT_DISABLED);
- } else if (AUTO_EXPORT_INTERFACES.equals(autoExport)) {
- autoExport = Integer.toString(ServiceMetadata.AUTO_EXPORT_INTERFACES);
- } else if (AUTO_EXPORT_CLASS_HIERARCHY.equals(autoExport)) {
- autoExport = Integer.toString(ServiceMetadata.AUTO_EXPORT_CLASS_HIERARCHY);
- } else if (AUTO_EXPORT_ALL.equals(autoExport)) {
- autoExport = Integer.toString(ServiceMetadata.AUTO_EXPORT_ALL_CLASSES);
- } else {
- throw new ComponentDefinitionException("Illegal value (" + autoExport + ") for " + AUTO_EXPORT_ATTRIBUTE + " attribute");
- }
- factoryMetadata.addProperty("autoExport", createValue(context, autoExport));
- String ranking = element.hasAttribute(RANKING_ATTRIBUTE) ? element.getAttribute(RANKING_ATTRIBUTE) : RANKING_DEFAULT;
- factoryMetadata.addProperty("ranking", createValue(context, ranking));
-
- List<String> interfaces = null;
- if (element.hasAttribute(INTERFACE_ATTRIBUTE)) {
- interfaces = Collections.singletonList(element.getAttribute(INTERFACE_ATTRIBUTE));
- factoryMetadata.addProperty("interfaces", createList(context, interfaces));
- }
-
- // Parse elements
- List<RegistrationListener> listeners = new ArrayList<RegistrationListener>();
- NodeList nl = element.getChildNodes();
- for (int i = 0; i < nl.getLength(); i++) {
- Node node = nl.item(i);
- if (node instanceof Element) {
- Element e = (Element) node;
- if (isBlueprintNamespace(e.getNamespaceURI())) {
- if (nodeNameEquals(e, INTERFACES_ELEMENT)) {
- if (interfaces != null) {
- throw new ComponentDefinitionException("Only one of " + INTERFACE_ATTRIBUTE + " attribute or " + INTERFACES_ELEMENT + " element must be used");
- }
- interfaces = parseInterfaceNames(e);
- factoryMetadata.addProperty("interfaces", createList(context, interfaces));
- } else if (nodeNameEquals(e, SERVICE_PROPERTIES_ELEMENT)) {
- MapMetadata map = context.parseElement(MapMetadata.class,
- factoryMetadata, e);
- factoryMetadata.addProperty("serviceProperties", map);
- NodeList enl = e.getChildNodes();
- for (int j = 0; j < enl.getLength(); j++) {
- Node enode = enl.item(j);
- if (enode instanceof Element) {
- if (isCmNamespace(enode.getNamespaceURI()) && nodeNameEquals(enode, CM_PROPERTIES_ELEMENT)) {
- decorateCmProperties(context, (Element) enode, factoryMetadata);
- }
- }
- }
- } else if (nodeNameEquals(e, REGISTRATION_LISTENER_ELEMENT)) {
- listeners.add(context.parseElement(RegistrationListener.class,
- factoryMetadata, e));
- }
- } else if (isCmNamespace(e.getNamespaceURI())) {
- if (nodeNameEquals(e, MANAGED_COMPONENT_ELEMENT)) {
- MutableBeanMetadata managedComponent = context.parseElement(MutableBeanMetadata.class, null, e);
- generateIdIfNeeded(context, managedComponent);
- managedComponent.setScope(BeanMetadata.SCOPE_PROTOTYPE);
- // destroy-method on managed-component has different signature than on regular beans
- // so we'll handle it differently
- String destroyMethod = managedComponent.getDestroyMethod();
- if (destroyMethod != null) {
- factoryMetadata.addProperty("componentDestroyMethod", createValue(context, destroyMethod));
- managedComponent.setDestroyMethod(null);
- }
- context.getComponentDefinitionRegistry().registerComponentDefinition(managedComponent);
- factoryMetadata.addProperty("managedComponentName", createIdRef(context, managedComponent.getId()));
- }
- }
- }
- }
-
- MutableCollectionMetadata listenerCollection = context.createMetadata(MutableCollectionMetadata.class);
- listenerCollection.setCollectionClass(List.class);
- for (RegistrationListener listener : listeners) {
- MutableBeanMetadata bean = context.createMetadata(MutableBeanMetadata.class);
- bean.setRuntimeClass(ServiceListener.class);
- bean.addProperty("listener", listener.getListenerComponent());
- bean.addProperty("registerMethod", createValue(context, listener.getRegistrationMethod()));
- bean.addProperty("unregisterMethod", createValue(context, listener.getUnregistrationMethod()));
- listenerCollection.addValue(bean);
- }
- factoryMetadata.addProperty("listeners", listenerCollection);
-
- context.getComponentDefinitionRegistry().registerComponentDefinition(factoryMetadata);
-
- MutableBeanMetadata mapMetadata = context.createMetadata(MutableBeanMetadata.class);
- mapMetadata.setScope(BeanMetadata.SCOPE_SINGLETON);
- mapMetadata.setId(id);
- mapMetadata.setFactoryComponent(createRef(context, factoryMetadata.getId()));
- mapMetadata.setFactoryMethod("getServiceMap");
- return mapMetadata;
- }
-
- private ComponentMetadata decorateCmProperties(ParserContext context, Element element, ComponentMetadata component) {
- generateIdIfNeeded(context, ((MutableComponentMetadata) component));
- MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
- metadata.setProcessor(true);
- metadata.setId(getId(context, element));
- metadata.setRuntimeClass(CmProperties.class);
- String persistentId = element.getAttribute(PERSISTENT_ID_ATTRIBUTE);
- // if persistentId is "" the cm-properties element in nested in managed-service-factory
- // and the configuration object will come from the factory. So we only really need to register
- // ManagedService if the persistentId is not an empty string.
- if (persistentId.length() > 0) {
- metadata.setInitMethod("init");
- metadata.setDestroyMethod("destroy");
- }
- metadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
- metadata.addProperty("configAdmin", createConfigurationAdminRef(context));
- metadata.addProperty("managedObjectManager", createRef(context, MANAGED_OBJECT_MANAGER_NAME));
- metadata.addProperty("persistentId", createValue(context, persistentId));
- if (element.hasAttribute(UPDATE_ATTRIBUTE)) {
- metadata.addProperty("update", createValue(context, element.getAttribute(UPDATE_ATTRIBUTE)));
- }
- metadata.addProperty("serviceId", createIdRef(context, component.getId()));
- context.getComponentDefinitionRegistry().registerComponentDefinition(metadata);
- return component;
- }
-
- private ComponentMetadata decorateManagedProperties(ParserContext context, Element element, ComponentMetadata component) {
- if (!(component instanceof MutableBeanMetadata)) {
- throw new ComponentDefinitionException("Element " + MANAGED_PROPERTIES_ELEMENT + " must be used inside a <bp:bean> element");
- }
- generateIdIfNeeded(context, ((MutableBeanMetadata) component));
- MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
- metadata.setProcessor(true);
- metadata.setId(getId(context, element));
- metadata.setRuntimeClass(CmManagedProperties.class);
- String persistentId = element.getAttribute(PERSISTENT_ID_ATTRIBUTE);
- // if persistentId is "" the managed properties element in nested in managed-service-factory
- // and the configuration object will come from the factory. So we only really need to register
- // ManagedService if the persistentId is not an empty string.
- if (persistentId.length() > 0) {
- metadata.setInitMethod("init");
- metadata.setDestroyMethod("destroy");
- }
- metadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
- metadata.addProperty("configAdmin", createConfigurationAdminRef(context));
- metadata.addProperty("managedObjectManager", createRef(context, MANAGED_OBJECT_MANAGER_NAME));
- metadata.addProperty("persistentId", createValue(context, persistentId));
- String updateStrategy = element.getAttribute(UPDATE_STRATEGY_ATTRIBUTE);
- if (updateStrategy != null) {
- metadata.addProperty("updateStrategy", createValue(context, updateStrategy));
- }
- if (element.hasAttribute(UPDATE_METHOD_ATTRIBUTE)) {
- metadata.addProperty("updateMethod", createValue(context, element.getAttribute(UPDATE_METHOD_ATTRIBUTE)));
- } else if ("component-managed".equals(updateStrategy)) {
- throw new ComponentDefinitionException(UPDATE_METHOD_ATTRIBUTE + " attribute must be set when " + UPDATE_STRATEGY_ATTRIBUTE + " is set to 'component-managed'");
- }
- metadata.addProperty("beanName", createIdRef(context, component.getId()));
- context.getComponentDefinitionRegistry().registerComponentDefinition(metadata);
- return component;
- }
-
- private void registerManagedObjectManager(ParserContext context, ComponentDefinitionRegistry registry) {
- if (registry.getComponentDefinition(MANAGED_OBJECT_MANAGER_NAME) == null) {
- MutableBeanMetadata beanMetadata = context.createMetadata(MutableBeanMetadata.class);
- beanMetadata.setScope(BeanMetadata.SCOPE_SINGLETON);
- beanMetadata.setId(MANAGED_OBJECT_MANAGER_NAME);
- beanMetadata.setRuntimeClass(ManagedObjectManager.class);
- registry.registerComponentDefinition(beanMetadata);
- }
- }
-
- private MutableReferenceMetadata createConfigurationAdminRef(ParserContext context) {
- return createServiceRef(context, ConfigurationAdmin.class, null);
- }
-
- private static ValueMetadata createValue(ParserContext context, String value) {
- return createValue(context, value, null);
- }
-
- private static ValueMetadata createValue(ParserContext context, String value, String type) {
- MutableValueMetadata m = context.createMetadata(MutableValueMetadata.class);
- m.setStringValue(value);
- m.setType(type);
- return m;
- }
-
- private static RefMetadata createRef(ParserContext context, String value) {
- MutableRefMetadata m = context.createMetadata(MutableRefMetadata.class);
- m.setComponentId(value);
- return m;
- }
-
- private MutableReferenceMetadata createServiceRef(ParserContext context, Class<?> cls, String filter) {
- MutableReferenceMetadata m = context.createMetadata(MutableReferenceMetadata.class);
- m.setRuntimeInterface(cls);
- m.setInterface(cls.getName());
- m.setActivation(ReferenceMetadata.ACTIVATION_EAGER);
- m.setAvailability(ReferenceMetadata.AVAILABILITY_MANDATORY);
-
- if (filter != null) {
- m.setFilter(filter);
- }
-
- return m;
- }
-
- private static IdRefMetadata createIdRef(ParserContext context, String value) {
- MutableIdRefMetadata m = context.createMetadata(MutableIdRefMetadata.class);
- m.setComponentId(value);
- return m;
- }
-
- private static CollectionMetadata createList(ParserContext context, List<String> list) {
- MutableCollectionMetadata m = context.createMetadata(MutableCollectionMetadata.class);
- m.setCollectionClass(List.class);
- m.setValueType(String.class.getName());
- for (String v : list) {
- m.addValue(createValue(context, v, String.class.getName()));
- }
- return m;
- }
-
- private static String getTextValue(Element element) {
- StringBuffer value = new StringBuffer();
- NodeList nl = element.getChildNodes();
- for (int i = 0; i < nl.getLength(); i++) {
- Node item = nl.item(i);
- if ((item instanceof CharacterData && !(item instanceof Comment)) || item instanceof EntityReference) {
- value.append(item.getNodeValue());
- }
- }
- return value.toString();
- }
-
- private static boolean nodeNameEquals(Node node, String name) {
- return (name.equals(node.getNodeName()) || name.equals(node.getLocalName()));
- }
-
- public static boolean isBlueprintNamespace(String ns) {
- return BLUEPRINT_NAMESPACE.equals(ns);
- }
-
- public static boolean isCmNamespace(String uri) {
- return BLUEPRINT_CM_NAMESPACE_1_0.equals(uri)
- || BLUEPRINT_CM_NAMESPACE_1_1.equals(uri)
- || BLUEPRINT_CM_NAMESPACE_1_2.equals(uri);
- }
-
- public static boolean isExtNamespace(String uri) {
- return BLUEPRINT_EXT_NAMESPACE_V1_0.equals(uri)
- || BLUEPRINT_EXT_NAMESPACE_V1_1.equals(uri)
- || BLUEPRINT_EXT_NAMESPACE_V1_2.equals(uri);
- }
-
- public String getId(ParserContext context, Element element) {
- if (element.hasAttribute(ID_ATTRIBUTE)) {
- return element.getAttribute(ID_ATTRIBUTE);
- } else {
- return generateId(context);
- }
- }
-
- public void generateIdIfNeeded(ParserContext context, MutableComponentMetadata metadata) {
- if (metadata.getId() == null) {
- metadata.setId(generateId(context));
- }
- }
-
- private String generateId(ParserContext context) {
- String id;
- do {
- id = ".cm-" + ++idCounter;
- } while (context.getComponentDefinitionRegistry().containsComponentDefinition(id));
- return id;
- }
-
- public List<String> parseInterfaceNames(Element element) {
- List<String> interfaceNames = new ArrayList<String>();
- NodeList nl = element.getChildNodes();
- for (int i = 0; i < nl.getLength(); i++) {
- Node node = nl.item(i);
- if (node instanceof Element) {
- Element e = (Element) node;
- if (nodeNameEquals(e, VALUE_ELEMENT)) {
- String v = getTextValue(e).trim();
- if (interfaceNames.contains(v)) {
- throw new ComponentDefinitionException("The element " + INTERFACES_ELEMENT + " should not contain the same interface twice");
- }
- interfaceNames.add(getTextValue(e));
- } else {
- throw new ComponentDefinitionException("Unsupported element " + e.getNodeName() + " inside an " + INTERFACES_ELEMENT + " element");
- }
- }
- }
- return interfaceNames;
- }
-}
diff --git a/src/main/java/org/apache/aries/blueprint/compendium/cm/CmProperties.java b/src/main/java/org/apache/aries/blueprint/compendium/cm/CmProperties.java
deleted file mode 100644
index eb8b881..0000000
--- a/src/main/java/org/apache/aries/blueprint/compendium/cm/CmProperties.java
+++ /dev/null
@@ -1,172 +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.aries.blueprint.compendium.cm;
-
-import java.util.Dictionary;
-import java.util.HashSet;
-import java.util.Properties;
-import java.util.Set;
-
-import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
-import org.apache.aries.blueprint.ServiceProcessor;
-import org.apache.aries.blueprint.utils.JavaUtils;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * @version $Rev$, $Date$
- */
-public class CmProperties implements ManagedObject, ServiceProcessor {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(CmProperties.class);
-
- private ExtendedBlueprintContainer blueprintContainer;
- private ConfigurationAdmin configAdmin;
- private ManagedObjectManager managedObjectManager;
- private String persistentId;
- private boolean update;
- private String serviceId;
-
- private final Object lock = new Object();
- private final Set<ServicePropertiesUpdater> services = new HashSet<ServicePropertiesUpdater>();
- private final Properties properties = new Properties();
-
- public ExtendedBlueprintContainer getBlueprintContainer() {
- return blueprintContainer;
- }
-
- public void setBlueprintContainer(ExtendedBlueprintContainer blueprintContainer) {
- this.blueprintContainer = blueprintContainer;
- }
-
- public ConfigurationAdmin getConfigAdmin() {
- return configAdmin;
- }
-
- public void setConfigAdmin(ConfigurationAdmin configAdmin) {
- this.configAdmin = configAdmin;
- }
-
- public void setManagedObjectManager(ManagedObjectManager managedObjectManager) {
- this.managedObjectManager = managedObjectManager;
- }
-
- public ManagedObjectManager getManagedObjectManager() {
- return managedObjectManager;
- }
-
- public Bundle getBundle() {
- return blueprintContainer.getBundleContext().getBundle();
- }
-
- public String getPersistentId() {
- return persistentId;
- }
-
- public void setPersistentId(String persistentId) {
- this.persistentId = persistentId;
- }
-
- public boolean getUpdate() {
- return update;
- }
-
- public void setUpdate(boolean update) {
- this.update = update;
- }
-
- public String getServiceId() {
- return serviceId;
- }
-
- public void setServiceId(String serviceId) {
- this.serviceId = serviceId;
- }
-
- public void init() throws Exception {
- if (serviceId != null) {
- LOGGER.debug("Initializing CmProperties for service={} / pid={}", serviceId, persistentId);
- } else {
- LOGGER.debug("Initializing CmProperties for pid={}", persistentId);
- }
-
- Properties props = new Properties();
- props.put(Constants.SERVICE_PID, persistentId);
- Bundle bundle = blueprintContainer.getBundleContext().getBundle();
- props.put(Constants.BUNDLE_SYMBOLICNAME, bundle.getSymbolicName());
- props.put(Constants.BUNDLE_VERSION, bundle.getHeaders().get(Constants.BUNDLE_VERSION));
-
- synchronized (lock) {
- managedObjectManager.register(this, props);
- Configuration config = CmUtils.getConfiguration(configAdmin, persistentId);
- if (config != null) {
- properties.clear();
- JavaUtils.copy(properties, config.getProperties());
- }
- }
- }
-
- public void destroy() {
- managedObjectManager.unregister(this);
- }
-
- public Properties getProperties() {
- return properties;
- }
-
- public void updated(Dictionary props) {
- if (serviceId != null) {
- LOGGER.debug("Service properties updated for service={} / pid={}, {}", new Object[] {serviceId, persistentId, props});
- } else {
- LOGGER.debug("Service properties updated for pid={}, {}", new Object[] {persistentId, props});
- }
-
- synchronized (lock) {
- properties.clear();
- if (props != null) {
- JavaUtils.copy(properties, props);
- }
- if (update) {
- for (ServicePropertiesUpdater service : services) {
- service.updateProperties(props);
- }
- }
- }
- }
-
- public void updateProperties(ServicePropertiesUpdater service, Dictionary props) {
- if (this.serviceId == null || !this.serviceId.equals(service.getId())) {
- return;
- }
-
- LOGGER.debug("Service properties initialized for service={} / pid={}, {}", new Object[] {serviceId, persistentId, props});
-
- synchronized (lock) {
- services.add(service);
- if (properties != null) {
- JavaUtils.copy(props, properties);
- }
- }
- }
-
-}
diff --git a/src/main/java/org/apache/aries/blueprint/compendium/cm/CmPropertyPlaceholder.java b/src/main/java/org/apache/aries/blueprint/compendium/cm/CmPropertyPlaceholder.java
deleted file mode 100644
index 7abb98e..0000000
--- a/src/main/java/org/apache/aries/blueprint/compendium/cm/CmPropertyPlaceholder.java
+++ /dev/null
@@ -1,166 +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.aries.blueprint.compendium.cm;
-
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.Properties;
-
-import org.apache.aries.blueprint.ext.PropertyPlaceholder;
-import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.Constants;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * TODO: javadoc
- *
- * @version $Rev$, $Date$
- */
-public class CmPropertyPlaceholder extends PropertyPlaceholder implements ManagedObject {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(CmPropertyPlaceholder.class);
-
- private ExtendedBlueprintContainer blueprintContainer;
- private ConfigurationAdmin configAdmin;
- private String persistentId;
- private String updateStrategy;
- private ManagedObjectManager managedObjectManager;
- private Dictionary<String,Object> properties;
-
- public ExtendedBlueprintContainer getBlueprintContainer() {
- return blueprintContainer;
- }
-
- public void setBlueprintContainer(ExtendedBlueprintContainer blueprintContainer) {
- this.blueprintContainer = blueprintContainer;
- }
-
- public ConfigurationAdmin getConfigAdmin() {
- return configAdmin;
- }
-
- public void setConfigAdmin(ConfigurationAdmin configAdmin) {
- this.configAdmin = configAdmin;
- }
-
- public String getPersistentId() {
- return persistentId;
- }
-
- public void setPersistentId(String persistentId) {
- this.persistentId = persistentId;
- }
-
- public String getUpdateStrategy() {
- return updateStrategy;
- }
-
- public void setUpdateStrategy(String updateStrategy) {
- this.updateStrategy = updateStrategy;
- }
-
- public ManagedObjectManager getManagedObjectManager() {
- return managedObjectManager;
- }
-
- public void setManagedObjectManager(ManagedObjectManager managedObjectManager) {
- this.managedObjectManager = managedObjectManager;
- }
-
- public void init() throws Exception {
- LOGGER.debug("Initializing CmPropertyPlaceholder");
- Configuration config = CmUtils.getConfiguration(configAdmin, persistentId);
- if (config != null) {
- properties = config.getProperties();
- }
- Properties props = new Properties();
- props.put(Constants.SERVICE_PID, persistentId);
- Bundle bundle = blueprintContainer.getBundleContext().getBundle();
- props.put(Constants.BUNDLE_SYMBOLICNAME, bundle.getSymbolicName());
- props.put(Constants.BUNDLE_VERSION, bundle.getHeaders().get(Constants.BUNDLE_VERSION));
- managedObjectManager.register(this, props);
- }
-
- public void destroy() {
- LOGGER.debug("Destroying CmPropertyPlaceholder");
- managedObjectManager.unregister(this);
- }
-
- protected String getProperty(String val) {
- LOGGER.debug("Retrieving property value {} from configuration with pid {}", val, persistentId);
- Object v = null;
- if (properties != null) {
- v = properties.get(val);
- if (v != null) {
- LOGGER.debug("Found property value {}", v);
- } else {
- LOGGER.debug("Property not found in configuration");
- }
- }
- if (v == null) {
- v = super.getProperty(val);
- }
- return v != null ? v.toString() : null;
- }
-
- public Bundle getBundle() {
- return blueprintContainer.getBundleContext().getBundle();
- }
-
- public void updated(Dictionary props) {
- if ("reload".equalsIgnoreCase(updateStrategy) && !equals(properties, props)) {
- LOGGER.debug("Configuration updated for pid={}", persistentId);
- // Run in a separate thread to avoid re-entrance
- new Thread() {
- public void run() {
- blueprintContainer.reload();
- }
- }.start();
- }
- }
-
- private <T,U> boolean equals(Dictionary<T,U> d1, Dictionary<T,U> d2) {
- if (d1 == null || d1.isEmpty()) {
- return d2 == null || d2.isEmpty();
- } else if (d2 == null || d1.size() != d2.size()) {
- return false;
- } else {
- for (Enumeration<T> e = d1.keys(); e.hasMoreElements();) {
- T k = e.nextElement();
- U v1 = d1.get(k);
- U v2 = d2.get(k);
- if (v1 == null) {
- if (v2 != null) {
- return false;
- }
- } else {
- if (!v1.equals(v2)) {
- return false;
- }
- }
- }
- return true;
- }
- }
-
-}
diff --git a/src/main/java/org/apache/aries/blueprint/compendium/cm/CmUtils.java b/src/main/java/org/apache/aries/blueprint/compendium/cm/CmUtils.java
deleted file mode 100644
index aa407f8..0000000
--- a/src/main/java/org/apache/aries/blueprint/compendium/cm/CmUtils.java
+++ /dev/null
@@ -1,51 +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.aries.blueprint.compendium.cm;
-
-import java.io.IOException;
-
-import org.osgi.framework.Constants;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-public class CmUtils {
-
- private CmUtils() {
- }
-
- public static Configuration getConfiguration(ConfigurationAdmin configAdmin, String persistentId) throws IOException {
- String filter = '(' + Constants.SERVICE_PID + '=' + persistentId + ')';
- Configuration[] configs;
- try {
- configs = configAdmin.listConfigurations(filter);
- } catch (InvalidSyntaxException e) {
- // this should not happen
- throw new RuntimeException("Invalid filter: " + filter);
- }
- if (configs != null && configs.length > 0) {
- return configs[0];
- } else {
- // TODO: what should we do?
- // throw new RuntimeException("No configuration object for pid=" + persistentId);
- return null;
- }
- }
-
-}
diff --git a/src/main/java/org/apache/aries/blueprint/compendium/cm/ManagedObject.java b/src/main/java/org/apache/aries/blueprint/compendium/cm/ManagedObject.java
deleted file mode 100644
index 8005dc5..0000000
--- a/src/main/java/org/apache/aries/blueprint/compendium/cm/ManagedObject.java
+++ /dev/null
@@ -1,32 +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.aries.blueprint.compendium.cm;
-
-import java.util.Dictionary;
-
-import org.osgi.framework.Bundle;
-
-public interface ManagedObject {
-
- Bundle getBundle();
- String getPersistentId();
-
- void updated(Dictionary props);
-
-}
diff --git a/src/main/java/org/apache/aries/blueprint/compendium/cm/ManagedObjectManager.java b/src/main/java/org/apache/aries/blueprint/compendium/cm/ManagedObjectManager.java
deleted file mode 100644
index 90bc7f4..0000000
--- a/src/main/java/org/apache/aries/blueprint/compendium/cm/ManagedObjectManager.java
+++ /dev/null
@@ -1,108 +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.aries.blueprint.compendium.cm;
-
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import org.apache.aries.util.AriesFrameworkUtil;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.cm.ConfigurationException;
-import org.osgi.service.cm.ManagedService;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Since persistence id can only be associated with one ManagedService in a bundle
- * this class ensures only one ManagedService is registered per persistence id.
- */
-public class ManagedObjectManager {
-
- private static final Logger LOGGER = LoggerFactory.getLogger(ManagedObjectManager.class);
-
- private HashMap<String, ConfigurationWatcher> map = new HashMap<String, ConfigurationWatcher>();
-
- public synchronized void register(ManagedObject cm, Properties props) {
- String key = cm.getPersistentId();
- ConfigurationWatcher reg = map.get(key);
- if (reg == null) {
- reg = new ConfigurationWatcher();
- ServiceRegistration registration = cm.getBundle().getBundleContext().registerService(ManagedService.class.getName(), reg, props);
- reg.setRegistration(registration);
- map.put(key, reg);
- }
- reg.add(cm);
- }
-
- public synchronized void unregister(ManagedObject cm) {
- String key = cm.getPersistentId();
- ConfigurationWatcher reg = map.get(key);
- if (reg != null) {
- reg.remove(cm);
- if (reg.isEmpty()) {
- map.remove(key);
- AriesFrameworkUtil.safeUnregisterService(reg.getRegistration());
- }
- }
- }
-
- private static class ConfigurationWatcher implements ManagedService {
-
- private ServiceRegistration registration;
- private List<ManagedObject> list = new CopyOnWriteArrayList<ManagedObject>();
-
- public ConfigurationWatcher() {
- }
-
- public void updated(final Dictionary props) throws ConfigurationException {
- // Run in a separate thread to avoid re-entrance
- new Thread() {
- public void run() {
- for (ManagedObject cm : list) {
- cm.updated(props);
- }
- }
- }.start();
- }
-
- private void setRegistration(ServiceRegistration registration) {
- this.registration = registration;
- }
-
- private ServiceRegistration getRegistration() {
- return registration;
- }
-
- private void add(ManagedObject cm) {
- list.add(cm);
- }
-
- private void remove(ManagedObject cm) {
- list.remove(cm);
- }
-
- private boolean isEmpty() {
- return list.isEmpty();
- }
- }
-
-}
diff --git a/src/main/java/org/apache/aries/blueprint/compendium/cm/packageinfo b/src/main/java/org/apache/aries/blueprint/compendium/cm/packageinfo
deleted file mode 100644
index c72722a..0000000
--- a/src/main/java/org/apache/aries/blueprint/compendium/cm/packageinfo
+++ /dev/null
@@ -1,19 +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.
-#
-version 1.0.0
diff --git a/src/main/java/org/apache/aries/blueprint/container/BeanRecipe.java b/src/main/java/org/apache/aries/blueprint/container/BeanRecipe.java
new file mode 100644
index 0000000..226fdee
--- /dev/null
+++ b/src/main/java/org/apache/aries/blueprint/container/BeanRecipe.java
@@ -0,0 +1,1073 @@
+/*
+ * 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.aries.blueprint.container;
+
+import static org.apache.aries.blueprint.utils.ReflectionUtils.getRealCause;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Callable;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicReference;
+
+import org.apache.aries.blueprint.BeanProcessor;
+import org.apache.aries.blueprint.ComponentDefinitionRegistry;
+import org.apache.aries.blueprint.Interceptor;
+import org.apache.aries.blueprint.di.AbstractRecipe;
+import org.apache.aries.blueprint.di.Recipe;
+import org.apache.aries.blueprint.proxy.Collaborator;
+import org.apache.aries.blueprint.proxy.ProxyUtils;
+import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
+import org.apache.aries.blueprint.utils.ReflectionUtils;
+import org.apache.aries.blueprint.utils.ReflectionUtils.PropertyDescriptor;
+import org.apache.aries.proxy.UnableToProxyException;
+import org.osgi.service.blueprint.container.ComponentDefinitionException;
+import org.osgi.service.blueprint.container.ReifiedType;
+import org.osgi.service.blueprint.reflect.BeanMetadata;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A <code>Recipe</code> to create POJOs.
+ *
+ * @version $Rev$, $Date$
+ */
+public class BeanRecipe extends AbstractRecipe {
+
+ static class UnwrapperedBeanHolder {
+ final Object unwrapperedBean;
+ final BeanRecipe recipe;
+
+ public UnwrapperedBeanHolder(Object unwrapperedBean, BeanRecipe recipe) {
+ this.unwrapperedBean = unwrapperedBean;
+ this.recipe = recipe;
+ }
+ }
+
+ public class VoidableCallable implements Callable<Object>, Voidable {
+
+ private final AtomicReference<Object> ref = new AtomicReference<Object>();
+
+ private final Semaphore sem = new Semaphore(1);
+
+ private final ThreadLocal<Object> deadlockDetector = new ThreadLocal<Object>();
+
+ public void voidReference() {
+ ref.set(null);
+ }
+
+ public Object call() throws ComponentDefinitionException {
+ Object o = ref.get();
+
+ if (o == null) {
+ if(deadlockDetector.get() != null) {
+ deadlockDetector.remove();
+ throw new ComponentDefinitionException("Construction cycle detected for bean " + name);
+ }
+
+ sem.acquireUninterruptibly();
+ try {
+ o = ref.get();
+ if (o == null) {
+ deadlockDetector.set(this);
+ try {
+ o = internalCreate2();
+ ref.set(o);
+ } finally {
+ deadlockDetector.remove();
+ }
+ }
+ } finally {
+ sem.release();
+ }
+ }
+
+ return o;
+ }
+
+ }
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(BeanRecipe.class);
+
+ private final ExtendedBlueprintContainer blueprintContainer;
+ private final LinkedHashMap<String,Object> properties = new LinkedHashMap<String,Object>();
+ private final Object type;
+
+ private String initMethod;
+ private String destroyMethod;
+ private List<Recipe> explicitDependencies;
+
+ private Recipe factory;
+ private String factoryMethod;
+ private List<Object> arguments;
+ private List<String> argTypes;
+ private boolean reorderArguments;
+ private final boolean allowsFieldInjection;
+ private BeanMetadata interceptorLookupKey;
+
+
+ public BeanRecipe(String name, ExtendedBlueprintContainer blueprintContainer, Object type, boolean allowsFieldInjection) {
+ super(name);
+ this.blueprintContainer = blueprintContainer;
+ this.type = type;
+ this.allowsFieldInjection = allowsFieldInjection;
+ }
+
+ public Object getProperty(String name) {
+ return properties.get(name);
+ }
+
+ public Map<String, Object> getProperties() {
+ return new LinkedHashMap<String, Object>(properties);
+ }
+
+ public void setProperty(String name, Object value) {
+ properties.put(name, value);
+ }
+
+ public void setFactoryMethod(String method) {
+ this.factoryMethod = method;
+ }
+
+ public void setFactoryComponent(Recipe factory) {
+ this.factory = factory;
+ }
+
+ public void setArgTypes(List<String> argTypes) {
+ this.argTypes = argTypes;
+ }
+
+ public void setArguments(List<Object> arguments) {
+ this.arguments = arguments;
+ }
+
+ public void setReorderArguments(boolean reorder) {
+ this.reorderArguments = reorder;
+ }
+
+ public void setInitMethod(String initMethod) {
+ this.initMethod = initMethod;
+ }
+
+ public String getInitMethod() {
+ return initMethod;
+ }
+
+ public void setDestroyMethod(String destroyMethod) {
+ this.destroyMethod = destroyMethod;
+ }
+
+ public String getDestroyMethod() {
+ return destroyMethod;
+ }
+
+ public List<Recipe> getExplicitDependencies() {
+ return explicitDependencies;
+ }
+
+ public void setExplicitDependencies(List<Recipe> explicitDependencies) {
+ this.explicitDependencies = explicitDependencies;
+ }
+
+ public void setInterceptorLookupKey(BeanMetadata metadata) {
+ interceptorLookupKey = metadata;
+ }
+
+ @Override
+ public List<Recipe> getConstructorDependencies() {
+ List<Recipe> recipes = new ArrayList<Recipe>();
+ if (explicitDependencies != null) {
+ recipes.addAll(explicitDependencies);
+ }
+ if (arguments != null) {
+ for (Object argument : arguments) {
+ if (argument instanceof Recipe) {
+ recipes.add((Recipe)argument);
+ }
+ }
+ }
+ return recipes;
+ }
+
+ public List<Recipe> getDependencies() {
+ List<Recipe> recipes = new ArrayList<Recipe>();
+ for (Object o : properties.values()) {
+ if (o instanceof Recipe) {
+ Recipe recipe = (Recipe) o;
+ recipes.add(recipe);
+ }
+ }
+ recipes.addAll(getConstructorDependencies());
+ return recipes;
+ }
+
+ private void instantiateExplicitDependencies() {
+ if (explicitDependencies != null) {
+ for (Recipe recipe : explicitDependencies) {
+ recipe.create();
+ }
+ }
+ }
+
+ @Override
+ protected Class loadClass(String className) {
+ ClassLoader loader = type instanceof Class ? ((Class) type).getClassLoader() : null;
+ ReifiedType t = loadType(className, loader);
+ return t != null ? t.getRawClass() : null;
+ }
+
+ @Override
+ protected ReifiedType loadType(String className) {
+ return loadType(className, type instanceof Class ? ((Class) type).getClassLoader() : null);
+ }
+
+ private Object getInstance() throws ComponentDefinitionException {
+ Object instance;
+
+ // Instanciate arguments
+ List<Object> args = new ArrayList<Object>();
+ List<ReifiedType> argTypes = new ArrayList<ReifiedType>();
+ if (arguments != null) {
+ for (int i = 0; i < arguments.size(); i++) {
+ Object arg = arguments.get(i);
+ if (arg instanceof Recipe) {
+ args.add(((Recipe) arg).create());
+ } else {
+ args.add(arg);
+ }
+ if (this.argTypes != null) {
+ argTypes.add(this.argTypes.get(i) != null ? loadType(this.argTypes.get(i)) : null);
+ }
+ }
+ }
+
+ if (factory != null) {
+ // look for instance method on factory object
+ Object factoryObj = factory.create();
+
+ // If the factory is a service reference, we need to get hold of the actual proxy for the service
+ /* BLUEPRINT-NOOSGI
+ if (factoryObj instanceof ReferenceRecipe.ServiceProxyWrapper) {
+ try {
+ factoryObj = ((ReferenceRecipe.ServiceProxyWrapper) factoryObj).convert(new ReifiedType(Object.class));
+ } catch (Exception e) {
+ throw new ComponentDefinitionException("Error when instantiating bean " + getName() + " of class " + getType(), getRealCause(e));
+ }
+ } else*/ if (factoryObj instanceof UnwrapperedBeanHolder) {
+ factoryObj = wrap((UnwrapperedBeanHolder) factoryObj, Object.class);
+ }
+
+ // Map of matching methods
+ Map<Method, List<Object>> matches = findMatchingMethods(factoryObj.getClass(), factoryMethod, true, args, argTypes);
+ if (matches.size() == 1) {
+ try {
+ Map.Entry<Method, List<Object>> match = matches.entrySet().iterator().next();
+ instance = invoke(match.getKey(), factoryObj, match.getValue().toArray());
+ } catch (Throwable e) {
+ throw new ComponentDefinitionException("Error when instantiating bean " + getName() + " of class " + getType(), getRealCause(e));
+ }
+ } else if (matches.size() == 0) {
+ throw new ComponentDefinitionException("Unable to find a matching factory method " + factoryMethod + " on class " + factoryObj.getClass().getName() + " for arguments " + args + " when instanciating bean " + getName());
+ } else {
+ throw new ComponentDefinitionException("Multiple matching factory methods " + factoryMethod + " found on class " + factoryObj.getClass().getName() + " for arguments " + args + " when instanciating bean " + getName() + ": " + matches.keySet());
+ }
+ } else if (factoryMethod != null) {
+ // Map of matching methods
+ Map<Method, List<Object>> matches = findMatchingMethods(getType(), factoryMethod, false, args, argTypes);
+ if (matches.size() == 1) {
+ try {
+ Map.Entry<Method, List<Object>> match = matches.entrySet().iterator().next();
+ instance = invoke(match.getKey(), null, match.getValue().toArray());
+ } catch (Throwable e) {
+ throw new ComponentDefinitionException("Error when instanciating bean " + getName() + " of class " + getType(), getRealCause(e));
+ }
+ } else if (matches.size() == 0) {
+ throw new ComponentDefinitionException("Unable to find a matching factory method " + factoryMethod + " on class " + getType().getName() + " for arguments " + args + " when instanciating bean " + getName());
+ } else {
+ throw new ComponentDefinitionException("Multiple matching factory methods " + factoryMethod + " found on class " + getType().getName() + " for arguments " + args + " when instanciating bean " + getName() + ": " + matches.keySet());
+ }
+ } else {
+ if (getType() == null) {
+ throw new ComponentDefinitionException("No factoryMethod nor class is defined for this bean");
+ }
+ // Map of matching constructors
+ Map<Constructor, List<Object>> matches = findMatchingConstructors(getType(), args, argTypes);
+ if (matches.size() == 1) {
+ try {
+ Map.Entry<Constructor, List<Object>> match = matches.entrySet().iterator().next();
+ instance = newInstance(match.getKey(), match.getValue().toArray());
+ } catch (Throwable e) {
+ throw new ComponentDefinitionException("Error when instanciating bean " + getName() + " of class " + getType(), getRealCause(e));
+ }
+ } else if (matches.size() == 0) {
+ throw new ComponentDefinitionException("Unable to find a matching constructor on class " + getType().getName() + " for arguments " + args + " when instanciating bean " + getName());
+ } else {
+ throw new ComponentDefinitionException("Multiple matching constructors found on class " + getType().getName() + " for arguments " + args + " when instanciating bean " + getName() + ": " + matches.keySet());
+ }
+ }
+
+ return instance;
+ }
+
+ private Map<Method, List<Object>> findMatchingMethods(Class type, String name, boolean instance, List<Object> args, List<ReifiedType> types) {
+ Map<Method, List<Object>> matches = new HashMap<Method, List<Object>>();
+ // Get constructors
+ List<Method> methods = new ArrayList<Method>(Arrays.asList(type.getMethods()));
+ // Discard any signature with wrong cardinality
+ for (Iterator<Method> it = methods.iterator(); it.hasNext();) {
+ Method mth = it.next();
+ if (!mth.getName().equals(name)) {
+ it.remove();
+ } else if (mth.getParameterTypes().length != args.size()) {
+ it.remove();
+ } else if (instance ^ !Modifier.isStatic(mth.getModifiers())) {
+ it.remove();
+ } else if (mth.isBridge()) {
+ it.remove();
+ }
+ }
+
+ // on some JVMs (J9) hidden static methods are returned by Class.getMethods so we need to weed them out
+ // to reduce ambiguity
+ if (!instance) {
+ methods = applyStaticHidingRules(methods);
+ }
+
+ // Find a direct match with assignment
+ if (matches.size() != 1) {
+ Map<Method, List<Object>> nmatches = new HashMap<Method, List<Object>>();
+ for (Method mth : methods) {
+ boolean found = true;
+ List<Object> match = new ArrayList<Object>();
+ for (int i = 0; i < args.size(); i++) {
+ ReifiedType argType = new GenericType(mth.getGenericParameterTypes()[i]);
+ if (types.get(i) != null && !argType.getRawClass().equals(types.get(i).getRawClass())) {
+ found = false;
+ break;
+ }
+ //If the arg is an Unwrappered bean then we need to do the assignment check against the
+ //unwrappered bean itself.
+ Object arg = args.get(i);
+ Object argToTest = arg;
+ if(arg instanceof UnwrapperedBeanHolder)
+ argToTest = ((UnwrapperedBeanHolder)arg).unwrapperedBean;
+ if (!AggregateConverter.isAssignable(argToTest, argType)) {
+ found = false;
+ break;
+ }
+ try {
+ match.add(convert(arg, mth.getGenericParameterTypes()[i]));
+ } catch (Throwable t) {
+ found = false;
+ break;
+ }
+ }
+ if (found) {
+ nmatches.put(mth, match);
+ }
+ }
+ if (nmatches.size() > 0) {
+ matches = nmatches;
+ }
+ }
+ // Find a direct match with conversion
+ if (matches.size() != 1) {
+ Map<Method, List<Object>> nmatches = new HashMap<Method, List<Object>>();
+ for (Method mth : methods) {
+ boolean found = true;
+ List<Object> match = new ArrayList<Object>();
+ for (int i = 0; i < args.size(); i++) {
+ ReifiedType argType = new GenericType(mth.getGenericParameterTypes()[i]);
+ if (types.get(i) != null && !argType.getRawClass().equals(types.get(i).getRawClass())) {
+ found = false;
+ break;
+ }
+ try {
+ Object val = convert(args.get(i), argType);
+ match.add(val);
+ } catch (Throwable t) {
+ found = false;
+ break;
+ }
+ }
+ if (found) {
+ nmatches.put(mth, match);
+ }
+ }
+ if (nmatches.size() > 0) {
+ matches = nmatches;
+ }
+ }
+ // Start reordering with assignment
+ if (matches.size() != 1 && reorderArguments && args.size() > 1) {
+ Map<Method, List<Object>> nmatches = new HashMap<Method, List<Object>>();
+ for (Method mth : methods) {
+ ArgumentMatcher matcher = new ArgumentMatcher(mth.getGenericParameterTypes(), false);
+ List<Object> match = matcher.match(args, types);
+ if (match != null) {
+ nmatches.put(mth, match);
+ }
+ }
+ if (nmatches.size() > 0) {
+ matches = nmatches;
+ }
+ }
+ // Start reordering with conversion
+ if (matches.size() != 1 && reorderArguments && args.size() > 1) {
+ Map<Method, List<Object>> nmatches = new HashMap<Method, List<Object>>();
+ for (Method mth : methods) {
+ ArgumentMatcher matcher = new ArgumentMatcher(mth.getGenericParameterTypes(), true);
+ List<Object> match = matcher.match(args, types);
+ if (match != null) {
+ nmatches.put(mth, match);
+ }
+ }
+ if (nmatches.size() > 0) {
+ matches = nmatches;
+ }
+ }
+
+ return matches;
+ }
+
+ private static List<Method> applyStaticHidingRules(Collection<Method> methods) {
+ List<Method> result = new ArrayList<Method>(methods.size());
+ for (Method m : methods) {
+ boolean toBeAdded = true;
+
+ Iterator<Method> it = result.iterator();
+ inner: while (it.hasNext()) {
+ Method other = it.next();
+ if (hasIdenticalParameters(m, other)) {
+ Class<?> mClass = m.getDeclaringClass();
+ Class<?> otherClass = other.getDeclaringClass();
+
+ if (mClass.isAssignableFrom(otherClass)) {
+ toBeAdded = false;
+ break inner;
+ } else if (otherClass.isAssignableFrom(mClass)) {
+ it.remove();
+ }
+ }
+ }
+
+ if (toBeAdded) result.add(m);
+ }
+
+ return result;
+ }
+
+ private static boolean hasIdenticalParameters(Method one, Method two) {
+ Class<?>[] oneTypes = one.getParameterTypes();
+ Class<?>[] twoTypes = two.getParameterTypes();
+
+ if (oneTypes.length != twoTypes.length) return false;
+
+ for (int i=0; i<oneTypes.length; i++) {
+ if (!oneTypes[i].equals(twoTypes[i])) return false;
+ }
+
+ return true;
+ }
+
+ private Map<Constructor, List<Object>> findMatchingConstructors(Class type, List<Object> args, List<ReifiedType> types) {
+ Map<Constructor, List<Object>> matches = new HashMap<Constructor, List<Object>>();
+ // Get constructors
+ List<Constructor> constructors = new ArrayList<Constructor>(Arrays.asList(type.getConstructors()));
+ // Discard any signature with wrong cardinality
+ for (Iterator<Constructor> it = constructors.iterator(); it.hasNext();) {
+ if (it.next().getParameterTypes().length != args.size()) {
+ it.remove();
+ }
+ }
+ // Find a direct match with assignment
+ if (matches.size() != 1) {
+ Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>();
+ for (Constructor cns : constructors) {
+ boolean found = true;
+ List<Object> match = new ArrayList<Object>();
+ for (int i = 0; i < args.size(); i++) {
+ ReifiedType argType = new GenericType(cns.getGenericParameterTypes()[i]);
+ if (types.get(i) != null && !argType.getRawClass().equals(types.get(i).getRawClass())) {
+ found = false;
+ break;
+ }
+ //If the arg is an Unwrappered bean then we need to do the assignment check against the
+ //unwrappered bean itself.
+ Object arg = args.get(i);
+ Object argToTest = arg;
+ if(arg instanceof UnwrapperedBeanHolder)
+ argToTest = ((UnwrapperedBeanHolder)arg).unwrapperedBean;
+ if (!AggregateConverter.isAssignable(argToTest, argType)) {
+ found = false;
+ break;
+ }
+ try {
+ match.add(convert(arg, cns.getGenericParameterTypes()[i]));
+ } catch (Throwable t) {
+ found = false;
+ break;
+ }
+ }
+ if (found) {
+ nmatches.put(cns, match);
+ }
+ }
+ if (nmatches.size() > 0) {
+ matches = nmatches;
+ }
+ }
+ // Find a direct match with conversion
+ if (matches.size() != 1) {
+ Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>();
+ for (Constructor cns : constructors) {
+ boolean found = true;
+ List<Object> match = new ArrayList<Object>();
+ for (int i = 0; i < args.size(); i++) {
+ ReifiedType argType = new GenericType(cns.getGenericParameterTypes()[i]);
+ if (types.get(i) != null && !argType.getRawClass().equals(types.get(i).getRawClass())) {
+ found = false;
+ break;
+ }
+ try {
+ Object val = convert(args.get(i), argType);
+ match.add(val);
+ } catch (Throwable t) {
+ found = false;
+ break;
+ }
+ }
+ if (found) {
+ nmatches.put(cns, match);
+ }
+ }
+ if (nmatches.size() > 0) {
+ matches = nmatches;
+ }
+ }
+ // Start reordering with assignment
+ if (matches.size() != 1 && reorderArguments && arguments.size() > 1) {
+ Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>();
+ for (Constructor cns : constructors) {
+ ArgumentMatcher matcher = new ArgumentMatcher(cns.getGenericParameterTypes(), false);
+ List<Object> match = matcher.match(args, types);
+ if (match != null) {
+ nmatches.put(cns, match);
+ }
+ }
+ if (nmatches.size() > 0) {
+ matches = nmatches;
+ }
+ }
+ // Start reordering with conversion
+ if (matches.size() != 1 && reorderArguments && arguments.size() > 1) {
+ Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>();
+ for (Constructor cns : constructors) {
+ ArgumentMatcher matcher = new ArgumentMatcher(cns.getGenericParameterTypes(), true);
+ List<Object> match = matcher.match(args, types);
+ if (match != null) {
+ nmatches.put(cns, match);
+ }
+ }
+ if (nmatches.size() > 0) {
+ matches = nmatches;
+ }
+ }
+ return matches;
+ }
+
+ /**
+ * Returns init method (if any). Throws exception if the init-method was set explicitly on the bean
+ * and the method is not found on the instance.
+ */
+ protected Method getInitMethod(Object instance) throws ComponentDefinitionException {
+ Method method = null;
+ if (initMethod != null && initMethod.length() > 0) {
+ method = ReflectionUtils.getLifecycleMethod(instance.getClass(), initMethod);
+ if (method == null) {
+ throw new ComponentDefinitionException("Component '" + getName() + "' does not have init-method: " + initMethod);
+ }
+ }
+ return method;
+ }
+
+ /**
+ * Returns destroy method (if any). Throws exception if the destroy-method was set explicitly on the bean
+ * and the method is not found on the instance.
+ */
+ public Method getDestroyMethod(Object instance) throws ComponentDefinitionException {
+ Method method = null;
+ if (instance != null && destroyMethod != null && destroyMethod.length() > 0) {
+ method = ReflectionUtils.getLifecycleMethod(instance.getClass(), destroyMethod);
+ if (method == null) {
+ throw new ComponentDefinitionException("Component '" + getName() + "' does not have destroy-method: " + destroyMethod);
+ }
+ }
+ return method;
+ }
+
+ /**
+ * Small helper class, to construct a chain of BeanCreators.
+ * <br>
+ * Each bean creator in the chain will return a bean that has been
+ * processed by every BeanProcessor in the chain before it.
+ */
+ private static class BeanCreatorChain implements BeanProcessor.BeanCreator {
+ public enum ChainType{Before,After};
+ private final BeanProcessor.BeanCreator parentBeanCreator;
+ private final BeanProcessor parentBeanProcessor;
+ private final BeanMetadata beanData;
+ private final String beanName;
+ private final ChainType when;
+ public BeanCreatorChain(BeanProcessor.BeanCreator parentBeanCreator,
+ BeanProcessor parentBeanProcessor,
+ BeanMetadata beanData,
+ String beanName,
+ ChainType when){
+ this.parentBeanCreator = parentBeanCreator;
+ this.parentBeanProcessor = parentBeanProcessor;
+ this.beanData = beanData;
+ this.beanName = beanName;
+ this.when = when;
+ }
+
+ public Object getBean() {
+ Object previousBean = parentBeanCreator.getBean();
+ Object processed = null;
+ switch(when){
+ case Before :
+ processed = parentBeanProcessor.beforeInit(previousBean, beanName, parentBeanCreator, beanData);
+ break;
+ case After:
+ processed = parentBeanProcessor.afterInit(previousBean, beanName, parentBeanCreator, beanData);
+ break;
+ }
+ return processed;
+ }
+ }
+
+ private Object runBeanProcPreInit(Object obj){
+ String beanName = getName();
+ BeanMetadata beanData = (BeanMetadata) blueprintContainer
+ .getComponentDefinitionRegistry().getComponentDefinition(beanName);
+ List<BeanProcessor> processors = blueprintContainer.getProcessors(BeanProcessor.class);
+
+ //The start link of the chain, that provides the
+ //original, unprocessed bean to the head of the chain.
+ BeanProcessor.BeanCreator initialBeanCreator = new BeanProcessor.BeanCreator() {
+ public Object getBean() {
+ Object obj = getInstance();
+ //getinit, getdestroy, addpartial object don't need calling again.
+ //however, property injection does.
+ setProperties(obj);
+ return obj;
+ }
+ };
+
+ BeanProcessor.BeanCreator currentCreator = initialBeanCreator;
+ for(BeanProcessor processor : processors){
+ obj = processor.beforeInit(obj, getName(), currentCreator, beanData);
+ currentCreator = new BeanCreatorChain(currentCreator, processor, beanData, beanName, BeanCreatorChain.ChainType.Before);
+ }
+ return obj;
+ }
+
+ private void runBeanProcInit(Method initMethod, Object obj){
+ // call init method
+ if (initMethod != null) {
+ try {
+ invoke(initMethod, obj, (Object[]) null);
+ } catch (Throwable t) {
+ throw new ComponentDefinitionException("Unable to intialize bean " + getName(), getRealCause(t));
+ }
+ }
+ }
+
+ private Object runBeanProcPostInit(Object obj){
+ String beanName = getName();
+ BeanMetadata beanData = (BeanMetadata) blueprintContainer
+ .getComponentDefinitionRegistry().getComponentDefinition(beanName);
+ List<BeanProcessor> processors = blueprintContainer.getProcessors(BeanProcessor.class);
+
+ //The start link of the chain, that provides the
+ //original, unprocessed bean to the head of the chain.
+ BeanProcessor.BeanCreator initialBeanCreator = new BeanProcessor.BeanCreator() {
+ public Object getBean() {
+ Object obj = getInstance();
+ //getinit, getdestroy, addpartial object don't need calling again.
+ //however, property injection does.
+ setProperties(obj);
+ //as this is the post init chain, new beans need to go thru
+ //the pre-init chain, and then have init called, before
+ //being passed along the post-init chain.
+ obj = runBeanProcPreInit(obj);
+ runBeanProcInit(getInitMethod(obj), obj);
+ return obj;
+ }
+ };
+
+ BeanProcessor.BeanCreator currentCreator = initialBeanCreator;
+ for(BeanProcessor processor : processors){
+ obj = processor.afterInit(obj, getName(), currentCreator, beanData);
+ currentCreator = new BeanCreatorChain(currentCreator, processor, beanData, beanName, BeanCreatorChain.ChainType.After);
+ }
+ return obj;
+ }
+
+ private Object addInterceptors(final Object original, Collection<Class<?>> requiredInterfaces)
+ throws ComponentDefinitionException {
+
+ Object intercepted = null;
+ if(requiredInterfaces.isEmpty())
+ requiredInterfaces.add(original.getClass());
+
+ ComponentDefinitionRegistry reg = blueprintContainer
+ .getComponentDefinitionRegistry();
+ List<Interceptor> interceptors = reg.getInterceptors(interceptorLookupKey);
+ if (interceptors != null && interceptors.size() > 0) {
+ /* BLUEPRINT-NOOSGI
+ try {
+ Bundle b = FrameworkUtil.getBundle(original.getClass());
+ if (b == null) {
+ // we have a class from the framework parent, so use our bundle for proxying.
+ b = blueprintContainer.getBundleContext().getBundle();
+ }
+ intercepted = blueprintContainer.getProxyManager().createInterceptingProxy(b,
+ requiredInterfaces, original, new Collaborator(interceptorLookupKey, interceptors));
+ } catch (org.apache.aries.proxy.UnableToProxyException e) {
+ Bundle b = blueprintContainer.getBundleContext().getBundle();
+ throw new ComponentDefinitionException("Unable to create proxy for bean " + name + " in bundle " + b.getSymbolicName() + " version " + b.getVersion(), e);
+ }
+ */
+ throw new ComponentDefinitionException("Unable to create proxy for bean " + name + ". Not supported in blueprint-noosgi");
+ } else {
+ intercepted = original;
+ }
+ return intercepted;
+ }
+
+ @Override
+ protected Object internalCreate() throws ComponentDefinitionException {
+ /* BLUEPRINT-NOOSGI
+ if (factory instanceof ReferenceRecipe) {
+ ReferenceRecipe rr = (ReferenceRecipe) factory;
+ if (rr.getProxyChildBeanClasses() != null) {
+ return createProxyBean(rr);
+ }
+ }
+ */
+ return new UnwrapperedBeanHolder(internalCreate2(), this);
+ }
+
+ /* BLUEPRINT-NOOSGI
+ private Object createProxyBean(ReferenceRecipe rr) {
+ try {
+ VoidableCallable vc = new VoidableCallable();
+ rr.addVoidableChild(vc);
+ return blueprintContainer.getProxyManager().createDelegatingProxy(
+ blueprintContainer.getBundleContext().getBundle(), rr.getProxyChildBeanClasses(),
+ vc, vc.call());
+ } catch (UnableToProxyException e) {
+ throw new ComponentDefinitionException(e);
+ }
+ }
+ */
+
+ private Object internalCreate2() throws ComponentDefinitionException {
+
+ instantiateExplicitDependencies();
+
+ Object obj = getInstance();
+
+ // check for init lifecycle method (if any)
+ Method initMethod = getInitMethod(obj);
+
+ // check for destroy lifecycle method (if any)
+ getDestroyMethod(obj);
+
+ // Add partially created object to the container
+// if (initMethod == null) {
+ addPartialObject(obj);
+// }
+
+ // inject properties
+ setProperties(obj);
+
+ obj = runBeanProcPreInit(obj);
+
+ runBeanProcInit(initMethod, obj);
+
+ obj = runBeanProcPostInit(obj);
+
+ //Replaced by calling wrap on the UnwrapperedBeanHolder
+// obj = addInterceptors(obj);
+
+ return obj;
+ }
+
+ static Object wrap(UnwrapperedBeanHolder holder, Collection<Class<?>> requiredViews) {
+ return holder.recipe.addInterceptors(holder.unwrapperedBean, requiredViews);
+ }
+
+ static Object wrap(UnwrapperedBeanHolder holder, Class<?> requiredView) {
+ if(requiredView == Object.class) {
+ //We don't know what we need so we have to do everything
+ return holder.recipe.addInterceptors(holder.unwrapperedBean, new ArrayList<Class<?>>(1));
+ } else {
+ return holder.recipe.addInterceptors(holder.unwrapperedBean, ProxyUtils.asList(requiredView));
+ }
+ }
+
+
+ @Override
+ public void destroy(Object obj) {
+ if (!(obj instanceof UnwrapperedBeanHolder)) {
+ LOGGER.warn("Object to be destroyed is not an instance of UnwrapperedBeanHolder, type: " + obj);
+ return;
+ }
+
+ obj = ((UnwrapperedBeanHolder)obj).unwrapperedBean;
+
+ for (BeanProcessor processor : blueprintContainer.getProcessors(BeanProcessor.class)) {
+ processor.beforeDestroy(obj, getName());
+ }
+ try {
+ Method method = getDestroyMethod(obj);
+ if (method != null) {
+ invoke(method, obj, (Object[]) null);
+ }
+ } catch (ComponentDefinitionException e) {
+ // This exception occurs if the destroy method does not exist, so we just output the exception message.
+ LOGGER.error(e.getMessage());
+ } catch (InvocationTargetException ite) {
+ /* BLUEPRINT-OSGI
+ Throwable t = ite.getTargetException();
+ BundleContext ctx = blueprintContainer.getBundleContext();
+ Bundle b = ctx.getBundle();
+ String bundleIdentifier = b.getSymbolicName() + '/' + b.getVersion();
+ LOGGER.error("The blueprint bean " + getName() + " in bundle " + bundleIdentifier + " incorrectly threw an exception from its destroy method.", t);
+ */
+ Throwable t = ite.getTargetException();
+ LOGGER.error("The blueprint bean " + getName() + " in incorrectly threw an exception from its destroy method.", t);
+ } catch (Exception e) {
+ /* BLUEPRINT-OSGI
+ BundleContext ctx = blueprintContainer.getBundleContext();
+ Bundle b = ctx.getBundle();
+ String bundleIdentifier = b.getSymbolicName() + '/' + b.getVersion();
+ LOGGER.error("An exception occurred while calling the destroy method of the blueprint bean " + getName() + " in bundle " + bundleIdentifier + ".", getRealCause(e));
+ */
+ LOGGER.error("An exception occurred while calling the destroy method of the blueprint bean " + getName() + ".", getRealCause(e));
+ }
+ for (BeanProcessor processor : blueprintContainer.getProcessors(BeanProcessor.class)) {
+ processor.afterDestroy(obj, getName());
+ }
+ }
+
+ public void setProperties(Object instance) throws ComponentDefinitionException {
+ // clone the properties so they can be used again
+ Map<String,Object> propertyValues = new LinkedHashMap<String,Object>(properties);
+ setProperties(propertyValues, instance, instance.getClass());
+ }
+
+ public Class getType() {
+ if (type instanceof Class) {
+ return (Class) type;
+ } else if (type instanceof String) {
+ return loadClass((String) type);
+ } else {
+ return null;
+ }
+ }
+
+ private void setProperties(Map<String, Object> propertyValues, Object instance, Class clazz) {
+ // set remaining properties
+ for (Map.Entry<String, Object> entry : propertyValues.entrySet()) {
+ String propertyName = entry.getKey();
+ Object propertyValue = entry.getValue();
+
+ setProperty(instance, clazz, propertyName, propertyValue);
+ }
+
+ }
+
+ private void setProperty(Object instance, Class clazz, String propertyName, Object propertyValue) {
+ String[] names = propertyName.split("\\.");
+ for (int i = 0; i < names.length - 1; i++) {
+ PropertyDescriptor pd = getPropertyDescriptor(clazz, names[i]);
+ if (pd.allowsGet()) {
+ try {
+ instance = pd.get(instance, blueprintContainer);
+ } catch (Exception e) {
+ throw new ComponentDefinitionException("Error getting property: " + names[i] + " on bean " + getName() + " when setting property " + propertyName + " on class " + clazz.getName(), getRealCause(e));
+ }
+ if (instance == null) {
+ throw new ComponentDefinitionException("Error setting compound property " + propertyName + " on bean " + getName() + ". Property " + names[i] + " is null");
+ }
+ clazz = instance.getClass();
+ } else {
+ throw new ComponentDefinitionException("No getter for " + names[i] + " property on bean " + getName() + " when setting property " + propertyName + " on class " + clazz.getName());
+ }
+ }
+
+ // Instantiate value
+ if (propertyValue instanceof Recipe) {
+ propertyValue = ((Recipe) propertyValue).create();
+ }
+
+ final PropertyDescriptor pd = getPropertyDescriptor(clazz, names[names.length - 1]);
+ if (pd.allowsSet()) {
+ try {
+ pd.set(instance, propertyValue, blueprintContainer);
+ } catch (Exception e) {
+ throw new ComponentDefinitionException("Error setting property: " + pd, getRealCause(e));
+ }
+ } else {
+ throw new ComponentDefinitionException("No setter for " + names[names.length - 1] + " property");
+ }
+ }
+
+ private ReflectionUtils.PropertyDescriptor getPropertyDescriptor(Class<?> clazz, String name) {
+ for (ReflectionUtils.PropertyDescriptor pd : ReflectionUtils.getPropertyDescriptors(clazz, allowsFieldInjection)) {
+ if (pd.getName().equals(name)) {
+ return pd;
+ }
+ }
+ throw new ComponentDefinitionException("Unable to find property descriptor " + name + " on class " + clazz.getName());
+ }
+
+ private Object invoke(Method method, Object instance, Object... args) throws Exception {
+ return ReflectionUtils.invoke(blueprintContainer.getAccessControlContext(), method, instance, args);
+ }
+
+ private Object newInstance(Constructor constructor, Object... args) throws Exception {
+ return ReflectionUtils.newInstance(blueprintContainer.getAccessControlContext(), constructor, args);
+ }
+
+ private static Object UNMATCHED = new Object();
+
+ private class ArgumentMatcher {
+
+ private final List<TypeEntry> entries;
+ private final boolean convert;
+
+ public ArgumentMatcher(Type[] types, boolean convert) {
+ entries = new ArrayList<TypeEntry>();
+ for (Type type : types) {
+ entries.add(new TypeEntry(new GenericType(type)));
+ }
+ this.convert = convert;
+ }
+
+ public List<Object> match(List<Object> arguments, List<ReifiedType> forcedTypes) {
+ if (find(arguments, forcedTypes)) {
+ return getArguments();
+ }
+ return null;
+ }
+
+ private List<Object> getArguments() {
+ List<Object> list = new ArrayList<Object>();
+ for (TypeEntry entry : entries) {
+ if (entry.argument == UNMATCHED) {
+ throw new RuntimeException("There are unmatched types");
+ } else {
+ list.add(entry.argument);
+ }
+ }
+ return list;
+ }
+
+ private boolean find(List<Object> arguments, List<ReifiedType> forcedTypes) {
+ if (entries.size() == arguments.size()) {
+ boolean matched = true;
+ for (int i = 0; i < arguments.size() && matched; i++) {
+ matched = find(arguments.get(i), forcedTypes.get(i));
+ }
+ return matched;
+ }
+ return false;
+ }
+
+ private boolean find(Object arg, ReifiedType forcedType) {
+ for (TypeEntry entry : entries) {
+ Object val = arg;
+ if (entry.argument != UNMATCHED) {
+ continue;
+ }
+ if (forcedType != null) {
+ if (!forcedType.equals(entry.type)) {
+ continue;
+ }
+ } else if (arg != null) {
+ if (convert) {
+
+ if(canConvert(arg, entry.type)) {
+ try {
+ val = convert(arg, entry.type);
+ } catch (Exception e) {
+ throw new ComponentDefinitionException(e);
+ }
+ } else {
+ continue;
+ }
+ } else {
+ UnwrapperedBeanHolder holder = null;
+ if(arg instanceof UnwrapperedBeanHolder) {
+ holder = (UnwrapperedBeanHolder)arg;
+ arg = holder.unwrapperedBean;
+ }
+ if (!AggregateConverter.isAssignable(arg, entry.type)) {
+ continue;
+ } else if (holder != null) {
+ val = wrap(holder, entry.type.getRawClass());
+ }
+ }
+ }
+ entry.argument = val;
+ return true;
+ }
+ return false;
+ }
+
+ }
+
+ private static class TypeEntry {
+
+ private final ReifiedType type;
+ private Object argument;
+
+ public TypeEntry(ReifiedType type) {
+ this.type = type;
+ this.argument = UNMATCHED;
+ }
+
+ }
+
+}
diff --git a/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java b/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
new file mode 100644
index 0000000..eec1ccd
--- /dev/null
+++ b/src/main/java/org/apache/aries/blueprint/container/BlueprintContainerImpl.java
@@ -0,0 +1,351 @@
+/*
+ * 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.aries.blueprint.container;
+
+import org.apache.aries.blueprint.ComponentDefinitionRegistryProcessor;
+import org.apache.aries.blueprint.ExtendedBeanMetadata;
+import org.apache.aries.blueprint.Processor;
+import org.apache.aries.blueprint.di.Recipe;
+import org.apache.aries.blueprint.di.Repository;
+import org.apache.aries.blueprint.parser.ComponentDefinitionRegistryImpl;
+import org.apache.aries.blueprint.parser.Parser;
+import org.apache.aries.blueprint.reflect.MetadataUtil;
+import org.apache.aries.blueprint.reflect.PassThroughMetadataImpl;
+import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
+import org.osgi.service.blueprint.container.ComponentDefinitionException;
+import org.osgi.service.blueprint.container.Converter;
+import org.osgi.service.blueprint.container.NoSuchComponentException;
+import org.osgi.service.blueprint.reflect.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URI;
+import java.net.URL;
+import java.security.AccessControlContext;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public class BlueprintContainerImpl implements ExtendedBlueprintContainer {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(BlueprintContainerImpl.class);
+
+ private final ClassLoader loader;
+ private final List<URL> resources;
+ private final AggregateConverter converter;
+ private final ComponentDefinitionRegistryImpl componentDefinitionRegistry;
+ private final AtomicBoolean destroyed = new AtomicBoolean(false);
+ private final IdSpace tempRecipeIdSpace = new IdSpace();
+ private BlueprintRepository repository;
+ private List<Processor> processors = new ArrayList<Processor>();
+ private Map<String, String> properties;
+
+ public BlueprintContainerImpl(ClassLoader loader, List<URL> resources) throws Exception {
+ this(loader, resources, null, true);
+ }
+
+ public BlueprintContainerImpl(ClassLoader loader, List<URL> resources, boolean init) throws Exception {
+ this(loader, resources, null, init);
+ }
+
+ public BlueprintContainerImpl(ClassLoader loader, List<URL> resources, Map<String, String> properties, boolean init) throws Exception {
+ this.loader = loader;
+ this.converter = new AggregateConverter(this);
+ this.componentDefinitionRegistry = new ComponentDefinitionRegistryImpl();
+ this.resources = resources;
+ this.properties = properties;
+ if (init) {
+ init();
+ }
+ }
+
+ public String getProperty(String key) {
+ if (properties != null && properties.containsKey(key)) {
+ return properties.get(key);
+ }
+ return System.getProperty(key);
+ }
+
+ public void init() throws Exception {
+ // Parse xml resources
+ Parser parser = new Parser();
+ parser.parse(getResources());
+ // Create handler set
+ SimpleNamespaceHandlerSet handlerSet = new SimpleNamespaceHandlerSet();
+ // Check namespaces
+ Set<URI> namespaces = parser.getNamespaces();
+ Set<URI> unsupported = new LinkedHashSet<URI>();
+ for (URI ns : namespaces) {
+ if (!handlerSet.getNamespaces().contains(ns)) {
+ unsupported.add(ns);
+ }
+ }
+ if (unsupported.size() > 0) {
+ throw new IllegalArgumentException("Unsupported namespaces: " + unsupported.toString());
+ }
+ // Add predefined beans
+ componentDefinitionRegistry.registerComponentDefinition(new PassThroughMetadataImpl("blueprintContainer", this));
+ // Validate
+ parser.validate(handlerSet.getSchema());
+ // Populate
+ parser.populate(handlerSet, componentDefinitionRegistry);
+ // Create repository
+ repository = new NoOsgiRecipeBuilder(this, tempRecipeIdSpace).createRepository();
+ // Processors handling
+ processTypeConverters();
+ processProcessors();
+ // Instantiate eager singletons
+ instantiateEagerComponents();
+ }
+
+ public void destroy() {
+ repository.destroy();
+ }
+
+ public List<URL> getResources() {
+ return resources;
+ }
+
+ public Converter getConverter() {
+ return converter;
+ }
+
+ public Class loadClass(String name) throws ClassNotFoundException {
+ return loader.loadClass(name);
+ }
+
+ public URL getResource(String name) {
+ return loader.getResource(name);
+ }
+
+ public AccessControlContext getAccessControlContext() {
+ return null;
+ }
+
+ public ComponentDefinitionRegistryImpl getComponentDefinitionRegistry() {
+ return componentDefinitionRegistry;
+ }
+
+ public <T extends Processor> List<T> getProcessors(Class<T> clazz) {
+ List<T> p = new ArrayList<T>();
+ for (Processor processor : processors) {
+ if (clazz.isInstance(processor)) {
+ p.add(clazz.cast(processor));
+ }
+ }
+ return p;
+ }
+
+ public Set<String> getComponentIds() {
+ return new LinkedHashSet<String>(componentDefinitionRegistry.getComponentDefinitionNames());
+ }
+
+ public Object getComponentInstance(String id) {
+ if (repository == null || destroyed.get()) {
+ throw new NoSuchComponentException(id);
+ }
+ try {
+ LOGGER.debug("Instantiating component {}", id);
+ return repository.create(id);
+ } catch (NoSuchComponentException e) {
+ throw e;
+ } catch (ComponentDefinitionException e) {
+ throw e;
+ } catch (Throwable t) {
+ throw new ComponentDefinitionException("Cound not create component instance for " + id, t);
+ }
+ }
+
+ public ComponentMetadata getComponentMetadata(String id) {
+ ComponentMetadata metadata = componentDefinitionRegistry.getComponentDefinition(id);
+ if (metadata == null) {
+ throw new NoSuchComponentException(id);
+ }
+ return metadata;
+ }
+
+ public <T extends ComponentMetadata> Collection<T> getMetadata(Class<T> clazz) {
+ Collection<T> metadatas = new ArrayList<T>();
+ for (String name : componentDefinitionRegistry.getComponentDefinitionNames()) {
+ ComponentMetadata component = componentDefinitionRegistry.getComponentDefinition(name);
+ getMetadata(clazz, component, metadatas);
+ }
+ metadatas = Collections.unmodifiableCollection(metadatas);
+ return metadatas;
+ }
+
+ public BlueprintRepository getRepository() {
+ return repository;
+ }
+
+ private <T extends ComponentMetadata> void getMetadata(Class<T> clazz, Metadata component, Collection<T> metadatas) {
+ if (component == null) {
+ return;
+ }
+ if (clazz.isInstance(component)) {
+ metadatas.add(clazz.cast(component));
+ }
+ if (component instanceof BeanMetadata) {
+ getMetadata(clazz, ((BeanMetadata) component).getFactoryComponent(), metadatas);
+ for (BeanArgument arg : ((BeanMetadata) component).getArguments()) {
+ getMetadata(clazz, arg.getValue(), metadatas);
+ }
+ for (BeanProperty prop : ((BeanMetadata) component).getProperties()) {
+ getMetadata(clazz, prop.getValue(), metadatas);
+ }
+ }
+ if (component instanceof CollectionMetadata) {
+ for (Metadata m : ((CollectionMetadata) component).getValues()) {
+ getMetadata(clazz, m, metadatas);
+ }
+ }
+ if (component instanceof MapMetadata) {
+ for (MapEntry m : ((MapMetadata) component).getEntries()) {
+ getMetadata(clazz, m.getKey(), metadatas);
+ getMetadata(clazz, m.getValue(), metadatas);
+ }
+ }
+ if (component instanceof PropsMetadata) {
+ for (MapEntry m : ((PropsMetadata) component).getEntries()) {
+ getMetadata(clazz, m.getKey(), metadatas);
+ getMetadata(clazz, m.getValue(), metadatas);
+ }
+ }
+ if (component instanceof ServiceReferenceMetadata) {
+ for (ReferenceListener l : ((ServiceReferenceMetadata) component).getReferenceListeners()) {
+ getMetadata(clazz, l.getListenerComponent(), metadatas);
+ }
+ }
+ if (component instanceof ServiceMetadata) {
+ getMetadata(clazz, ((ServiceMetadata) component).getServiceComponent(), metadatas);
+ for (MapEntry m : ((ServiceMetadata) component).getServiceProperties()) {
+ getMetadata(clazz, m.getKey(), metadatas);
+ getMetadata(clazz, m.getValue(), metadatas);
+ }
+ for (RegistrationListener l : ((ServiceMetadata) component).getRegistrationListeners()) {
+ getMetadata(clazz, l.getListenerComponent(), metadatas);
+ }
+ }
+ }
+
+ private void processTypeConverters() throws Exception {
+ List<String> typeConverters = new ArrayList<String>();
+ for (Target target : componentDefinitionRegistry.getTypeConverters()) {
+ if (target instanceof ComponentMetadata) {
+ typeConverters.add(((ComponentMetadata) target).getId());
+ } else if (target instanceof RefMetadata) {
+ typeConverters.add(((RefMetadata) target).getComponentId());
+ } else {
+ throw new ComponentDefinitionException("Unexpected metadata for type converter: " + target);
+ }
+ }
+
+ Map<String, Object> objects = repository.createAll(typeConverters, Arrays.<Class<?>>asList(Converter.class));
+ for (String name : typeConverters) {
+ Object obj = objects.get(name);
+ if (obj instanceof Converter) {
+ converter.registerConverter((Converter) obj);
+ } else {
+ throw new ComponentDefinitionException("Type converter " + obj + " does not implement the " + Converter.class.getName() + " interface");
+ }
+ }
+ }
+
+ private void processProcessors() throws Exception {
+ // Instantiate ComponentDefinitionRegistryProcessor and BeanProcessor
+ for (BeanMetadata bean : getMetadata(BeanMetadata.class)) {
+ if (bean instanceof ExtendedBeanMetadata && !((ExtendedBeanMetadata) bean).isProcessor()) {
+ continue;
+ }
+
+ Class clazz = null;
+ if (bean instanceof ExtendedBeanMetadata) {
+ clazz = ((ExtendedBeanMetadata) bean).getRuntimeClass();
+ }
+ if (clazz == null && bean.getClassName() != null) {
+ clazz = loadClass(bean.getClassName());
+ }
+ if (clazz == null) {
+ continue;
+ }
+
+ if (ComponentDefinitionRegistryProcessor.class.isAssignableFrom(clazz)) {
+ Object obj = repository.create(bean.getId(), Arrays.<Class<?>>asList(ComponentDefinitionRegistryProcessor.class));
+ ((ComponentDefinitionRegistryProcessor) obj).process(componentDefinitionRegistry);
+ } else if (Processor.class.isAssignableFrom(clazz)) {
+ Object obj = repository.create(bean.getId(), Arrays.<Class<?>>asList(Processor.class));
+ this.processors.add((Processor) obj);
+ } else {
+ continue;
+ }
+ updateUninstantiatedRecipes();
+ }
+ }
+ private void updateUninstantiatedRecipes() {
+ Repository tmpRepo = new NoOsgiRecipeBuilder(this, tempRecipeIdSpace).createRepository();
+
+ LOGGER.debug("Updating blueprint repository");
+
+ for (String name : repository.getNames()) {
+ if (repository.getInstance(name) == null) {
+ LOGGER.debug("Removing uninstantiated recipe {}", new Object[] { name });
+ repository.removeRecipe(name);
+ } else {
+ LOGGER.debug("Recipe {} is already instantiated", new Object[] { name });
+ }
+ }
+
+ for (String name : tmpRepo.getNames()) {
+ if (repository.getInstance(name) == null) {
+ LOGGER.debug("Adding new recipe {}", new Object[] { name });
+ Recipe r = tmpRepo.getRecipe(name);
+ if (r != null) {
+ repository.putRecipe(name, r);
+ }
+ } else {
+ LOGGER.debug("Recipe {} is already instantiated and cannot be updated", new Object[] { name });
+ }
+ }
+ }
+
+ protected void instantiateEagerComponents() {
+ List<String> components = new ArrayList<String>();
+ for (String name : componentDefinitionRegistry.getComponentDefinitionNames()) {
+ ComponentMetadata component = componentDefinitionRegistry.getComponentDefinition(name);
+ boolean eager = component.getActivation() == ComponentMetadata.ACTIVATION_EAGER;
+ if (component instanceof BeanMetadata) {
+ BeanMetadata local = (BeanMetadata) component;
+ eager &= MetadataUtil.isSingletonScope(local);
+ }
+ if (eager) {
+ components.add(name);
+ }
+ }
+ LOGGER.debug("Instantiating components: {}", components);
+ try {
+ repository.createAll(components);
+ } catch (ComponentDefinitionException e) {
+ throw e;
+ } catch (Throwable t) {
+ throw new ComponentDefinitionException("Unable to instantiate components", t);
+ }
+ }
+
+
+
+}
diff --git a/src/main/java/org/apache/aries/blueprint/container/GenericType.java b/src/main/java/org/apache/aries/blueprint/container/GenericType.java
new file mode 100644
index 0000000..30ef440
--- /dev/null
+++ b/src/main/java/org/apache/aries/blueprint/container/GenericType.java
@@ -0,0 +1,230 @@
+/**
+ *
+ * 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.aries.blueprint.container;
+
+import org.apache.aries.blueprint.di.ExecutionContext;
+import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
+import org.osgi.service.blueprint.container.ReifiedType;
+
+import java.lang.reflect.*;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * XXXX: Currently, in case of arrays getActualTypeArgument(0) returns something similar to what
+ * Class.getComponentType() does for arrays. I don't think this is quite right since getActualTypeArgument()
+ * should return the given parameterized type not the component type. Need to check this behavior with the spec.
+ */
+public class GenericType extends ReifiedType {
+
+ private static final GenericType[] EMPTY = new GenericType[0];
+
+ private static final Map<String, Class> primitiveClasses = new HashMap<String, Class>();
+
+ static {
+ primitiveClasses.put("int", int.class);
+ primitiveClasses.put("short", short.class);
+ primitiveClasses.put("long", long.class);
+ primitiveClasses.put("byte", byte.class);
+ primitiveClasses.put("char", char.class);
+ primitiveClasses.put("float", float.class);
+ primitiveClasses.put("double", double.class);
+ primitiveClasses.put("boolean", boolean.class);
+ }
+
+ private GenericType[] parameters;
+
+ public GenericType(Type type) {
+ this(getConcreteClass(type), parametersOf(type));
+ }
+
+ public GenericType(Class clazz, GenericType... parameters) {
+ super(clazz);
+ this.parameters = parameters;
+ }
+
+ public static GenericType parse(String rawType, final Object loader) throws ClassNotFoundException, IllegalArgumentException {
+ final String type = rawType.trim();
+ // Check if this is an array
+ if (type.endsWith("[]")) {
+ GenericType t = parse(type.substring(0, type.length() - 2), loader);
+ return new GenericType(Array.newInstance(t.getRawClass(), 0).getClass(), t);
+ }
+ // Check if this is a generic
+ int genericIndex = type.indexOf('<');
+ if (genericIndex > 0) {
+ if (!type.endsWith(">")) {
+ throw new IllegalArgumentException("Can not load type: " + type);
+ }
+ GenericType base = parse(type.substring(0, genericIndex), loader);
+ String[] params = type.substring(genericIndex + 1, type.length() - 1).split(",");
+ GenericType[] types = new GenericType[params.length];
+ for (int i = 0; i < params.length; i++) {
+ types[i] = parse(params[i], loader);
+ }
+ return new GenericType(base.getRawClass(), types);
+ }
+ // Primitive
+ if (primitiveClasses.containsKey(type)) {
+ return new GenericType(primitiveClasses.get(type));
+ }
+ // Class
+ if (loader instanceof ClassLoader) {
+ return new GenericType(((ClassLoader) loader).loadClass(type));
+ } else if (loader instanceof ExecutionContext) {
+ return new GenericType(((ExecutionContext) loader).loadClass(type));
+ } else if (loader instanceof ExtendedBlueprintContainer) {
+ return new GenericType(((ExtendedBlueprintContainer) loader).loadClass(type));
+ } else {
+ throw new IllegalArgumentException("Unsupported loader: " + loader);
+ }
+ }
+
+ @Override
+ public ReifiedType getActualTypeArgument(int i) {
+ if (parameters.length == 0) {
+ return super.getActualTypeArgument(i);
+ }
+ return parameters[i];
+ }
+
+ @Override
+ public int size() {
+ return parameters.length;
+ }
+
+ @Override
+ public String toString() {
+ Class cl = getRawClass();
+ if (cl.isArray()) {
+ if (parameters.length > 0) {
+ return parameters[0].toString() + "[]";
+ } else {
+ return cl.getComponentType().getName() + "[]";
+ }
+ }
+ if (parameters.length > 0) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(cl.getName());
+ sb.append("<");
+ for (int i = 0; i < parameters.length; i++) {
+ if (i > 0) {
+ sb.append(",");
+ }
+ sb.append(parameters[i].toString());
+ }
+ sb.append(">");
+ return sb.toString();
+ }
+ return cl.getName();
+ }
+
+ public boolean equals(Object object) {
+ if (!(object instanceof GenericType)) {
+ return false;
+ }
+ GenericType other = (GenericType) object;
+ if (getRawClass() != other.getRawClass()) {
+ return false;
+ }
+ if (parameters == null) {
+ return (other.parameters == null);
+ } else {
+ if (other.parameters == null) {
+ return false;
+ }
+ if (parameters.length != other.parameters.length) {
+ return false;
+ }
+ for (int i = 0; i < parameters.length; i++) {
+ if (!parameters[i].equals(other.parameters[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+ }
+
+ static GenericType[] parametersOf(Type type) {
+ if (type instanceof Class) {
+ Class clazz = (Class) type;
+ if (clazz.isArray()) {
+ GenericType t = new GenericType(clazz.getComponentType());
+ if (t.size() > 0) {
+ return new GenericType[] { t };
+ } else {
+ return EMPTY;
+ }
+ } else {
+ return EMPTY;
+ }
+ }
+ if (type instanceof ParameterizedType) {
+ ParameterizedType pt = (ParameterizedType) type;
+ Type [] parameters = pt.getActualTypeArguments();
+ GenericType[] gts = new GenericType[parameters.length];
+ for ( int i =0; i<gts.length; i++) {
+ gts[i] = new GenericType(parameters[i]);
+ }
+ return gts;
+ }
+ if (type instanceof GenericArrayType) {
+ return new GenericType[] { new GenericType(((GenericArrayType) type).getGenericComponentType()) };
+ }
+ if (type instanceof WildcardType) {
+ return EMPTY;
+ }
+ if (type instanceof TypeVariable) {
+ return EMPTY;
+ }
+ throw new IllegalStateException();
+ }
+
+ static Class<?> getConcreteClass(Type type) {
+ Type ntype = collapse(type);
+ if ( ntype instanceof Class )
+ return (Class<?>) ntype;
+
+ if ( ntype instanceof ParameterizedType )
+ return getConcreteClass(collapse(((ParameterizedType)ntype).getRawType()));
+
+ throw new RuntimeException("Unknown type " + type );
+ }
+
+ static Type collapse(Type target) {
+ if (target instanceof Class || target instanceof ParameterizedType ) {
+ return target;
+ } else if (target instanceof TypeVariable) {
+ return collapse(((TypeVariable<?>) target).getBounds()[0]);
+ } else if (target instanceof GenericArrayType) {
+ Type t = collapse(((GenericArrayType) target)
+ .getGenericComponentType());
+ while ( t instanceof ParameterizedType )
+ t = collapse(((ParameterizedType)t).getRawType());
+ return Array.newInstance((Class<?>)t, 0).getClass();
+ } else if (target instanceof WildcardType) {
+ WildcardType wct = (WildcardType) target;
+ if (wct.getLowerBounds().length == 0)
+ return collapse(wct.getUpperBounds()[0]);
+ else
+ return collapse(wct.getLowerBounds()[0]);
+ }
+ throw new RuntimeException("Huh? " + target);
+ }
+
+}
diff --git a/src/main/java/org/apache/aries/blueprint/container/NoOsgiBlueprintRepository.java b/src/main/java/org/apache/aries/blueprint/container/NoOsgiBlueprintRepository.java
new file mode 100644
index 0000000..a70ad32
--- /dev/null
+++ b/src/main/java/org/apache/aries/blueprint/container/NoOsgiBlueprintRepository.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.aries.blueprint.container;
+
+import org.apache.aries.blueprint.di.CollectionRecipe;
+import org.apache.aries.blueprint.di.IdRefRecipe;
+import org.apache.aries.blueprint.di.Recipe;
+import org.apache.aries.blueprint.di.RefRecipe;
+import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
+import org.osgi.service.blueprint.container.ComponentDefinitionException;
+
+public class NoOsgiBlueprintRepository extends BlueprintRepository {
+
+ public NoOsgiBlueprintRepository(ExtendedBlueprintContainer container) {
+ super(container);
+ }
+
+ @Override
+ public void validate() {
+ for (Recipe recipe : getAllRecipes()) {
+ // Check that references are satisfied
+ String ref = null;
+ if (recipe instanceof RefRecipe) {
+ ref = ((RefRecipe) recipe).getIdRef();
+ } else if (recipe instanceof IdRefRecipe) {
+ ref = ((IdRefRecipe) recipe).getIdRef();
+ }
+ if (ref != null && getRecipe(ref) == null) {
+ throw new ComponentDefinitionException("Unresolved ref/idref to component: " + ref);
+ }
+ }
+ }
+}
diff --git a/src/main/java/org/apache/aries/blueprint/container/NoOsgiRecipeBuilder.java b/src/main/java/org/apache/aries/blueprint/container/NoOsgiRecipeBuilder.java
new file mode 100644
index 0000000..6235f3c
--- /dev/null
+++ b/src/main/java/org/apache/aries/blueprint/container/NoOsgiRecipeBuilder.java
@@ -0,0 +1,261 @@
+/*
+ * 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.aries.blueprint.container;
+
+import org.apache.aries.blueprint.ComponentDefinitionRegistry;
+import org.apache.aries.blueprint.ExtendedBeanMetadata;
+import org.apache.aries.blueprint.PassThroughMetadata;
+import org.apache.aries.blueprint.di.*;
+import org.apache.aries.blueprint.ext.ComponentFactoryMetadata;
+import org.apache.aries.blueprint.ext.DependentComponentFactoryMetadata;
+import org.apache.aries.blueprint.reflect.MetadataUtil;
+import org.apache.aries.blueprint.utils.ServiceListener;
+import org.osgi.service.blueprint.reflect.*;
+
+import java.util.*;
+
+public class NoOsgiRecipeBuilder {
+
+ private final Set<String> names = new HashSet<String>();
+ private final BlueprintContainerImpl blueprintContainer;
+ private final ComponentDefinitionRegistry registry;
+ private final IdSpace recipeIdSpace;
+
+ public NoOsgiRecipeBuilder(BlueprintContainerImpl blueprintContainer, IdSpace recipeIdSpace) {
+ this.recipeIdSpace = recipeIdSpace;
+ this.blueprintContainer = blueprintContainer;
+ this.registry = blueprintContainer.getComponentDefinitionRegistry();
+ }
+
+ public BlueprintRepository createRepository() {
+ BlueprintRepository repository = new NoOsgiBlueprintRepository(blueprintContainer);
+ // Create component recipes
+ for (String name : registry.getComponentDefinitionNames()) {
+ ComponentMetadata component = registry.getComponentDefinition(name);
+ Recipe recipe = createRecipe(component);
+ repository.putRecipe(recipe.getName(), recipe);
+ }
+ repository.validate();
+ return repository;
+ }
+
+ public Recipe createRecipe(ComponentMetadata component) {
+
+ // Custom components should be handled before built-in ones
+ // in case we have a custom component that also implements a built-in metadata
+
+ if (component instanceof DependentComponentFactoryMetadata) {
+ return createDependentComponentFactoryMetadata((DependentComponentFactoryMetadata) component);
+ } else if (component instanceof ComponentFactoryMetadata) {
+ return createComponentFactoryMetadata((ComponentFactoryMetadata) component);
+ } else if (component instanceof BeanMetadata) {
+ return createBeanRecipe((BeanMetadata) component);
+ } else if (component instanceof ServiceMetadata) {
+ throw new IllegalArgumentException("OSGi services are not supported");
+ } else if (component instanceof ReferenceMetadata) {
+ throw new IllegalArgumentException("OSGi references are not supported");
+ } else if (component instanceof ReferenceListMetadata) {
+ throw new IllegalArgumentException("OSGi references are not supported");
+ } else if (component instanceof PassThroughMetadata) {
+ return createPassThroughRecipe((PassThroughMetadata) component);
+ } else {
+ throw new IllegalStateException("Unsupported component type " + component.getClass());
+ }
+ }
+
+ private Recipe createComponentFactoryMetadata(ComponentFactoryMetadata metadata) {
+ return new ComponentFactoryRecipe<ComponentFactoryMetadata>(
+ metadata.getId(), metadata, blueprintContainer, getDependencies(metadata));
+ }
+
+ private Recipe createDependentComponentFactoryMetadata(DependentComponentFactoryMetadata metadata) {
+ return new DependentComponentFactoryRecipe(
+ metadata.getId(), metadata, blueprintContainer, getDependencies(metadata));
+ }
+
+ private List<Recipe> getDependencies(ComponentMetadata metadata) {
+ List<Recipe> deps = new ArrayList<Recipe>();
+ for (String name : metadata.getDependsOn()) {
+ deps.add(new RefRecipe(getName(null), name));
+ }
+ return deps;
+ }
+
+ private Recipe createPassThroughRecipe(PassThroughMetadata passThroughMetadata) {
+ return new PassThroughRecipe(getName(passThroughMetadata.getId()),
+ passThroughMetadata.getObject());
+ }
+
+ private Object getBeanClass(BeanMetadata beanMetadata) {
+ if (beanMetadata instanceof ExtendedBeanMetadata) {
+ ExtendedBeanMetadata extBeanMetadata = (ExtendedBeanMetadata) beanMetadata;
+ if (extBeanMetadata.getRuntimeClass() != null) {
+ return extBeanMetadata.getRuntimeClass();
+ }
+ }
+ return beanMetadata.getClassName();
+ }
+
+ private boolean allowsFieldInjection(BeanMetadata beanMetadata) {
+ if (beanMetadata instanceof ExtendedBeanMetadata) {
+ return ((ExtendedBeanMetadata) beanMetadata).getFieldInjection();
+ }
+ return false;
+ }
+
+ private BeanRecipe createBeanRecipe(BeanMetadata beanMetadata) {
+ BeanRecipe recipe = new BeanRecipe(
+ getName(beanMetadata.getId()),
+ blueprintContainer,
+ getBeanClass(beanMetadata),
+ allowsFieldInjection(beanMetadata));
+ // Create refs for explicit dependencies
+ recipe.setExplicitDependencies(getDependencies(beanMetadata));
+ recipe.setPrototype(MetadataUtil.isPrototypeScope(beanMetadata) || MetadataUtil.isCustomScope(beanMetadata));
+ recipe.setInitMethod(beanMetadata.getInitMethod());
+ recipe.setDestroyMethod(beanMetadata.getDestroyMethod());
+ recipe.setInterceptorLookupKey(beanMetadata);
+ List<BeanArgument> beanArguments = beanMetadata.getArguments();
+ if (beanArguments != null && !beanArguments.isEmpty()) {
+ boolean hasIndex = (beanArguments.get(0).getIndex() >= 0);
+ if (hasIndex) {
+ List<BeanArgument> beanArgumentsCopy = new ArrayList<BeanArgument>(beanArguments);
+ Collections.sort(beanArgumentsCopy, MetadataUtil.BEAN_COMPARATOR);
+ beanArguments = beanArgumentsCopy;
+ }
+ List<Object> arguments = new ArrayList<Object>();
+ List<String> argTypes = new ArrayList<String>();
+ for (BeanArgument argument : beanArguments) {
+ Recipe value = getValue(argument.getValue(), null);
+ arguments.add(value);
+ argTypes.add(argument.getValueType());
+ }
+ recipe.setArguments(arguments);
+ recipe.setArgTypes(argTypes);
+ recipe.setReorderArguments(!hasIndex);
+ }
+ recipe.setFactoryMethod(beanMetadata.getFactoryMethod());
+ if (beanMetadata.getFactoryComponent() != null) {
+ recipe.setFactoryComponent(getValue(beanMetadata.getFactoryComponent(), null));
+ }
+ for (BeanProperty property : beanMetadata.getProperties()) {
+ Recipe value = getValue(property.getValue(), null);
+ recipe.setProperty(property.getName(), value);
+ }
+ return recipe;
+ }
+
+ private Recipe createRecipe(RegistrationListener listener) {
+ BeanRecipe recipe = new BeanRecipe(getName(null), blueprintContainer, ServiceListener.class, false);
+ recipe.setProperty("listener", getValue(listener.getListenerComponent(), null));
+ if (listener.getRegistrationMethod() != null) {
+ recipe.setProperty("registerMethod", listener.getRegistrationMethod());
+ }
+ if (listener.getUnregistrationMethod() != null) {
+ recipe.setProperty("unregisterMethod", listener.getUnregistrationMethod());
+ }
+ recipe.setProperty("blueprintContainer", blueprintContainer);
+ return recipe;
+ }
+
+ private Recipe createRecipe(ReferenceListener listener) {
+ BeanRecipe recipe = new BeanRecipe(getName(null), blueprintContainer, AbstractServiceReferenceRecipe.Listener.class, false);
+ recipe.setProperty("listener", getValue(listener.getListenerComponent(), null));
+ recipe.setProperty("metadata", listener);
+ recipe.setProperty("blueprintContainer", blueprintContainer);
+ return recipe;
+ }
+
+ private Recipe getValue(Metadata v, Object groupingType) {
+ if (v instanceof NullMetadata) {
+ return null;
+ } else if (v instanceof ComponentMetadata) {
+ return createRecipe((ComponentMetadata) v);
+ } else if (v instanceof ValueMetadata) {
+ ValueMetadata stringValue = (ValueMetadata) v;
+ Object type = stringValue.getType();
+ type = (type == null) ? groupingType : type;
+ ValueRecipe vr = new ValueRecipe(getName(null), stringValue, type);
+ return vr;
+ } else if (v instanceof RefMetadata) {
+ // TODO: make it work with property-placeholders?
+ String componentName = ((RefMetadata) v).getComponentId();
+ RefRecipe rr = new RefRecipe(getName(null), componentName);
+ return rr;
+ } else if (v instanceof CollectionMetadata) {
+ CollectionMetadata collectionMetadata = (CollectionMetadata) v;
+ Class<?> cl = collectionMetadata.getCollectionClass();
+ String type = collectionMetadata.getValueType();
+ if (cl == Object[].class) {
+ ArrayRecipe ar = new ArrayRecipe(getName(null), type);
+ for (Metadata lv : collectionMetadata.getValues()) {
+ ar.add(getValue(lv, type));
+ }
+ return ar;
+ } else {
+ CollectionRecipe cr = new CollectionRecipe(getName(null), cl != null ? cl : ArrayList.class, type);
+ for (Metadata lv : collectionMetadata.getValues()) {
+ cr.add(getValue(lv, type));
+ }
+ return cr;
+ }
+ } else if (v instanceof MapMetadata) {
+ return createMapRecipe((MapMetadata) v);
+ } else if (v instanceof PropsMetadata) {
+ PropsMetadata mapValue = (PropsMetadata) v;
+ MapRecipe mr = new MapRecipe(getName(null), Properties.class, String.class, String.class);
+ for (MapEntry entry : mapValue.getEntries()) {
+ Recipe key = getValue(entry.getKey(), String.class);
+ Recipe val = getValue(entry.getValue(), String.class);
+ mr.put(key, val);
+ }
+ return mr;
+ } else if (v instanceof IdRefMetadata) {
+ // TODO: make it work with property-placeholders?
+ String componentName = ((IdRefMetadata) v).getComponentId();
+ IdRefRecipe rnr = new IdRefRecipe(getName(null), componentName);
+ return rnr;
+ } else {
+ throw new IllegalStateException("Unsupported value: " + v.getClass().getName());
+ }
+ }
+
+ private MapRecipe createMapRecipe(MapMetadata mapValue) {
+ String keyType = mapValue.getKeyType();
+ String valueType = mapValue.getValueType();
+ MapRecipe mr = new MapRecipe(getName(null), HashMap.class, keyType, valueType);
+ for (MapEntry entry : mapValue.getEntries()) {
+ Recipe key = getValue(entry.getKey(), keyType);
+ Recipe val = getValue(entry.getValue(), valueType);
+ mr.put(key, val);
+ }
+ return mr;
+ }
+
+ private String getName(String name) {
+ if (name == null) {
+ do {
+ name = "#recipe-" + recipeIdSpace.nextId();
+ } while (names.contains(name) || registry.containsComponentDefinition(name));
+ }
+ names.add(name);
+ return name;
+ }
+
+}
diff --git a/src/main/java/org/apache/aries/blueprint/container/SimpleNamespaceHandlerSet.java b/src/main/java/org/apache/aries/blueprint/container/SimpleNamespaceHandlerSet.java
new file mode 100644
index 0000000..c937ad8
--- /dev/null
+++ b/src/main/java/org/apache/aries/blueprint/container/SimpleNamespaceHandlerSet.java
@@ -0,0 +1,85 @@
+/*
+ * 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.aries.blueprint.container;
+
+import org.apache.aries.blueprint.NamespaceHandler;
+import org.apache.aries.blueprint.ext.impl.ExtNamespaceHandler;
+import org.apache.aries.blueprint.parser.NamespaceHandlerSet;
+import org.xml.sax.SAXException;
+
+import javax.xml.XMLConstants;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import java.io.IOException;
+import java.net.URI;
+import java.util.*;
+
+public class SimpleNamespaceHandlerSet implements NamespaceHandlerSet {
+
+ public static final URI EXT_1_2_NAMESPACE = URI.create("http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.2.0");
+
+ private Set<URI> namespaces;
+ private Schema schema;
+
+ public SimpleNamespaceHandlerSet() {
+ this.namespaces = new LinkedHashSet<URI>();
+ this.namespaces.add(EXT_1_2_NAMESPACE);
+ }
+
+ public Set<URI> getNamespaces() {
+ return Collections.unmodifiableSet(namespaces);
+ }
+
+ public boolean isComplete() {
+ return true;
+ }
+
+ public NamespaceHandler getNamespaceHandler(URI uri) {
+ if (EXT_1_2_NAMESPACE.equals(uri)) {
+ return new ExtNamespaceHandler();
+ }
+ return null;
+ }
+
+ public Schema getSchema() throws SAXException, IOException {
+ if (schema == null) {
+ final List<StreamSource> schemaSources = new ArrayList<StreamSource>();
+ schemaSources.add(new StreamSource(getClass().getResourceAsStream("/org/apache/aries/blueprint/blueprint.xsd")));
+ schemaSources.add(new StreamSource(getClass().getResourceAsStream("/org/apache/aries/blueprint/ext/impl/blueprint-ext-1.2.xsd")));
+ SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ schema = schemaFactory.newSchema(schemaSources.toArray(new Source[schemaSources.size()]));
+ }
+ return schema;
+ }
+
+ public void addListener(Listener listener) {
+ throw new IllegalStateException();
+ }
+
+ public void removeListener(Listener listener) {
+ throw new IllegalStateException();
+ }
+
+ public void destroy() {
+ schema = null;
+ }
+
+}
diff --git a/src/main/java/org/apache/aries/blueprint/ext/AbstractPropertyPlaceholder.java b/src/main/java/org/apache/aries/blueprint/ext/AbstractPropertyPlaceholder.java
new file mode 100644
index 0000000..ae2f812
--- /dev/null
+++ b/src/main/java/org/apache/aries/blueprint/ext/AbstractPropertyPlaceholder.java
@@ -0,0 +1,367 @@
+/**
+ * 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.aries.blueprint.ext;
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.aries.blueprint.ComponentDefinitionRegistry;
+import org.apache.aries.blueprint.ComponentDefinitionRegistryProcessor;
+import org.apache.aries.blueprint.PassThroughMetadata;
+import org.apache.aries.blueprint.mutable.MutableBeanArgument;
+import org.apache.aries.blueprint.mutable.MutableBeanMetadata;
+import org.apache.aries.blueprint.mutable.MutableBeanProperty;
+import org.apache.aries.blueprint.mutable.MutableCollectionMetadata;
+import org.apache.aries.blueprint.mutable.MutableMapEntry;
+import org.apache.aries.blueprint.mutable.MutableMapMetadata;
+import org.apache.aries.blueprint.mutable.MutablePropsMetadata;
+import org.apache.aries.blueprint.services.ExtendedBlueprintContainer;
+import org.osgi.service.blueprint.container.ComponentDefinitionException;
+import org.osgi.service.blueprint.reflect.BeanArgument;
+import org.osgi.service.blueprint.reflect.BeanMetadata;
+import org.osgi.service.blueprint.reflect.BeanProperty;
+import org.osgi.service.blueprint.reflect.CollectionMetadata;
+import org.osgi.service.blueprint.reflect.MapEntry;
+import org.osgi.service.blueprint.reflect.MapMetadata;
+import org.osgi.service.blueprint.reflect.Metadata;
+import org.osgi.service.blueprint.reflect.NonNullMetadata;
+import org.osgi.service.blueprint.reflect.PropsMetadata;
+import org.osgi.service.blueprint.reflect.Target;
+import org.osgi.service.blueprint.reflect.ValueMetadata;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Abstract class for property placeholders.
+ *
+ * @version $Rev: 1211548 $, $Date: 2011-12-07 17:26:22 +0000 (Wed, 07 Dec 2011) $
+ */
+public abstract class AbstractPropertyPlaceholder implements ComponentDefinitionRegistryProcessor {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AbstractPropertyPlaceholder.class);
+
+ private ExtendedBlueprintContainer blueprintContainer;
+ private String placeholderPrefix = "${";
+ private String placeholderSuffix = "}";
+ private Pattern pattern;
+
+ private LinkedList<String> processingStack = new LinkedList<String>();
+
+ public String getPlaceholderPrefix() {
+ return placeholderPrefix;
+ }
+
+ public void setPlaceholderPrefix(String placeholderPrefix) {
+ this.placeholderPrefix = placeholderPrefix;
+ }
+
+ public String getPlaceholderSuffix() {
+ return placeholderSuffix;
+ }
+
+ public void setPlaceholderSuffix(String placeholderSuffix) {
+ this.placeholderSuffix = placeholderSuffix;
+ }
+
+ public ExtendedBlueprintContainer getBlueprintContainer() {
+ return blueprintContainer;
+ }
+
+ public void setBlueprintContainer(ExtendedBlueprintContainer blueprintContainer) {
+ this.blueprintContainer = blueprintContainer;
+ }
+
+ public void process(ComponentDefinitionRegistry registry) throws ComponentDefinitionException {
+ try {
+ for (String name : registry.getComponentDefinitionNames()) {
+ processMetadata(registry.getComponentDefinition(name));
+ }
+ } finally {
+ processingStack.clear();
+ }
+ }
+
+ protected Metadata processMetadata(Metadata metadata) {
+ try {
+ if (metadata instanceof BeanMetadata) {
+ BeanMetadata bmd = (BeanMetadata) metadata;
+ processingStack.add("Bean named " + bmd.getId() + "->");
+ return processBeanMetadata(bmd);
+ } else if (metadata instanceof CollectionMetadata) {
+ CollectionMetadata cmd = (CollectionMetadata) metadata;
+ processingStack.add("Collection of type " + cmd.getCollectionClass() + "->");
+ return processCollectionMetadata(cmd);
+ } else if (metadata instanceof MapMetadata) {
+ processingStack.add("Map->");
+ return processMapMetadata((MapMetadata) metadata);
+ } else if (metadata instanceof PropsMetadata) {
+ processingStack.add("Properties->");
+ return processPropsMetadata((PropsMetadata) metadata);
+ } else if (metadata instanceof ValueMetadata) {
+ processingStack.add("Value->");
+ return processValueMetadata((ValueMetadata) metadata);
+ } else {
+ processingStack.add("Unknown Metadata " + metadata + "->");
+ return metadata;
+ }
+ } finally {
+ processingStack.removeLast();
+ }
+ }
+
+ protected Metadata processBeanMetadata(BeanMetadata component) {
+ for (BeanArgument arg : component.getArguments()) {
+
+ try {
+ processingStack.add(
+ "Argument index " + arg.getIndex() + " and value type " + arg.getValueType() + "->");
+ if(arg instanceof MutableBeanArgument) {
+ ((MutableBeanArgument) arg).setValue(processMetadata(arg.getValue()));
+ } else {
+ //Say that we can't change this argument, but continue processing
+ //If the value is mutable then we may be ok!
+ printWarning(arg, "Constructor Argument");
+ processMetadata(arg.getValue());
+ }
+ } finally {
+ processingStack.removeLast();
+ }
+ }
+ for (BeanProperty prop : component.getProperties()) {
+
+ try {
+ processingStack.add("Property named " + prop.getName() + "->");
+ if(prop instanceof MutableBeanProperty) {
+ ((MutableBeanProperty) prop).setValue(processMetadata(prop.getValue()));
+ } else {
+ //Say that we can't change this property, but continue processing
+ //If the value is mutable then we may be ok!
+ printWarning(prop, "Injection Property");
+ processMetadata(prop.getValue());
+ }
+ } finally {
+ processingStack.removeLast();
+ }
+ }
+
+ Target factoryComponent = component.getFactoryComponent();
+ if(factoryComponent != null) {
+
+ try {
+
+ if(component instanceof MutableBeanMetadata) {
+ processingStack.add("Factory Component->");
+ ((MutableBeanMetadata) component).setFactoryComponent(
+ (Target) processMetadata(factoryComponent));
+ } else {
+ printWarning(component, "Factory Component");
+ processingStack.add("Factory Component->");
+ processMetadata(factoryComponent);
+ }
+ } finally {
+ processingStack.removeLast();
+ }
+ }
+
+ return component;
+ }
+
+ protected Metadata processPropsMetadata(PropsMetadata metadata) {
+
+ List<MapEntry> entries = new ArrayList<MapEntry>(metadata.getEntries());
+ if(!!! entries.isEmpty()) {
+
+ try {
+ if(metadata instanceof MutablePropsMetadata) {
+ processingStack.add("Properties->");
+ MutablePropsMetadata mpm = (MutablePropsMetadata) metadata;
+
+ for (MapEntry entry : entries) {
+ mpm.removeEntry(entry);
+ }
+ for (MapEntry entry : processMapEntries(entries)) {
+ mpm.addEntry(entry);
+ }
+ } else {
+ printWarning(metadata, "Properties");
+ processingStack.add("Properties->");
+ processMapEntries(entries);
+ }
+ } finally {
+ processingStack.removeLast();
+ }
+ }
+ return metadata;
+ }
+
+ protected Metadata processMapMetadata(MapMetadata metadata) {
+ List<MapEntry> entries = new ArrayList<MapEntry>(metadata.getEntries());
+ if(!!! entries.isEmpty()) {
+
+ try {
+ if(metadata instanceof MutableMapMetadata) {
+ processingStack.add("Map->");
+ MutableMapMetadata mmm = (MutableMapMetadata) metadata;
+
+ for (MapEntry entry : entries) {
+ mmm.removeEntry(entry);
+ }
+ for (MapEntry entry : processMapEntries(entries)) {
+ mmm.addEntry(entry);
+ }
+ } else {
+ printWarning(metadata, "Map");
+ processingStack.add("Map->");
+ processMapEntries(entries);
+ }
+ } finally {
+ processingStack.removeLast();
+ }
+ }
+ return metadata;
+ }
+
+ protected List<MapEntry> processMapEntries(List<MapEntry> entries) {
+ for (MapEntry entry : entries) {
+ try {
+ processingStack.add("Map Entry Key: " + entry.getKey() + " Value: " + entry.getValue() + "->" );
+
+ if(entry instanceof MutableMapEntry) {
+ ((MutableMapEntry) entry).setKey((NonNullMetadata) processMetadata(entry.getKey()));
+ ((MutableMapEntry) entry).setValue(processMetadata(entry.getValue()));
+ } else {
+ printWarning(entry, "Map Entry");
+ processMetadata(entry.getKey());
+ processMetadata(entry.getValue());
+ }
+ } finally {
+ processingStack.removeLast();
+ }
+ }
+ return entries;
+ }
+
+ protected Metadata processCollectionMetadata(CollectionMetadata metadata) {
+
+ List<Metadata> values = new ArrayList<Metadata>(metadata.getValues());
+ if(!!! values.isEmpty()) {
+
+ try {
+ if(metadata instanceof MutableCollectionMetadata) {
+ processingStack.add("Collection type: " + metadata.getValueType() + "->");
+ MutableCollectionMetadata mcm = (MutableCollectionMetadata) metadata;
+
+ for (Metadata value : values) {
+ mcm.removeValue(value);
+ }
+ for (Metadata value : values) {
+ mcm.addValue(processMetadata(value));
+ }
+ } else {
+ printWarning(metadata, "Collection type: " + metadata.getValueType());
+ processingStack.add("Collection type: " + metadata.getValueType() + "->");
+ for (Metadata value : values) {
+ processMetadata(value);
+ }
+ }
+ } finally {
+ processingStack.removeLast();
+ }
+ }
+ return metadata;
+ }
+
+ protected Metadata processValueMetadata(ValueMetadata metadata) {
+
+ return new LateBindingValueMetadata(metadata);
+ }
+
+ private void printWarning(Object immutable, String processingType) {
+ StringBuilder sb = new StringBuilder("The property placeholder processor for ");
+ sb.append(placeholderPrefix).append(',').append(" ").append(placeholderSuffix)
+ .append(" found an immutable ").append(processingType)
+ .append(" at location ");
+
+ for(String s : processingStack) {
+ sb.append(s);
+ }
+
+ sb.append(". This may prevent properties, beans, or other items referenced by this component from being properly processed.");
+
+ LOGGER.info(sb.toString());
+ }
+
+ protected String retrieveValue(String expression) {
+ return getProperty(expression);
+ }
+
+ protected String processString(String str) {
+ // TODO: we need to handle escapes on the prefix / suffix
+ Matcher matcher = getPattern().matcher(str);
+ while (matcher.find()) {
+ String rep = retrieveValue(matcher.group(1));
+ if (rep != null) {
+ str = str.replace(matcher.group(0), rep);
+ matcher.reset(str);
+ }
+ }
+ return str;
+ }
+
+ protected String getProperty(String val) {
+ return null;
+ }
+
+ protected Pattern getPattern() {
+ if (pattern == null) {
+ pattern = Pattern.compile("\\Q" + placeholderPrefix + "\\E(.+?)\\Q" + placeholderSuffix + "\\E");
+ }
+ return pattern;
+ }
+
+ public class LateBindingValueMetadata implements ValueMetadata {
+
+ private final ValueMetadata metadata;
+ private boolean retrieved;
+ private String retrievedValue;
+
+ public LateBindingValueMetadata(ValueMetadata metadata) {
+ this.metadata = metadata;
+ }
+
+ public String getStringValue() {
+ if (!retrieved) {
+ String v = metadata.getStringValue();
+ LOGGER.debug("Before process: {}", v);
+ retrievedValue = processString(v);
+ LOGGER.debug("After process: {}", retrievedValue);
+
+ retrieved = true;
+ }
+ return retrievedValue;
+ }
+
+ public String getType() {
+ return metadata.getType();
+ }
+ }
+}
diff --git a/src/main/java/org/apache/aries/blueprint/ext/PropertyPlaceholder.java b/src/main/java/org/apache/aries/blueprint/ext/PropertyPlaceholder.java
new file mode 100644
index 0000000..f3b6162
--- /dev/null
+++ b/src/main/java/org/apache/aries/blueprint/ext/PropertyPlaceholder.java
@@ -0,0 +1,208 @@
+/**
+ * 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.aries.blueprint.ext;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.aries.blueprint.ext.evaluator.PropertyEvaluator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Property placeholder that looks for properties in the System properties.
+ *
+ * @version $Rev$, $Date$
+ */
+public class PropertyPlaceholder extends AbstractPropertyPlaceholder {
+
+ public enum SystemProperties {
+ never,
+ fallback,
+ override
+ }
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(PropertyPlaceholder.class);
+
+ private Map defaultProperties;
+ private Properties properties;
+ private List<String> locations;
+ private boolean ignoreMissingLocations;
+ private SystemProperties systemProperties = SystemProperties.override;
+ private PropertyEvaluator evaluator = null;
+
+ public Map getDefaultProperties() {
+ return defaultProperties;
+ }
+
+ public void setDefaultProperties(Map defaultProperties) {
+ this.defaultProperties = defaultProperties;
+ }
+
+ public List<String> getLocations() {
+ return locations;
+ }
+
+ public void setLocations(List<String> locations) {
+ this.locations = locations;
+ }
+
+ public boolean isIgnoreMissingLocations() {
+ return ignoreMissingLocations;
+ }
+
+ public void setIgnoreMissingLocations(boolean ignoreMissingLocations) {
+ this.ignoreMissingLocations = ignoreMissingLocations;
+ }
+
+ public SystemProperties getSystemProperties() {
+ return systemProperties;
+ }
+
+ public void setSystemProperties(SystemProperties systemProperties) {
+ this.systemProperties = systemProperties;
+ }
+
+ public PropertyEvaluator getEvaluator() {
+ return evaluator;
+ }
+
+ public void setEvaluator(PropertyEvaluator evaluator) {
+ this.evaluator = evaluator;
+ }
+
+ public void init() throws Exception {
+ properties = new Properties();
+ if (locations != null) {
+ for (String url : locations) {
+ InputStream is = null;
+ try {
+ if (url.startsWith("classpath:")) {
+ is = getBlueprintContainer().getResource(url.substring("classpath:".length())).openStream();
+ } else {
+ is = new URL(url).openStream();
+ }
+ } catch (IOException e) {
+ if (ignoreMissingLocations) {
+ LOGGER.debug("Unable to load properties from url " + url + " while ignoreMissingLocations is set to true");
+ } else {
+ throw e;
+ }
+ }
+ if (is != null) {
+ try {
+ properties.load(is);
+ } finally {
+ is.close();
+ }
+ }
+ }
+ }
+ }
+
+ protected String getProperty(String val) {
+ LOGGER.debug("Retrieving property {}", val);
+ Object v = null;
+ if (v == null && systemProperties == SystemProperties.override) {
+ v = getBlueprintContainer().getProperty(val);
+ if (v != null) {
+ LOGGER.debug("Found system property {} with value {}", val, v);
+ }
+ }
+ if (v == null && properties != null) {
+ v = properties.getProperty(val);
+ if (v != null) {
+ LOGGER.debug("Found property {} from locations with value {}", val, v);
+ }
+ }
+ if (v == null && systemProperties == SystemProperties.fallback) {
+ v = getBlueprintContainer().getProperty(val);
+ if (v != null) {
+ LOGGER.debug("Found system property {} with value {}", val, v);
+ }
+ }
+ if (v == null && defaultProperties != null) {
+ v = defaultProperties.get(val);
+ if (v != null) {
+ LOGGER.debug("Retrieved property {} value from defaults {}", val, v);
+ }
+ }
+ if (v == null) {
+ LOGGER.debug("Property {} not found", val);
+ }
+ return v != null ? v.toString() : null;
+ }
+
+ @Override
+ protected String retrieveValue(String expression) {
+ LOGGER.debug("Retrieving Value from expression: {}", expression);
+
+ if (evaluator == null) {
+ return super.retrieveValue(expression);
+ } else {
+ return evaluator.evaluate(expression, new Dictionary<String, String>(){
+ @Override
+ public String get(Object key) {
+ return getProperty((String) key);
+ }
+
+ // following are not important
+ @Override
+ public String put(String key, String value) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Enumeration<String> elements() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public boolean isEmpty() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Enumeration<String> keys() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String remove(Object key) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int size() {
+ throw new UnsupportedOperationException();
+ }
+
+ });
+ }
+
+ }
+
+
+}
diff --git a/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java b/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java
new file mode 100644
index 0000000..4101a53
--- /dev/null
+++ b/src/main/java/org/apache/aries/blueprint/ext/impl/ExtNamespaceHandler.java
@@ -0,0 +1,445 @@
+/**
+ * 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.aries.blueprint.ext.impl;
+
+import org.apache.aries.blueprint.ComponentDefinitionRegistry;
+import org.apache.aries.blueprint.ExtendedBeanMetadata;
+import org.apache.aries.blueprint.ExtendedReferenceListMetadata;
+import org.apache.aries.blueprint.ParserContext;
+import org.apache.aries.blueprint.ext.AbstractPropertyPlaceholder;
+import org.apache.aries.blueprint.ext.PlaceholdersUtils;
+import org.apache.aries.blueprint.ext.PropertyPlaceholder;
+import org.apache.aries.blueprint.ext.evaluator.PropertyEvaluator;
+import org.apache.aries.blueprint.mutable.*;
+import org.osgi.service.blueprint.container.ComponentDefinitionException;
+import org.osgi.service.blueprint.reflect.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.*;
+import org.w3c.dom.CharacterData;
+
+import java.net.URL;
+import java.util.*;
+
+/**
+ * A namespace handler for Aries blueprint extensions
+ *
+ * @version $Rev$, $Date$
+ */
+public class ExtNamespaceHandler implements org.apache.aries.blueprint.NamespaceHandler {
+
+ public static final String BLUEPRINT_NAMESPACE = "http://www.osgi.org/xmlns/blueprint/v1.0.0";
+ public static final String BLUEPRINT_EXT_NAMESPACE_V1_0 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0";
+ public static final String BLUEPRINT_EXT_NAMESPACE_V1_1 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.1.0";
+ public static final String BLUEPRINT_EXT_NAMESPACE_V1_2 = "http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.2.0";
+
+ public static final String PROPERTY_PLACEHOLDER_ELEMENT = "property-placeholder";
+ public static final String DEFAULT_PROPERTIES_ELEMENT = "default-properties";
+ public static final String PROPERTY_ELEMENT = "property";
+ public static final String VALUE_ELEMENT = "value";
+ public static final String LOCATION_ELEMENT = "location";
+
+ public static final String ID_ATTRIBUTE = "id";
+ public static final String PLACEHOLDER_PREFIX_ATTRIBUTE = "placeholder-prefix";
+ public static final String PLACEHOLDER_SUFFIX_ATTRIBUTE = "placeholder-suffix";
+ public static final String DEFAULTS_REF_ATTRIBUTE = "defaults-ref";
+ public static final String IGNORE_MISSING_LOCATIONS_ATTRIBUTE = "ignore-missing-locations";
+ public static final String EVALUATOR_ATTRIBUTE = "evaluator";
+
+ public static final String SYSTEM_PROPERTIES_ATTRIBUTE = "system-properties";
+ public static final String SYSTEM_PROPERTIES_NEVER = "never";
+ public static final String SYSTEM_PROPERTIES_FALLBACK = "fallback";
+ public static final String SYSTEM_PROPERTIES_OVERRIDE = "override";
+
+ public static final String PROXY_METHOD_ATTRIBUTE = "proxy-method";
+ public static final String PROXY_METHOD_DEFAULT = "default";
+ public static final String PROXY_METHOD_CLASSES = "classes";
+ public static final String PROXY_METHOD_GREEDY = "greedy";
+
+ public static final String ROLE_ATTRIBUTE = "role";
+ public static final String ROLE_PROCESSOR = "processor";
+
+ public static final String FIELD_INJECTION_ATTRIBUTE = "field-injection";
+
+ public static final String DEFAULT_REFERENCE_BEAN = "default";
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ExtNamespaceHandler.class);
+
+ private int idCounter;
+
+ public URL getSchemaLocation(String namespace) {
+ if (BLUEPRINT_EXT_NAMESPACE_V1_0.equals(namespace)) {
+ return getClass().getResource("blueprint-ext.xsd");
+ } else if (BLUEPRINT_EXT_NAMESPACE_V1_1.equals(namespace)) {
+ return getClass().getResource("blueprint-ext-1.1.xsd");
+ } else if (BLUEPRINT_EXT_NAMESPACE_V1_2.equals(namespace)) {
+ return getClass().getResource("blueprint-ext-1.2.xsd");
+ } else {
+ return null;
+ }
+ }
+
+ public Set<Class> getManagedClasses() {
+ return new HashSet<Class>(Arrays.asList(
+ PropertyPlaceholder.class
+ ));
+ }
+
+ public Metadata parse(Element element, ParserContext context) {
+ LOGGER.debug("Parsing element {{}}{}", element.getNamespaceURI(), element.getLocalName());
+ if (nodeNameEquals(element, PROPERTY_PLACEHOLDER_ELEMENT)) {
+ return parsePropertyPlaceholder(context, element);
+ } else {
+ throw new ComponentDefinitionException("Unsupported element: " + element.getNodeName());
+ }
+ }
+
+ public ComponentMetadata decorate(Node node, ComponentMetadata component, ParserContext context) {
+ if (node instanceof Attr && nodeNameEquals(node, PROXY_METHOD_ATTRIBUTE)) {
+ return decorateProxyMethod(node, component, context);
+ } else if (node instanceof Attr && nodeNameEquals(node, ROLE_ATTRIBUTE)) {
+ return decorateRole(node, component, context);
+ } else if (node instanceof Attr && nodeNameEquals(node, FIELD_INJECTION_ATTRIBUTE)) {
+ return decorateFieldInjection(node, component, context);
+ } else if (node instanceof Attr && nodeNameEquals(node, DEFAULT_REFERENCE_BEAN)) {
+ return decorateDefaultBean(node, component, context);
+ } else {
+ throw new ComponentDefinitionException("Unsupported node: " + node.getNodeName());
+ }
+ }
+
+ private ComponentMetadata decorateDefaultBean(Node node,
+ ComponentMetadata component, ParserContext context)
+ {
+ if (!(component instanceof ReferenceMetadata)) {
+ throw new ComponentDefinitionException("Attribute " + node.getNodeName() + " can only be used on a <reference> element");
+ }
+
+ if (!(component instanceof MutableReferenceMetadata)) {
+ throw new ComponentDefinitionException("Expected an instanceof MutableReferenceMetadata");
+ }
+
+ String value = ((Attr) node).getValue();
+ ((MutableReferenceMetadata) component).setDefaultBean(value);
+ return component;
+ }
+
+ private ComponentMetadata decorateFieldInjection(Node node, ComponentMetadata component, ParserContext context) {
+ if (!(component instanceof BeanMetadata)) {
+ throw new ComponentDefinitionException("Attribute " + node.getNodeName() + " can only be used on a <bean> element");
+ }
+
+ if (!(component instanceof MutableBeanMetadata)) {
+ throw new ComponentDefinitionException("Expected an instanceof MutableBeanMetadata");
+ }
+
+ String value = ((Attr) node).getValue();
+ ((MutableBeanMetadata) component).setFieldInjection("true".equals(value) || "1".equals(value));
+ return component;
+ }
+
+ private ComponentMetadata decorateRole(Node node, ComponentMetadata component, ParserContext context) {
+ if (!(component instanceof BeanMetadata)) {
+ throw new ComponentDefinitionException("Attribute " + node.getNodeName() + " can only be used on a <bean> element");
+ }
+ if (!(component instanceof MutableBeanMetadata)) {
+ throw new ComponentDefinitionException("Expected an instance of MutableBeanMetadata");
+ }
+ boolean processor = false;
+ String value = ((Attr) node).getValue();
+ String[] flags = value.trim().split(" ");
+ for (String flag : flags) {
+ if (ROLE_PROCESSOR.equals(flag)) {
+ processor = true;
+ } else {
+ throw new ComponentDefinitionException("Unknown proxy method: " + flag);
+ }
+ }
+ ((MutableBeanMetadata) component).setProcessor(processor);
+ return component;
+ }
+
+ private ComponentMetadata decorateProxyMethod(Node node, ComponentMetadata component, ParserContext context) {
+ if (!(component instanceof ServiceReferenceMetadata)) {
+ throw new ComponentDefinitionException("Attribute " + node.getNodeName() + " can only be used on a <reference> or <reference-list> element");
+ }
+ if (!(component instanceof MutableServiceReferenceMetadata)) {
+ throw new ComponentDefinitionException("Expected an instance of MutableServiceReferenceMetadata");
+ }
+ int method = 0;
+ String value = ((Attr) node).getValue();
+ String[] flags = value.trim().split(" ");
+ for (String flag : flags) {
+ if (PROXY_METHOD_DEFAULT.equals(flag)) {
+ method += ExtendedReferenceListMetadata.PROXY_METHOD_DEFAULT;
+ } else if (PROXY_METHOD_CLASSES.equals(flag)) {
+ method += ExtendedReferenceListMetadata.PROXY_METHOD_CLASSES;
+ } else if (PROXY_METHOD_GREEDY.equals(flag)) {
+ method += ExtendedReferenceListMetadata.PROXY_METHOD_GREEDY;
+ } else {
+ throw new ComponentDefinitionException("Unknown proxy method: " + flag);
+ }
+ }
+ if ((method & ExtendedReferenceListMetadata.PROXY_METHOD_GREEDY) != 0 && !(component instanceof ReferenceListMetadata)) {
+ throw new ComponentDefinitionException("Greedy proxying is only available for <reference-list> element");
+ }
+ ((MutableServiceReferenceMetadata) component).setProxyMethod(method);
+ return component;
+ }
+
+ private Metadata parsePropertyPlaceholder(ParserContext context, Element element) {
+ MutableBeanMetadata metadata = context.createMetadata(MutableBeanMetadata.class);
+ metadata.setProcessor(true);
+ metadata.setId(getId(context, element));
+ metadata.setScope(BeanMetadata.SCOPE_SINGLETON);
+ metadata.setRuntimeClass(PropertyPlaceholder.class);
+ metadata.setInitMethod("init");
+ String prefix = element.hasAttribute(PLACEHOLDER_PREFIX_ATTRIBUTE)
+ ? element.getAttribute(PLACEHOLDER_PREFIX_ATTRIBUTE)
+ : "${";
+ metadata.addProperty("placeholderPrefix", createValue(context, prefix));
+ String suffix = element.hasAttribute(PLACEHOLDER_SUFFIX_ATTRIBUTE)
+ ? element.getAttribute(PLACEHOLDER_SUFFIX_ATTRIBUTE)
+ : "}";
+ metadata.addProperty("placeholderSuffix", createValue(context, suffix));
+ metadata.addProperty("blueprintContainer", createRef(context, "blueprintContainer"));
+ String defaultsRef = element.hasAttribute(DEFAULTS_REF_ATTRIBUTE) ? element.getAttribute(DEFAULTS_REF_ATTRIBUTE) : null;
+ if (defaultsRef != null) {
+ metadata.addProperty("defaultProperties", createRef(context, defaultsRef));
+ }
+ String ignoreMissingLocations = element.hasAttribute(IGNORE_MISSING_LOCATIONS_ATTRIBUTE) ? element.getAttribute(IGNORE_MISSING_LOCATIONS_ATTRIBUTE) : null;
+ if (ignoreMissingLocations != null) {
+ metadata.addProperty("ignoreMissingLocations", createValue(context, ignoreMissingLocations));
+ }
+ String systemProperties = element.hasAttribute(SYSTEM_PROPERTIES_ATTRIBUTE) ? element.getAttribute(SYSTEM_PROPERTIES_ATTRIBUTE) : null;
+ if (systemProperties != null) {
+ metadata.addProperty("systemProperties", createValue(context, systemProperties));
+ }
+ String evaluator = element.hasAttribute(EVALUATOR_ATTRIBUTE) ? element.getAttribute(EVALUATOR_ATTRIBUTE) : null;
+ if (evaluator != null) {
+ throw new IllegalStateException("Evaluators are not supported outside OSGi");
+ }
+ // Parse elements
+ List<String> locations = new ArrayList<String>();
+ NodeList nl = element.getChildNodes();
+ for (int i = 0; i < nl.getLength(); i++) {
+ Node node = nl.item(i);
+ if (node instanceof Element) {
+ Element e = (Element) node;
+ if (BLUEPRINT_EXT_NAMESPACE_V1_0.equals(e.getNamespaceURI())
+ || BLUEPRINT_EXT_NAMESPACE_V1_1.equals(e.getNamespaceURI())
+ || BLUEPRINT_EXT_NAMESPACE_V1_2.equals(e.getNamespaceURI())) {
+ if (nodeNameEquals(e, DEFAULT_PROPERTIES_ELEMENT)) {
+ if (defaultsRef != null) {
+ throw new ComponentDefinitionException("Only one of " + DEFAULTS_REF_ATTRIBUTE + " attribute or " + DEFAULT_PROPERTIES_ELEMENT + " element is allowed");
+ }
+ Metadata props = parseDefaultProperties(context, metadata, e);
+ metadata.addProperty("defaultProperties", props);
+ } else if (nodeNameEquals(e, LOCATION_ELEMENT)) {
+ locations.add(getTextValue(e));
+ }
+ }
+ }
+ }
+ if (!locations.isEmpty()) {
+ metadata.addProperty("locations", createList(context, locations));
+ }
+
+ boolean result = validatePlaceholder(metadata, context.getComponentDefinitionRegistry());
+
+ return result ? metadata : null;
+ }
+
+ private boolean validatePlaceholder(MutableBeanMetadata metadata, ComponentDefinitionRegistry registry) {
+ for (String id : registry.getComponentDefinitionNames()) {
+ ComponentMetadata component = registry.getComponentDefinition(id);
+ if (component instanceof ExtendedBeanMetadata) {
+ ExtendedBeanMetadata bean = (ExtendedBeanMetadata) component;
+ if (bean.getRuntimeClass() != null && AbstractPropertyPlaceholder.class.isAssignableFrom(bean.getRuntimeClass())) {
+ if (arePropertiesEquals(bean, metadata, "placeholderPrefix")
+ && arePropertiesEquals(bean, metadata, "placeholderSuffix")) {
+ if (!arePropertiesEquals(bean, metadata, "systemProperties")
+ || !arePropertiesEquals(bean, metadata, "ignoreMissingLocations")) {
+ throw new ComponentDefinitionException("Multiple incompatible placeholders found");
+ }
+ // Merge both placeholders
+ mergeList(bean, metadata, "locations");
+ mergeMap(bean, metadata, "defaultProperties");
+ return false;
+ }
+ }
+ }
+ }
+ return true;
+ }
+
+ private void mergeList(ExtendedBeanMetadata bean1, MutableBeanMetadata bean2, String name) {
+ Metadata m1 = getProperty(bean1, name);
+ Metadata m2 = getProperty(bean2, name);
+ if (m1 == null && m2 != null) {
+ ((MutableBeanMetadata) bean1).addProperty(name, m2);
+ } else if (m1 != null && m2 != null) {
+ if (!(m1 instanceof MutableCollectionMetadata) || !(m2 instanceof MutableCollectionMetadata)) {
+ throw new ComponentDefinitionException("Unable to merge " + name + " list properties");
+ }
+ MutableCollectionMetadata c1 = (MutableCollectionMetadata) m1;
+ MutableCollectionMetadata c2 = (MutableCollectionMetadata) m2;
+ for (Metadata v : c2.getValues()) {
+ c1.addValue(v);
+ }
+ }
+ }
+
+ private void mergeMap(ExtendedBeanMetadata bean1, MutableBeanMetadata bean2, String name) {
+ Metadata m1 = getProperty(bean1, name);
+ Metadata m2 = getProperty(bean2, name);
+ if (m1 == null && m2 != null) {
+ ((MutableBeanMetadata) bean1).addProperty(name, m2);
+ } else if (m1 != null && m2 != null) {
+ if (!(m1 instanceof MutableMapMetadata) || !(m2 instanceof MutableMapMetadata)) {
+ throw new ComponentDefinitionException("Unable to merge " + name + " list properties");
+ }
+ MutableMapMetadata c1 = (MutableMapMetadata) m1;
+ MutableMapMetadata c2 = (MutableMapMetadata) m2;
+ for (MapEntry e : c2.getEntries()) {
+ c1.addEntry(e);
+ }
+ }
+ }
+
+ private boolean arePropertiesEquals(BeanMetadata bean1, BeanMetadata bean2, String name) {
+ String v1 = getPlaceholderProperty(bean1, name);
+ String v2 = getPlaceholderProperty(bean2, name);
+ return v1 == null ? v2 == null : v1.equals(v2);
+ }
+
+ private String getPlaceholderProperty(BeanMetadata bean, String name) {
+ Metadata metadata = getProperty(bean, name);
+ if (metadata instanceof ValueMetadata) {
+ return ((ValueMetadata) metadata).getStringValue();
+ }
+ return null;
+ }
+
+ private Metadata getProperty(BeanMetadata bean, String name) {
+ for (BeanProperty property : bean.getProperties()) {
+ if (name.equals(property.getName())) {
+ return property.getValue();
+ }
+ }
+ return null;
+ }
+
+
+ private Metadata parseDefaultProperties(ParserContext context, MutableBeanMetadata enclosingComponent, Element element) {
+ MutableMapMetadata props = context.createMetadata(MutableMapMetadata.class);
+ NodeList nl = element.getChildNodes();
+ for (int i = 0; i < nl.getLength(); i++) {
+ Node node = nl.item(i);
+ if (node instanceof Element) {
+ Element e = (Element) node;
+ if (BLUEPRINT_EXT_NAMESPACE_V1_0.equals(e.getNamespaceURI())
+ || BLUEPRINT_EXT_NAMESPACE_V1_1.equals(e.getNamespaceURI())
+ || BLUEPRINT_EXT_NAMESPACE_V1_2.equals(e.getNamespaceURI())) {
+ if (nodeNameEquals(e, PROPERTY_ELEMENT)) {
+ BeanProperty prop = context.parseElement(BeanProperty.class, enclosingComponent, e);
+ props.addEntry(createValue(context, prop.getName(), String.class.getName()), prop.getValue());
+ }
+ }
+ }
+ }
+ return props;
+ }
+
+ public String getId(ParserContext context, Element element) {
+ if (element.hasAttribute(ID_ATTRIBUTE)) {
+ return element.getAttribute(ID_ATTRIBUTE);
+ } else {
+ return generateId(context);
+ }
+ }
+
+ public void generateIdIfNeeded(ParserContext context, MutableComponentMetadata metadata) {
+ if (metadata.getId() == null) {
+ metadata.setId(generateId(context));
+ }
+ }
+
+ private String generateId(ParserContext context) {
+ String id;
+ do {
+ id = ".ext-" + ++idCounter;
+ } while (context.getComponentDefinitionRegistry().containsComponentDefinition(id));
+ return id;
+ }
+
+ private static ValueMetadata createValue(ParserContext context, String value) {
+ return createValue(context, value, null);
+ }
+
+ private static ValueMetadata createValue(ParserContext context, String value, String type) {
+ MutableValueMetadata m = context.createMetadata(MutableValueMetadata.class);
+ m.setStringValue(value);
+ m.setType(type);
+ return m;
+ }
+
+ private static RefMetadata createRef(ParserContext context, String value) {
+ MutableRefMetadata m = context.createMetadata(MutableRefMetadata.class);
+ m.setComponentId(value);
+ return m;
+ }
+
+ private static IdRefMetadata createIdRef(ParserContext context, String value) {
+ MutableIdRefMetadata m = context.createMetadata(MutableIdRefMetadata.class);
+ m.setComponentId(value);
+ return m;
+ }
+
+ private static CollectionMetadata createList(ParserContext context, List<String> list) {
+ MutableCollectionMetadata m = context.createMetadata(MutableCollectionMetadata.class);
+ m.setCollectionClass(List.class);
+ m.setValueType(String.class.getName());
+ for (String v : list) {
+ m.addValue(createValue(context, v, String.class.getName()));
+ }
+ return m;
+ }
+
+ private static String getTextValue(Element element) {
+ StringBuffer value = new StringBuffer();
+ NodeList nl = element.getChildNodes();
+ for (int i = 0; i < nl.getLength(); i++) {
+ Node item = nl.item(i);
+ if ((item instanceof CharacterData && !(item instanceof Comment)) || item instanceof EntityReference) {
+ value.append(item.getNodeValue());
+ }
+ }
+ return value.toString();
+ }
+
+ private static boolean nodeNameEquals(Node node, String name) {
+ return (name.equals(node.getNodeName()) || name.equals(node.getLocalName()));
+ }
+
+ public static boolean isBlueprintNamespace(String ns) {
+ return BLUEPRINT_NAMESPACE.equals(ns);
+ }
+
+}
diff --git a/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java b/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java
new file mode 100644
index 0000000..d490c71
--- /dev/null
+++ b/src/main/java/org/apache/aries/blueprint/services/ExtendedBlueprintContainer.java
@@ -0,0 +1,46 @@
+/*
+ * 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.aries.blueprint.services;
+
+import org.apache.aries.blueprint.ComponentDefinitionRegistry;
+import org.apache.aries.blueprint.Processor;
+import org.osgi.service.blueprint.container.BlueprintContainer;
+import org.osgi.service.blueprint.container.Converter;
+
+import java.net.URL;
+import java.security.AccessControlContext;
+import java.util.List;
+
+public interface ExtendedBlueprintContainer extends BlueprintContainer {
+
+ Converter getConverter();
+
+ Class loadClass(String name) throws ClassNotFoundException;
+
+ URL getResource(String name);
+
+ AccessControlContext getAccessControlContext();
+
+ ComponentDefinitionRegistry getComponentDefinitionRegistry();
+
+ <T extends Processor> List<T> getProcessors(Class<T> type);
+
+ String getProperty(String key);
+
+}
diff --git a/src/main/resources/OSGI-INF/blueprint/blueprint-cm.xml b/src/main/resources/OSGI-INF/blueprint/blueprint-cm.xml
deleted file mode 100644
index c9ffa4e..0000000
--- a/src/main/resources/OSGI-INF/blueprint/blueprint-cm.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!--
-
- 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.
-
--->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" default-activation="lazy">
-
- <bean id="CmNamespaceHandler" class="org.apache.aries.blueprint.compendium.cm.CmNamespaceHandler"/>
-
- <service ref="CmNamespaceHandler" interface="org.apache.aries.blueprint.NamespaceHandler">
- <service-properties>
- <entry key="osgi.service.blueprint.namespace" value="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"/>
- </service-properties>
- </service>
- <service ref="CmNamespaceHandler" interface="org.apache.aries.blueprint.NamespaceHandler">
- <service-properties>
- <entry key="osgi.service.blueprint.namespace" value="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"/>
- </service-properties>
- </service>
- <service ref="CmNamespaceHandler" interface="org.apache.aries.blueprint.NamespaceHandler">
- <service-properties>
- <entry key="osgi.service.blueprint.namespace" value="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.2.0"/>
- </service-properties>
- </service>
-
-</blueprint>
diff --git a/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.0.0.xsd b/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.0.0.xsd
deleted file mode 100644
index 30c4d36..0000000
--- a/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.0.0.xsd
+++ /dev/null
@@ -1,121 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!--
- /*
- * $Revision$
- *
- * Copyright (c) OSGi Alliance (2008, 2009). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-<xsd:schema xmlns="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- targetNamespace="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.0.0"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified"
- version="1.0.0">
-
- <xsd:import namespace="http://www.osgi.org/xmlns/blueprint/v1.0.0" />
-
- <!-- property placeholder -->
-
- <xsd:element name="property-placeholder" type="TpropertyPlaceholder"/>
-
- <xsd:complexType name="TpropertyPlaceholder">
- <xsd:complexContent>
- <xsd:extension base="bp:Tcomponent">
- <xsd:sequence>
- <!-- nested properties declaration -->
- <xsd:element name="default-properties" type="TdefaultProperties" minOccurs="0" maxOccurs="1"/>
- </xsd:sequence>
-
- <!-- #### What should be the type for a persistent id? I think we need to define one like class and method -->
- <xsd:attribute name="persistent-id" type="xsd:string" use="required"/>
- <xsd:attribute name="placeholder-prefix" type="xsd:string" use="optional" default="${"/>
- <xsd:attribute name="placeholder-suffix" type="xsd:string" use="optional" default="}"/>
- <xsd:attribute name="defaults-ref" type="bp:Tidref" use="optional"/>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
- <!-- #### is this the correct type here? This is defining placeholder properties,
- so should this be a restricted set of value types or should this be expanded to
- all of the elements you can inject into a bean property? -->
- <xsd:complexType name="TdefaultProperties">
- <xsd:sequence minOccurs="0" maxOccurs="unbounded">
- <xsd:element name="property" type="bp:Tproperty"/>
- </xsd:sequence>
- </xsd:complexType>
-
-
- <!-- managed-properties -->
-
- <xsd:element name="managed-properties" type="TmanagedProperties"/>
-
- <xsd:complexType name="TmanagedProperties">
- <xsd:attribute name="persistent-id" type="xsd:string" use="required"/>
- <xsd:attribute name="update-strategy" type="TupdateStrategyType" use="optional"/>
- <xsd:attribute name="update-method" type="xsd:string" use="optional"/>
- </xsd:complexType>
-
- <xsd:simpleType name="TupdateStrategyType">
- <xsd:restriction base="xsd:NMTOKEN">
- <xsd:enumeration value="none"/>
- <xsd:enumeration value="component-managed"/>
- <xsd:enumeration value="container-managed"/>
- </xsd:restriction>
- </xsd:simpleType>
-
- <!-- managed-service-factory -->
-
- <xsd:element name="managed-service-factory" type="TmanagedServiceFactory"/>
-
- <xsd:complexType name="TmanagedServiceFactory">
- <xsd:complexContent>
- <xsd:extension base="bp:Tcomponent">
- <xsd:sequence>
- <xsd:group ref="bp:GbaseServiceElements"/>
- <xsd:element name="managed-component" type="TmanagedComponent" minOccurs="1" maxOccurs="1"/>
- </xsd:sequence>
- <xsd:attribute name="interface" type="bp:Tclass" use="optional" />
- <xsd:attribute name="ref" type="bp:Tidref" use="optional" />
- <xsd:attribute name="auto-export" type="bp:TautoExportModes" default="disabled" />
- <xsd:attribute name="ranking" type="xsd:int" default="0"/>
- <xsd:attribute name="factory-pid" type="xsd:string" use="required"/>
- <xsd:anyAttribute namespace="##other" processContents="strict"/>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
- <xsd:complexType name="TmanagedComponent">
- <xsd:group ref="bp:GbeanElements"/>
- <xsd:attribute name="class" type="bp:Tclass"/>
- <xsd:attribute name="init-method" type="bp:Tmethod"/>
- <xsd:attribute name="destroy-method" type="bp:Tmethod"/>
- <xsd:attribute name="factory-method" type="bp:Tmethod"/>
- <xsd:attribute name="factory-component" type="bp:Tidref"/>
- <xsd:anyAttribute namespace="##other" processContents="strict"/>
- </xsd:complexType>
-
-
- <!-- cm-properties -->
-
- <xsd:element name="cm-properties" type="TcmProperties"/>
-
- <xsd:complexType name="TcmProperties">
- <xsd:attribute name="persistent-id" type="xsd:string" use="required"/>
- <xsd:attribute name="update" type="xsd:boolean" use="optional" default="false"/>
- </xsd:complexType>
-
-</xsd:schema>
diff --git a/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.1.0.xsd b/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.1.0.xsd
deleted file mode 100644
index 8db6d9c..0000000
--- a/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.1.0.xsd
+++ /dev/null
@@ -1,129 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!--
- /*
- * $Revision$
- *
- * Copyright (c) OSGi Alliance (2008, 2009). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-<xsd:schema xmlns="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- targetNamespace="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified"
- version="1.0.0">
-
- <xsd:import namespace="http://www.osgi.org/xmlns/blueprint/v1.0.0" />
-
- <!-- property placeholder -->
-
- <xsd:element name="property-placeholder" type="TpropertyPlaceholder"/>
-
- <xsd:complexType name="TpropertyPlaceholder">
- <xsd:complexContent>
- <xsd:extension base="bp:Tcomponent">
- <xsd:sequence>
- <!-- nested properties declaration -->
- <xsd:element name="default-properties" type="TdefaultProperties" minOccurs="0" maxOccurs="1"/>
- </xsd:sequence>
-
- <!-- #### What should be the type for a persistent id? I think we need to define one like class and method -->
- <xsd:attribute name="persistent-id" type="xsd:string" use="required"/>
- <xsd:attribute name="placeholder-prefix" type="xsd:string" use="optional" default="${"/>
- <xsd:attribute name="placeholder-suffix" type="xsd:string" use="optional" default="}"/>
- <xsd:attribute name="defaults-ref" type="bp:Tidref" use="optional"/>
- <xsd:attribute name="update-strategy" type="TplaceholderUpdateStrategyType" use="optional" default="none"/>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
- <xsd:simpleType name="TplaceholderUpdateStrategyType">
- <xsd:restriction base="xsd:NMTOKEN">
- <xsd:enumeration value="none"/>
- <xsd:enumeration value="reload"/>
- </xsd:restriction>
- </xsd:simpleType>
-
- <!-- #### is this the correct type here? This is defining placeholder properties,
- so should this be a restricted set of value types or should this be expanded to
- all of the elements you can inject into a bean property? -->
- <xsd:complexType name="TdefaultProperties">
- <xsd:sequence minOccurs="0" maxOccurs="unbounded">
- <xsd:element name="property" type="bp:Tproperty"/>
- </xsd:sequence>
- </xsd:complexType>
-
-
- <!-- managed-properties -->
-
- <xsd:element name="managed-properties" type="TmanagedProperties"/>
-
- <xsd:complexType name="TmanagedProperties">
- <xsd:attribute name="persistent-id" type="xsd:string" use="required"/>
- <xsd:attribute name="update-strategy" type="TupdateStrategyType" use="optional"/>
- <xsd:attribute name="update-method" type="xsd:string" use="optional"/>
- </xsd:complexType>
-
- <xsd:simpleType name="TupdateStrategyType">
- <xsd:restriction base="xsd:NMTOKEN">
- <xsd:enumeration value="none"/>
- <xsd:enumeration value="component-managed"/>
- <xsd:enumeration value="container-managed"/>
- </xsd:restriction>
- </xsd:simpleType>
-
- <!-- managed-service-factory -->
-
- <xsd:element name="managed-service-factory" type="TmanagedServiceFactory"/>
-
- <xsd:complexType name="TmanagedServiceFactory">
- <xsd:complexContent>
- <xsd:extension base="bp:Tcomponent">
- <xsd:sequence>
- <xsd:group ref="bp:GbaseServiceElements"/>
- <xsd:element name="managed-component" type="TmanagedComponent" minOccurs="1" maxOccurs="1"/>
- </xsd:sequence>
- <xsd:attribute name="interface" type="bp:Tclass" use="optional" />
- <xsd:attribute name="ref" type="bp:Tidref" use="optional" />
- <xsd:attribute name="auto-export" type="bp:TautoExportModes" default="disabled" />
- <xsd:attribute name="ranking" type="xsd:int" default="0"/>
- <xsd:attribute name="factory-pid" type="xsd:string" use="required"/>
- <xsd:anyAttribute namespace="##other" processContents="strict"/>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
- <xsd:complexType name="TmanagedComponent">
- <xsd:group ref="bp:GbeanElements"/>
- <xsd:attribute name="class" type="bp:Tclass"/>
- <xsd:attribute name="init-method" type="bp:Tmethod"/>
- <xsd:attribute name="destroy-method" type="bp:Tmethod"/>
- <xsd:attribute name="factory-method" type="bp:Tmethod"/>
- <xsd:attribute name="factory-component" type="bp:Tidref"/>
- <xsd:anyAttribute namespace="##other" processContents="strict"/>
- </xsd:complexType>
-
-
- <!-- cm-properties -->
-
- <xsd:element name="cm-properties" type="TcmProperties"/>
-
- <xsd:complexType name="TcmProperties">
- <xsd:attribute name="persistent-id" type="xsd:string" use="required"/>
- <xsd:attribute name="update" type="xsd:boolean" use="optional" default="false"/>
- </xsd:complexType>
-
-</xsd:schema>
diff --git a/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.2.0.xsd b/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.2.0.xsd
deleted file mode 100644
index 9851f51..0000000
--- a/src/main/resources/org/apache/aries/blueprint/compendium/cm/blueprint-cm-1.2.0.xsd
+++ /dev/null
@@ -1,133 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!--
- /*
- * $Revision$
- *
- * Copyright (c) OSGi Alliance (2008, 2009). All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- -->
-<xsd:schema xmlns="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.2.0"
- xmlns:xsd="http://www.w3.org/2001/XMLSchema"
- xmlns:bp="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- targetNamespace="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.2.0"
- elementFormDefault="qualified"
- attributeFormDefault="unqualified"
- version="1.0.0">
-
- <xsd:import namespace="http://www.osgi.org/xmlns/blueprint/v1.0.0" />
-
- <!-- property placeholder -->
-
- <xsd:element name="property-placeholder" type="TpropertyPlaceholder"/>
-
- <xsd:complexType name="TpropertyPlaceholder">
- <xsd:complexContent>
- <xsd:extension base="bp:Tcomponent">
- <xsd:sequence>
- <!-- nested properties declaration -->
- <xsd:element name="default-properties" type="TdefaultProperties" minOccurs="0" maxOccurs="1"/>
- </xsd:sequence>
-
- <!-- #### What should be the type for a persistent id? I think we need to define one like class and method -->
- <xsd:attribute name="persistent-id" type="xsd:string" use="required"/>
- <xsd:attribute name="placeholder-prefix" type="xsd:string" use="optional" default="${"/>
- <xsd:attribute name="placeholder-suffix" type="xsd:string" use="optional" default="}"/>
- <xsd:attribute name="defaults-ref" type="bp:Tidref" use="optional"/>
- <xsd:attribute name="update-strategy" type="TplaceholderUpdateStrategyType" use="optional" default="none"/>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
- <xsd:simpleType name="TplaceholderUpdateStrategyType">
- <xsd:restriction base="xsd:NMTOKEN">
- <xsd:enumeration value="none"/>
- <xsd:enumeration value="reload"/>
- </xsd:restriction>
- </xsd:simpleType>
-
- <!-- #### is this the correct type here? This is defining placeholder properties,
- so should this be a restricted set of value types or should this be expanded to
- all of the elements you can inject into a bean property? -->
- <xsd:complexType name="TdefaultProperties">
- <xsd:sequence minOccurs="0" maxOccurs="unbounded">
- <xsd:element name="property" type="bp:Tproperty"/>
- </xsd:sequence>
- </xsd:complexType>
-
-
- <!-- managed-properties -->
-
- <xsd:element name="managed-properties" type="TmanagedProperties"/>
-
- <xsd:complexType name="TmanagedProperties">
- <xsd:attribute name="persistent-id" type="xsd:string" use="required"/>
- <xsd:attribute name="update-strategy" type="TupdateStrategyType" use="optional"/>
- <xsd:attribute name="update-method" type="xsd:string" use="optional"/>
- </xsd:complexType>
-
- <xsd:simpleType name="TupdateStrategyType">
- <xsd:restriction base="xsd:NMTOKEN">
- <xsd:enumeration value="none"/>
- <xsd:enumeration value="component-managed"/>
- <xsd:enumeration value="container-managed"/>
- </xsd:restriction>
- </xsd:simpleType>
-
- <!-- managed-service-factory -->
-
- <xsd:element name="managed-service-factory" type="TmanagedServiceFactory"/>
-
- <xsd:complexType name="TmanagedServiceFactory">
- <xsd:complexContent>
- <xsd:extension base="bp:Tcomponent">
- <xsd:sequence>
- <xsd:group ref="bp:GbaseServiceElements"/>
- <xsd:element name="managed-component" type="TmanagedComponent" minOccurs="1" maxOccurs="1"/>
- </xsd:sequence>
- <xsd:attribute name="interface" type="bp:Tclass" use="optional" />
- <xsd:attribute name="ref" type="bp:Tidref" use="optional" />
- <xsd:attribute name="auto-export" type="bp:TautoExportModes" default="disabled" />
- <xsd:attribute name="ranking" type="xsd:int" default="0"/>
- <xsd:attribute name="factory-pid" type="xsd:string" use="required"/>
- <xsd:anyAttribute namespace="##other" processContents="strict"/>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
- <xsd:complexType name="TmanagedComponent">
- <xsd:group ref="bp:GbeanElements"/>
- <xsd:attribute name="class" type="bp:Tclass"/>
- <xsd:attribute name="init-method" type="bp:Tmethod"/>
- <xsd:attribute name="destroy-method" type="bp:Tmethod"/>
- <xsd:attribute name="factory-method" type="bp:Tmethod"/>
- <xsd:attribute name="factory-component" type="bp:Tidref"/>
- <xsd:anyAttribute namespace="##other" processContents="strict"/>
- </xsd:complexType>
-
-
- <!-- cm-properties -->
-
- <xsd:element name="cm-properties" type="TcmProperties"/>
-
- <xsd:complexType name="TcmProperties">
- <xsd:complexContent>
- <xsd:extension base="bp:Tcomponent">
- <xsd:attribute name="persistent-id" type="xsd:string" use="required"/>
- <xsd:attribute name="update" type="xsd:boolean" use="optional" default="false"/>
- </xsd:extension>
- </xsd:complexContent>
- </xsd:complexType>
-
-</xsd:schema>
diff --git a/src/test/java/org.apache.aries.blueprint/BlueprintContainerTest.java b/src/test/java/org.apache.aries.blueprint/BlueprintContainerTest.java
new file mode 100644
index 0000000..3e41c6d
--- /dev/null
+++ b/src/test/java/org.apache.aries.blueprint/BlueprintContainerTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.aries.blueprint;
+
+import org.apache.aries.blueprint.container.BlueprintContainerImpl;
+import org.apache.aries.blueprint.sample.Foo;
+import org.junit.Test;
+
+import java.net.URL;
+import java.util.Arrays;
+
+import static org.junit.Assert.*;
+
+public class BlueprintContainerTest {
+
+ @Test
+ public void testSimple() throws Exception {
+ URL url = getClass().getClassLoader().getResource("test.xml");
+ BlueprintContainerImpl container = new BlueprintContainerImpl(getClass().getClassLoader(), Arrays.asList(url));
+
+ Foo foo = (Foo) container.getComponentInstance("foo");
+ System.out.println(foo);
+ assertNotNull(foo);
+ assertEquals(5, foo.getA());
+ assertEquals(1, foo.getB());
+
+ container.destroy();
+ }
+
+ @Test
+ public void testPlaceholders() throws Exception {
+ URL url1 = getClass().getClassLoader().getResource("test.xml");
+ URL url2 = getClass().getClassLoader().getResource("test2.xml");
+ BlueprintContainerImpl container = new BlueprintContainerImpl(getClass().getClassLoader(), Arrays.asList(url1, url2));
+
+ Foo foo = (Foo) container.getComponentInstance("foo");
+ System.out.println(foo);
+ assertNotNull(foo);
+ assertEquals(5, foo.getA());
+ assertEquals(1, foo.getB());
+
+ container.destroy();
+ }
+
+ public static void main(String[] args) throws Exception {
+ URL url = BlueprintContainerTest.class.getClassLoader().getResource("test.xml");
+ BlueprintContainerImpl container = new BlueprintContainerImpl(BlueprintContainerTest.class.getClassLoader(), Arrays.asList(url));
+ System.out.println(container.getComponentInstance("foo"));
+ container.destroy();
+ }
+}
diff --git a/src/test/java/org.apache.aries.blueprint/sample/Bar.java b/src/test/java/org.apache.aries.blueprint/sample/Bar.java
new file mode 100644
index 0000000..25f70cf
--- /dev/null
+++ b/src/test/java/org.apache.aries.blueprint/sample/Bar.java
@@ -0,0 +1,46 @@
+/**
+ * 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.aries.blueprint.sample;
+
+import java.util.List;
+
+public class Bar {
+
+ private String value;
+ private List list;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String s) {
+ value = s;
+ }
+
+ public List getList() {
+ return list;
+ }
+
+ public void setList(List l) {
+ list = l;
+ }
+
+ public String toString() {
+ return hashCode() + ": " + value + " " + list;
+ }
+
+}
diff --git a/src/test/java/org.apache.aries.blueprint/sample/CurrencyTypeConverter.java b/src/test/java/org.apache.aries.blueprint/sample/CurrencyTypeConverter.java
new file mode 100644
index 0000000..986787a
--- /dev/null
+++ b/src/test/java/org.apache.aries.blueprint/sample/CurrencyTypeConverter.java
@@ -0,0 +1,34 @@
+/**
+ * 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.aries.blueprint.sample;
+
+import org.osgi.service.blueprint.container.Converter;
+import org.osgi.service.blueprint.container.ReifiedType;
+
+import java.util.Currency;
+
+public class CurrencyTypeConverter implements Converter {
+
+ public boolean canConvert(Object fromValue, ReifiedType toType) {
+ return Currency.class.isAssignableFrom(toType.getRawClass());
+ }
+
+ public Object convert(Object source, ReifiedType toType) throws Exception {
+ return Currency.getInstance(source.toString());
+ }
+
+}
diff --git a/src/test/java/org.apache.aries.blueprint/sample/DateTypeConverter.java b/src/test/java/org.apache.aries.blueprint/sample/DateTypeConverter.java
new file mode 100644
index 0000000..11e9014
--- /dev/null
+++ b/src/test/java/org.apache.aries.blueprint/sample/DateTypeConverter.java
@@ -0,0 +1,42 @@
+/**
+ * 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.aries.blueprint.sample;
+
+import org.osgi.service.blueprint.container.Converter;
+import org.osgi.service.blueprint.container.ReifiedType;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class DateTypeConverter implements Converter {
+
+ DateFormat dateFormat;
+
+ public void setFormat(String format) {
+ dateFormat = new SimpleDateFormat(format);
+ }
+
+ public Object convert(Object source, ReifiedType toType) throws Exception {
+ return dateFormat.parse(source.toString());
+ }
+
+ public boolean canConvert(Object fromValue, ReifiedType toType) {
+ return Date.class.isAssignableFrom(toType.getRawClass());
+ }
+
+}
diff --git a/src/test/java/org.apache.aries.blueprint/sample/Foo.java b/src/test/java/org.apache.aries.blueprint/sample/Foo.java
new file mode 100644
index 0000000..7eedebd
--- /dev/null
+++ b/src/test/java/org.apache.aries.blueprint/sample/Foo.java
@@ -0,0 +1,107 @@
+/**
+ * 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.aries.blueprint.sample;
+
+import java.io.Serializable;
+import java.util.Currency;
+import java.util.Date;
+import java.util.Map;
+
+public class Foo implements Serializable {
+
+ private int a;
+ private int b;
+ private Bar bar;
+ private Currency currency;
+ private Date date;
+
+ public boolean initialized;
+ public boolean destroyed;
+ private Map<String, Object> props;
+
+ public int getA() {
+ return a;
+ }
+
+ public void setA(int i) {
+ a = i;
+ }
+
+ public int getB() {
+ return b;
+ }
+
+ public void setB(int i) {
+ b = i;
+ }
+
+ public Bar getBar() {
+ return bar;
+ }
+
+ public void setBar(Bar b) {
+ bar = b;
+ }
+
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ public void setCurrency(Currency c) {
+ currency = c;
+ }
+
+ public Date getDate() {
+ return date;
+ }
+
+ public void setDate(Date d) {
+ date = d;
+ }
+
+ public String toString() {
+ return a + " " + b + " " + bar + " " + currency + " " + date;
+ }
+
+ public void init() {
+ System.out.println("======== Initializing Foo =========");
+ initialized = true;
+ }
+
+ public void destroy() {
+ System.out.println("======== Destroying Foo =========");
+ destroyed = true;
+ }
+
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ public boolean isDestroyed() {
+ return destroyed;
+ }
+
+ public void update(Map<String,Object> props) {
+ this.props = props;
+ }
+
+ public Map<String, Object> getProps() {
+ return props;
+ }
+
+}
+
diff --git a/src/test/java/org/apache/aries/blueprint/compendium/cm/BaseTest.java b/src/test/java/org/apache/aries/blueprint/compendium/cm/BaseTest.java
deleted file mode 100644
index 11b01c6..0000000
--- a/src/test/java/org/apache/aries/blueprint/compendium/cm/BaseTest.java
+++ /dev/null
@@ -1,111 +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.aries.blueprint.compendium.cm;
-
-import org.junit.After;
-import org.junit.Before;
-import org.ops4j.pax.swissbox.tinybundles.core.TinyBundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.blueprint.container.BlueprintContainer;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public abstract class BaseTest {
-
- private BundleContext bundleContext;
- protected transient Logger log = LoggerFactory.getLogger(getClass());
-
- @Before
- public void setUp() throws Exception {
- String symbolicName = getClass().getSimpleName();
-
- TinyBundle cmBundle = Helper.createTestBundle("blueprint-cm", "1.0.0.SNAPSHOT", "OSGI-INF/blueprint/blueprint-cm.xml");
- TinyBundle testBundle = Helper.createTestBundle(symbolicName, "1.0.0.SNAPSHOT", getBlueprintDescriptor());
-
- this.bundleContext = Helper.createBundleContext(getBundleFilter(), new TinyBundle[] { cmBundle, testBundle });
-
- // must wait for blueprint container to be published then the namespace parser is complete and we are ready for testing
- log.debug("Waiting for BlueprintContainer to be published with symbolicName: {}", symbolicName);
- getOsgiService(BlueprintContainer.class, "(osgi.blueprint.container.symbolicname=" + symbolicName + ")");
- }
-
- @After
- public void tearDown() throws Exception {
- Helper.disposeBundleContext(bundleContext);
- }
-
- /**
- * Return the system bundle context
- * @return
- */
- protected BundleContext getBundleContext() {
- return bundleContext;
- }
-
- /**
- * Gets the bundle descriptor from the classpath.
- * <p/>
- * Return the location(s) of the bundle descriptors from the classpath.
- * Separate multiple locations by comma, or return a single location.
- * <p/>
- * For example override this method and return <tt>OSGI-INF/blueprint/camel-context.xml</tt>
- *
- * @return the location of the bundle descriptor file.
- */
- protected String getBlueprintDescriptor() {
- return null;
- }
-
- /**
- * Gets filter expression of bundle descriptors.
- * Modify this method if you wish to change default behavior.
- *
- * @return filter expression for OSGi bundles.
- */
- protected String getBundleFilter() {
- return Helper.BUNDLE_FILTER;
- }
-
- /**
- * Gets test bundle version.
- * Modify this method if you wish to change default behavior.
- *
- * @return test bundle version
- */
- protected String getBundleVersion() {
- return Helper.BUNDLE_VERSION;
- }
-
- protected <T> T getOsgiService(Class<T> type) {
- return Helper.getOsgiService(bundleContext, type);
- }
-
- protected <T> T getOsgiService(Class<T> type, long timeout) {
- return Helper.getOsgiService(bundleContext, type, timeout);
- }
-
- protected <T> T getOsgiService(Class<T> type, String filter) {
- return Helper.getOsgiService(bundleContext, type, filter);
- }
-
- protected <T> T getOsgiService(Class<T> type, String filter, long timeout) {
- return Helper.getOsgiService(bundleContext, type, filter, timeout);
- }
-
-}
diff --git a/src/test/java/org/apache/aries/blueprint/compendium/cm/CmPropertiesTest.java b/src/test/java/org/apache/aries/blueprint/compendium/cm/CmPropertiesTest.java
deleted file mode 100644
index 4409c68..0000000
--- a/src/test/java/org/apache/aries/blueprint/compendium/cm/CmPropertiesTest.java
+++ /dev/null
@@ -1,63 +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.aries.blueprint.compendium.cm;
-
-import java.util.Hashtable;
-
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-public class CmPropertiesTest extends BaseTest {
-
- @Override
- protected String getBlueprintDescriptor() {
- return "org/apache/aries/blueprint/compendium/cm/CmPropertiesTest.xml";
- }
-
- @Test
- public void test4() throws Exception {
- BundleContext context = getBundleContext();
- ServiceReference sr = Helper.getOsgiServiceReference(context, FooInterface.class, "(key=foo4)", Helper.DEFAULT_TIMEOUT);
- assertNotNull(sr);
-
- FooInterface foo = (FooInterface) context.getService(sr);
- assertNotNull(foo);
- assertNotNull(foo.getProps());
- assertTrue(foo.getProps().isEmpty());
-
- ConfigurationAdmin ca = getOsgiService(ConfigurationAdmin.class);
- Configuration cf = ca.getConfiguration("blueprint-sample-properties.pid", null);
- Hashtable<String,String> props = new Hashtable<String,String>();
- props.put("a", "5");
- cf.update(props);
-
- Thread.sleep(500);
- assertFalse(foo.getProps().isEmpty());
- assertEquals("5", foo.getProps().getProperty("a"));
- }
-
-}
diff --git a/src/test/java/org/apache/aries/blueprint/compendium/cm/Foo.java b/src/test/java/org/apache/aries/blueprint/compendium/cm/Foo.java
deleted file mode 100644
index d2eac1d..0000000
--- a/src/test/java/org/apache/aries/blueprint/compendium/cm/Foo.java
+++ /dev/null
@@ -1,56 +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.aries.blueprint.compendium.cm;
-
-import java.util.Properties;
-
-public class Foo implements FooInterface {
-
- public Foo() {
- }
-
- private int a;
- private String b;
- private Properties props;
-
- public int getA() {
- return a;
- }
-
- public void setA(int i) {
- a = i;
- }
-
- public String getB() {
- return b;
- }
-
- public void setB(String i) {
- b = i;
- }
-
- public Properties getProps() {
- return props;
- }
-
- public void setProps(Properties props) {
- this.props = props;
- }
-}
-
diff --git a/src/test/java/org/apache/aries/blueprint/compendium/cm/FooInterface.java b/src/test/java/org/apache/aries/blueprint/compendium/cm/FooInterface.java
deleted file mode 100644
index 9ab860d..0000000
--- a/src/test/java/org/apache/aries/blueprint/compendium/cm/FooInterface.java
+++ /dev/null
@@ -1,27 +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.aries.blueprint.compendium.cm;
-
-import java.util.Properties;
-
-public interface FooInterface {
-
- Properties getProps();
-
-}
diff --git a/src/test/java/org/apache/aries/blueprint/compendium/cm/Helper.java b/src/test/java/org/apache/aries/blueprint/compendium/cm/Helper.java
deleted file mode 100644
index 56c749f..0000000
--- a/src/test/java/org/apache/aries/blueprint/compendium/cm/Helper.java
+++ /dev/null
@@ -1,781 +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.aries.blueprint.compendium.cm;
-
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Dictionary;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Scanner;
-import java.util.jar.JarInputStream;
-
-import de.kalpatec.pojosr.framework.PojoServiceRegistryFactoryImpl;
-import de.kalpatec.pojosr.framework.launch.BundleDescriptor;
-import de.kalpatec.pojosr.framework.launch.ClasspathScanner;
-import de.kalpatec.pojosr.framework.launch.PojoServiceRegistry;
-import de.kalpatec.pojosr.framework.launch.PojoServiceRegistryFactory;
-import org.ops4j.pax.swissbox.tinybundles.core.TinyBundle;
-import org.ops4j.pax.swissbox.tinybundles.core.TinyBundles;
-import org.osgi.framework.BundleContext;
-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.ServiceReference;
-import org.osgi.util.tracker.ServiceTracker;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-public final class Helper {
-
- public static final long DEFAULT_TIMEOUT = 30000;
- public static final String BUNDLE_FILTER = "(Bundle-SymbolicName=*)";
- public static final String BUNDLE_VERSION = "1.0.0";
- private static final transient Logger LOG = LoggerFactory.getLogger(Helper.class);
-
- private Helper() {
- }
-
- public static BundleContext createBundleContext(String name, String descriptors, boolean includeTestBundle) throws Exception {
- return createBundleContext(name, descriptors, includeTestBundle, BUNDLE_FILTER, BUNDLE_VERSION);
- }
-
- public static BundleContext createBundleContext(String name, String descriptors, boolean includeTestBundle,
- String bundleFilter, String testBundleVersion) throws Exception {
- TinyBundle bundle = null;
-
- if (includeTestBundle) {
- // add ourselves as a bundle
- bundle = createTestBundle(name, testBundleVersion, descriptors);
- }
-
- return createBundleContext(bundleFilter, new TinyBundle[] { bundle });
- }
-
- public static BundleContext createBundleContext(String bundleFilter, TinyBundle[] testBundles) throws Exception {
- deleteDirectory("target/bundles");
- createDirectory("target/bundles");
-
- // ensure pojosr stores bundles in an unique target directory
- System.setProperty("org.osgi.framework.storage", "target/bundles/" + System.currentTimeMillis());
-
- // get the bundles
- List<BundleDescriptor> bundles = getBundleDescriptors(bundleFilter);
-
- if (testBundles != null) {
- for (TinyBundle bundle : testBundles) {
- File tmp = File.createTempFile("test-", ".jar", new File("target/bundles/"));
- tmp.delete();
- bundles.add(getBundleDescriptor(tmp.getPath(), bundle));
- }
- }
-
- if (LOG.isDebugEnabled()) {
- for (int i = 0; i < bundles.size(); i++) {
- BundleDescriptor desc = bundles.get(i);
- LOG.debug("Bundle #{} -> {}", i, desc);
- }
- }
-
- // setup pojosr to use our bundles
- Map<String, List<BundleDescriptor>> config = new HashMap<String, List<BundleDescriptor>>();
- config.put(PojoServiceRegistryFactory.BUNDLE_DESCRIPTORS, bundles);
-
- // create pojorsr osgi service registry
- PojoServiceRegistry reg = new PojoServiceRegistryFactoryImpl().newPojoServiceRegistry(config);
- return reg.getBundleContext();
- }
-
- public static void disposeBundleContext(BundleContext bundleContext) throws BundleException {
- try {
- if (bundleContext != null) {
- bundleContext.getBundle().stop();
- }
- } finally {
- System.clearProperty("org.osgi.framework.storage");
- }
- }
-
- public static <T> T getOsgiService(BundleContext bundleContext, Class<T> type, long timeout) {
- return getOsgiService(bundleContext, type, null, timeout);
- }
-
- public static <T> T getOsgiService(BundleContext bundleContext, Class<T> type) {
- return getOsgiService(bundleContext, type, null, DEFAULT_TIMEOUT);
- }
-
- public static <T> T getOsgiService(BundleContext bundleContext, Class<T> type, String filter) {
- return getOsgiService(bundleContext, type, filter, DEFAULT_TIMEOUT);
- }
-
- public static <T> ServiceReference getOsgiServiceReference(BundleContext bundleContext, Class<T> type, String filter, long timeout) {
- ServiceTracker tracker = null;
- try {
- String flt;
- if (filter != null) {
- if (filter.startsWith("(")) {
- flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")" + filter + ")";
- } else {
- flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")(" + filter + "))";
- }
- } else {
- flt = "(" + Constants.OBJECTCLASS + "=" + type.getName() + ")";
- }
- Filter osgiFilter = FrameworkUtil.createFilter(flt);
- tracker = new ServiceTracker(bundleContext, osgiFilter, null);
- tracker.open(true);
- // Note that the tracker is not closed to keep the reference
- // This is buggy, as the service reference may change i think
- Object svc = tracker.waitForService(timeout);
- if (svc == null) {
- Dictionary<?, ?> dic = bundleContext.getBundle().getHeaders();
- System.err.println("Test bundle headers: " + explode(dic));
-
- for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, null))) {
- System.err.println("ServiceReference: " + ref + ", bundle: " + ref.getBundle() + ", symbolicName: " + ref.getBundle().getSymbolicName());
- }
-
- for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, flt))) {
- System.err.println("Filtered ServiceReference: " + ref + ", bundle: " + ref.getBundle() + ", symbolicName: " + ref.getBundle().getSymbolicName());
- }
-
- throw new RuntimeException("Gave up waiting for service " + flt);
- }
- return tracker.getServiceReference();
- } catch (InvalidSyntaxException e) {
- throw new IllegalArgumentException("Invalid filter", e);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-
- public static <T> T getOsgiService(BundleContext bundleContext, Class<T> type, String filter, long timeout) {
- ServiceTracker tracker = null;
- try {
- String flt;
- if (filter != null) {
- if (filter.startsWith("(")) {
- flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")" + filter + ")";
- } else {
- flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")(" + filter + "))";
- }
- } else {
- flt = "(" + Constants.OBJECTCLASS + "=" + type.getName() + ")";
- }
- Filter osgiFilter = FrameworkUtil.createFilter(flt);
- tracker = new ServiceTracker(bundleContext, osgiFilter, null);
- tracker.open(true);
- // Note that the tracker is not closed to keep the reference
- // This is buggy, as the service reference may change i think
- Object svc = tracker.waitForService(timeout);
- if (svc == null) {
- Dictionary<?, ?> dic = bundleContext.getBundle().getHeaders();
- System.err.println("Test bundle headers: " + explode(dic));
-
- for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, null))) {
- System.err.println("ServiceReference: " + ref + ", bundle: " + ref.getBundle() + ", symbolicName: " + ref.getBundle().getSymbolicName());
- }
-
- for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, flt))) {
- System.err.println("Filtered ServiceReference: " + ref + ", bundle: " + ref.getBundle() + ", symbolicName: " + ref.getBundle().getSymbolicName());
- }
-
- throw new RuntimeException("Gave up waiting for service " + flt);
- }
- return type.cast(svc);
- } catch (InvalidSyntaxException e) {
- throw new IllegalArgumentException("Invalid filter", e);
- } catch (InterruptedException e) {
- throw new RuntimeException(e);
- }
- }
-
- protected static TinyBundle createTestBundle(String name, String version, String descriptors) throws FileNotFoundException, MalformedURLException {
- TinyBundle bundle = TinyBundles.newBundle();
- for (URL url : getBlueprintDescriptors(descriptors)) {
- LOG.info("Using Blueprint XML file: " + url.getFile());
- bundle.add("OSGI-INF/blueprint/blueprint-" + url.getFile().replace("/", "-"), url);
- }
- bundle.set("Manifest-Version", "2")
- .set("Bundle-ManifestVersion", "2")
- .set("Bundle-SymbolicName", name)
- .set("Bundle-Version", version);
- return bundle;
- }
-
- /**
- * Explode the dictionary into a <code>,</code> delimited list of <code>key=value</code> pairs.
- */
- private static String explode(Dictionary<?, ?> dictionary) {
- Enumeration<?> keys = dictionary.keys();
- StringBuffer result = new StringBuffer();
- while (keys.hasMoreElements()) {
- Object key = keys.nextElement();
- result.append(String.format("%s=%s", key, dictionary.get(key)));
- if (keys.hasMoreElements()) {
- result.append(", ");
- }
- }
- return result.toString();
- }
-
- /**
- * Provides an iterable collection of references, even if the original array is <code>null</code>.
- */
- private static Collection<ServiceReference> asCollection(ServiceReference[] references) {
- return references == null ? new ArrayList<ServiceReference>(0) : Arrays.asList(references);
- }
-
- /**
- * Gets list of bundle descriptors.
- * @param bundleFilter Filter expression for OSGI bundles.
- *
- * @return List pointers to OSGi bundles.
- * @throws Exception If looking up the bundles fails.
- */
- private static List<BundleDescriptor> getBundleDescriptors(final String bundleFilter) throws Exception {
- return new ClasspathScanner().scanForBundles(bundleFilter);
- }
-
- /**
- * Gets the bundle descriptors as {@link URL} resources.
- *
- * @param descriptors the bundle descriptors, can be separated by comma
- * @return the bundle descriptors.
- * @throws FileNotFoundException is thrown if a bundle descriptor cannot be found
- */
- private static Collection<URL> getBlueprintDescriptors(String descriptors) throws FileNotFoundException, MalformedURLException {
- List<URL> answer = new ArrayList<URL>();
- String descriptor = descriptors;
- if (descriptor != null) {
- // there may be more resources separated by comma
- Iterator<Object> it = createIterator(descriptor);
- while (it.hasNext()) {
- String s = (String) it.next();
- LOG.trace("Resource descriptor: {}", s);
-
- // remove leading / to be able to load resource from the classpath
- s = stripLeadingSeparator(s);
-
- // if there is wildcards for *.xml then we need to find the urls from the package
- if (s.endsWith("*.xml")) {
- String packageName = s.substring(0, s.length() - 5);
- // remove trailing / to be able to load resource from the classpath
- Enumeration<URL> urls = loadResourcesAsURL(packageName);
- while (urls.hasMoreElements()) {
- URL url = urls.nextElement();
- File dir = new File(url.getFile());
- if (dir.isDirectory()) {
- File[] files = dir.listFiles();
- if (files != null) {
- for (File file : files) {
- if (file.isFile() && file.exists() && file.getName().endsWith(".xml")) {
- String name = packageName + file.getName();
- LOG.debug("Resolving resource: {}", name);
- URL xmlUrl = loadResourceAsURL(name);
- if (xmlUrl != null) {
- answer.add(xmlUrl);
- }
- }
- }
- }
- }
- }
- } else {
- LOG.debug("Resolving resource: {}", s);
- URL url = resolveMandatoryResourceAsUrl(s);
- if (url == null) {
- throw new FileNotFoundException("Resource " + s + " not found");
- }
- answer.add(url);
- }
- }
- } else {
- throw new IllegalArgumentException("No bundle descriptor configured. Override getBlueprintDescriptor() or getBlueprintDescriptors() method");
- }
-
- if (answer.isEmpty()) {
- throw new IllegalArgumentException("Cannot find any resources in classpath from descriptor " + descriptors);
- }
- return answer;
- }
-
- private static BundleDescriptor getBundleDescriptor(String path, TinyBundle bundle) throws Exception {
- File file = new File(path);
- FileOutputStream fos = new FileOutputStream(file, true);
- try {
- copy(bundle.build(), fos);
- } finally {
- close(fos);
- }
-
- FileInputStream fis = null;
- JarInputStream jis = null;
- try {
- fis = new FileInputStream(file);
- jis = new JarInputStream(fis);
- Map<String, String> headers = new HashMap<String, String>();
- for (Map.Entry<Object, Object> entry : jis.getManifest().getMainAttributes().entrySet()) {
- headers.put(entry.getKey().toString(), entry.getValue().toString());
- }
-
- return new BundleDescriptor(
- bundle.getClass().getClassLoader(),
- new URL("jar:" + file.toURI().toString() + "!/"),
- headers);
- } finally {
- close(fis, jis);
- }
- }
-
- /**
- * Closes the given resource if it is available, logging any closing exceptions to the given log.
- *
- * @param closeable the object to close
- * @param name the name of the resource
- * @param log the log to use when reporting closure warnings, will use this class's own {@link Logger} if <tt>log == null</tt>
- */
- public static void close(Closeable closeable, String name, Logger log) {
- if (closeable != null) {
- try {
- closeable.close();
- } catch (IOException e) {
- if (log == null) {
- // then fallback to use the own Logger
- log = LOG;
- }
- if (name != null) {
- log.warn("Cannot close: " + name + ". Reason: " + e.getMessage(), e);
- } else {
- log.warn("Cannot close. Reason: " + e.getMessage(), e);
- }
- }
- }
- }
-
- /**
- * Closes the given resource if it is available.
- *
- * @param closeable the object to close
- * @param name the name of the resource
- */
- public static void close(Closeable closeable, String name) {
- close(closeable, name, LOG);
- }
-
- /**
- * Closes the given resource if it is available.
- *
- * @param closeable the object to close
- */
- public static void close(Closeable closeable) {
- close(closeable, null, LOG);
- }
-
- /**
- * Closes the given resources if they are available.
- *
- * @param closeables the objects to close
- */
- public static void close(Closeable... closeables) {
- for (Closeable closeable : closeables) {
- close(closeable);
- }
- }
-
- private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;
- private static final String DEFAULT_DELIMITER = ",";
-
- public static int copy(InputStream input, OutputStream output) throws IOException {
- return copy(input, output, DEFAULT_BUFFER_SIZE);
- }
-
- public static int copy(final InputStream input, final OutputStream output, int bufferSize) throws IOException {
- int avail = input.available();
- if (avail > 262144) {
- avail = 262144;
- }
- if (avail > bufferSize) {
- bufferSize = avail;
- }
-
- final byte[] buffer = new byte[bufferSize];
- int n = input.read(buffer);
- int total = 0;
- while (-1 != n) {
- output.write(buffer, 0, n);
- total += n;
- n = input.read(buffer);
- }
- output.flush();
- return total;
- }
-
- /**
- * Creates an iterator over the value if the value is a collection, an
- * Object[], a String with values separated by comma,
- * or a primitive type array; otherwise to simplify the caller's code,
- * we just create a singleton collection iterator over a single value
- * <p/>
- * Will default use comma for String separating String values.
- * This method does <b>not</b> allow empty values
- *
- * @param value the value
- * @return the iterator
- */
- public static Iterator<Object> createIterator(Object value) {
- return createIterator(value, DEFAULT_DELIMITER);
- }
-
- /**
- * Creates an iterator over the value if the value is a collection, an
- * Object[], a String with values separated by the given delimiter,
- * or a primitive type array; otherwise to simplify the caller's
- * code, we just create a singleton collection iterator over a single value
- * <p/>
- * This method does <b>not</b> allow empty values
- *
- * @param value the value
- * @param delimiter delimiter for separating String values
- * @return the iterator
- */
- public static Iterator<Object> createIterator(Object value, String delimiter) {
- return createIterator(value, delimiter, false);
- }
-
- /**
- * Creates an iterator over the value if the value is a collection, an
- * Object[], a String with values separated by the given delimiter,
- * or a primitive type array; otherwise to simplify the caller's
- * code, we just create a singleton collection iterator over a single value
- *
- * @param value the value
- * @param delimiter delimiter for separating String values
- * @param allowEmptyValues whether to allow empty values
- * @return the iterator
- */
- @SuppressWarnings("unchecked")
- public static Iterator<Object> createIterator(Object value, String delimiter, final boolean allowEmptyValues) {
- if (value == null) {
- return Collections.emptyList().iterator();
- } else if (value instanceof Iterator) {
- return (Iterator<Object>)value;
- } else if (value instanceof Iterable) {
- return ((Iterable<Object>)value).iterator();
- } else if (value.getClass().isArray()) {
- // TODO we should handle primitive array types?
- List<Object> list = Arrays.asList((Object[])value);
- return list.iterator();
- } else if (value instanceof NodeList) {
- // lets iterate through DOM results after performing XPaths
- final NodeList nodeList = (NodeList) value;
- return cast(new Iterator<Node>() {
- int idx = -1;
-
- public boolean hasNext() {
- return (idx + 1) < nodeList.getLength();
- }
-
- public Node next() {
- idx++;
- return nodeList.item(idx);
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
- });
- } else if (value instanceof String) {
- final String s = (String) value;
-
- // this code is optimized to only use a Scanner if needed, eg there is a delimiter
-
- if (delimiter != null && s.contains(delimiter)) {
- // use a scanner if it contains the delimiter
- Scanner scanner = new Scanner((String)value);
-
- if (DEFAULT_DELIMITER.equals(delimiter)) {
- // we use the default delimiter which is a comma, then cater for bean expressions with OGNL
- // which may have balanced parentheses pairs as well.
- // if the value contains parentheses we need to balance those, to avoid iterating
- // in the middle of parentheses pair, so use this regular expression (a bit hard to read)
- // the regexp will split by comma, but honor parentheses pair that may include commas
- // as well, eg if value = "bean=foo?method=killer(a,b),bean=bar?method=great(a,b)"
- // then the regexp will split that into two:
- // -> bean=foo?method=killer(a,b)
- // -> bean=bar?method=great(a,b)
- // http://stackoverflow.com/questions/1516090/splitting-a-title-into-separate-parts
- delimiter = ",(?!(?:[^\\(,]|[^\\)],[^\\)])+\\))";
- }
-
- scanner.useDelimiter(delimiter);
- return cast(scanner);
- } else {
- // use a plain iterator that returns the value as is as there are only a single value
- return cast(new Iterator<String>() {
- int idx = -1;
-
- public boolean hasNext() {
- return idx + 1 == 0 && (allowEmptyValues || isNotEmpty(s));
- }
-
- public String next() {
- idx++;
- return s;
- }
-
- public void remove() {
- throw new UnsupportedOperationException();
- }
- });
- }
- } else {
- return Collections.singletonList(value).iterator();
- }
- }
-
- /**
- * Tests whether the value is <b>not</b> <tt>null</tt> or an empty string.
- *
- * @param value the value, if its a String it will be tested for text length as well
- * @return true if <b>not</b> empty
- */
- public static boolean isNotEmpty(Object value) {
- if (value == null) {
- return false;
- } else if (value instanceof String) {
- String text = (String) value;
- return text.trim().length() > 0;
- } else {
- return true;
- }
- }
-
- public static <T> Iterator<T> cast(Iterator<?> p) {
- return (Iterator<T>) p;
- }
-
- /**
- * Strip any leading separators
- */
- public static String stripLeadingSeparator(String name) {
- if (name == null) {
- return null;
- }
- while (name.startsWith("/") || name.startsWith(File.separator)) {
- name = name.substring(1);
- }
- return name;
- }
-
- /**
- * Attempts to load the given resources from the given package name using the thread context
- * class loader or the class loader used to load this class
- *
- * @param packageName the name of the package to load its resources
- * @return the URLs for the resources or null if it could not be loaded
- */
- public static Enumeration<URL> loadResourcesAsURL(String packageName) {
- Enumeration<URL> url = null;
-
- ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
- if (contextClassLoader != null) {
- try {
- url = contextClassLoader.getResources(packageName);
- } catch (IOException e) {
- // ignore
- }
- }
- if (url == null) {
- try {
- url = Helper.class.getClassLoader().getResources(packageName);
- } catch (IOException e) {
- // ignore
- }
- }
-
- return url;
- }
-
- /**
- * Attempts to load the given resource as a stream using the thread context
- * class loader or the class loader used to load this class
- *
- * @param name the name of the resource to load
- * @return the stream or null if it could not be loaded
- */
- public static URL loadResourceAsURL(String name) {
- URL url = null;
-
- String resolvedName = resolveUriPath(name);
- ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
- if (contextClassLoader != null) {
- url = contextClassLoader.getResource(resolvedName);
- }
- if (url == null) {
- url = Helper.class.getClassLoader().getResource(resolvedName);
- }
-
- return url;
- }
-
- /**
- * Helper operation used to remove relative path notation from
- * resources. Most critical for resources on the Classpath
- * as resource loaders will not resolve the relative paths correctly.
- *
- * @param name the name of the resource to load
- * @return the modified or unmodified string if there were no changes
- */
- private static String resolveUriPath(String name) {
- String answer = name;
- if (answer.indexOf("//") > -1) {
- answer = answer.replaceAll("//", "/");
- }
- if (answer.indexOf("../") > -1) {
- answer = answer.replaceAll("[A-Za-z0-9]*/\\.\\./", "");
- }
- if (answer.indexOf("./") > -1) {
- answer = answer.replaceAll("\\./", "");
- }
- return answer;
- }
-
- /**
- * Resolves the mandatory resource.
- *
- * @param uri uri of the resource
- * @return the resource as an {@link InputStream}. Remember to close this stream after usage.
- * @throws java.io.FileNotFoundException is thrown if the resource file could not be found
- * @throws java.net.MalformedURLException if the URI is malformed
- */
- public static URL resolveMandatoryResourceAsUrl(String uri) throws FileNotFoundException, MalformedURLException {
- if (uri.startsWith("file:")) {
- // check if file exists first
- String name = after(uri, "file:");
- File file = new File(name);
- if (!file.exists()) {
- throw new FileNotFoundException("File " + file + " not found");
- }
- return new URL(uri);
- } else if (uri.startsWith("http:")) {
- return new URL(uri);
- } else if (uri.startsWith("classpath:")) {
- uri = after(uri, "classpath:");
- }
-
- // load from classpath by default
- URL url = loadResourceAsURL(uri);
- if (url == null) {
- throw new FileNotFoundException("Cannot find resource in classpath for URI: " + uri);
- } else {
- return url;
- }
- }
-
- public static String after(String text, String after) {
- if (!text.contains(after)) {
- return null;
- }
- return text.substring(text.indexOf(after) + after.length());
- }
-
- /**
- * Recursively delete a directory, useful to zapping test data
- *
- * @param file the directory to be deleted
- * @return <tt>false</tt> if error deleting directory
- */
- public static boolean deleteDirectory(String file) {
- return deleteDirectory(new File(file));
- }
-
- /**
- * Recursively delete a directory, useful to zapping test data
- *
- * @param file the directory to be deleted
- * @return <tt>false</tt> if error deleting directory
- */
- public static boolean deleteDirectory(File file) {
- int tries = 0;
- int maxTries = 5;
- boolean exists = true;
- while (exists && (tries < maxTries)) {
- recursivelyDeleteDirectory(file);
- tries++;
- exists = file.exists();
- if (exists) {
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- // Ignore
- }
- }
- }
- return !exists;
- }
-
- private static void recursivelyDeleteDirectory(File file) {
- if (!file.exists()) {
- return;
- }
-
- if (file.isDirectory()) {
- File[] files = file.listFiles();
- for (File child : files) {
- recursivelyDeleteDirectory(child);
- }
- }
- boolean success = file.delete();
- if (!success) {
- LOG.warn("Deletion of file: " + file.getAbsolutePath() + " failed");
- }
- }
-
- /**
- * create the directory
- *
- * @param file the directory to be created
- */
- public static void createDirectory(String file) {
- File dir = new File(file);
- dir.mkdirs();
- }
-
-
-}
diff --git a/src/test/java/org/apache/aries/blueprint/compendium/cm/ManagedServiceFactoryTest.java b/src/test/java/org/apache/aries/blueprint/compendium/cm/ManagedServiceFactoryTest.java
deleted file mode 100644
index be68982..0000000
--- a/src/test/java/org/apache/aries/blueprint/compendium/cm/ManagedServiceFactoryTest.java
+++ /dev/null
@@ -1,141 +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.aries.blueprint.compendium.cm;
-
-import java.util.Hashtable;
-
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-public class ManagedServiceFactoryTest extends BaseTest {
-
- @Override
- protected String getBlueprintDescriptor() {
- return "org/apache/aries/blueprint/compendium/cm/ManagedServiceFactoryTest.xml";
- }
-
- @Test
- public void test1() throws Exception {
- ConfigurationAdmin ca = getOsgiService(ConfigurationAdmin.class);
- Configuration cf = ca.createFactoryConfiguration("blueprint-sample-managed-service-factory", null);
- Hashtable<String,String> props = new Hashtable<String,String>();
- props.put("a", "5");
- cf.update(props);
-
- BundleContext context = getBundleContext();
- ServiceReference sr = Helper.getOsgiServiceReference(context, Foo.class, "(key=foo1)", Helper.DEFAULT_TIMEOUT);
- assertNotNull(sr);
- Foo foo = (Foo) context.getService(sr);
- assertNotNull(foo);
- assertEquals(5, foo.getA());
- assertEquals("default", foo.getB());
- assertEquals("5", sr.getProperty("a"));
- assertNull(sr.getProperty("b"));
-
- props = new Hashtable<String,String>();
- props.put("a", "5");
- props.put("b", "foo");
- cf.update(props);
- Thread.sleep(500);
-
- // No update of bean after creation
- assertEquals(5, foo.getA());
- assertEquals("default", foo.getB());
-
- // Only initial update of service properties
- assertEquals("5", sr.getProperty("a"));
- assertNull(sr.getProperty("b"));
- }
-
- @Test
- public void test2() throws Exception {
- ConfigurationAdmin ca = getOsgiService(ConfigurationAdmin.class);
- Configuration cf = ca.createFactoryConfiguration("blueprint-sample-managed-service-factory2", null);
- Hashtable<String,String> props = new Hashtable<String,String>();
- props.put("a", "5");
- cf.update(props);
-
- BundleContext context = getBundleContext();
- ServiceReference sr = Helper.getOsgiServiceReference(context, Foo.class, "(key=foo2)", Helper.DEFAULT_TIMEOUT);
- assertNotNull(sr);
-
- Foo foo = (Foo) context.getService(sr);
- assertNotNull(foo);
- assertEquals(5, foo.getA());
- assertEquals("default", foo.getB());
- assertNull(sr.getProperty("a"));
- assertNull(sr.getProperty("b"));
-
- props = new Hashtable<String,String>();
- props.put("a", "5");
- props.put("b", "foo");
- cf.update(props);
-
- // Update after creation
- Thread.sleep(500);
- assertEquals(5, foo.getA());
- assertEquals("foo", foo.getB());
-
- // No update of service properties
- assertNull(sr.getProperty("a"));
- assertNull(sr.getProperty("b"));
- }
-
- @Test
- public void test3() throws Exception {
- ConfigurationAdmin ca = getOsgiService(ConfigurationAdmin.class);
- Configuration cf = ca.createFactoryConfiguration("blueprint-sample-managed-service-factory3", null);
- Hashtable<String,String> props = new Hashtable<String,String>();
- props.put("a", "5");
- cf.update(props);
-
- BundleContext context = getBundleContext();
- ServiceReference sr = Helper.getOsgiServiceReference(context, Foo.class, "(key=foo3)", Helper.DEFAULT_TIMEOUT);
- assertNotNull(sr);
-
- Foo foo = (Foo) context.getService(sr);
- assertNotNull(foo);
- assertEquals(5, foo.getA());
- assertEquals("default", foo.getB());
- assertEquals("5", sr.getProperty("a"));
- assertNull(sr.getProperty("b"));
-
- props = new Hashtable<String,String>();
- props.put("a", "5");
- props.put("b", "foo");
- cf.update(props);
-
- // Update after creation
- Thread.sleep(500);
- assertEquals(5, foo.getA());
- assertEquals("foo", foo.getB());
-
- // Update of service properties
- assertEquals("5", sr.getProperty("a"));
- assertEquals("foo", sr.getProperty("b"));
- }
-
-}
diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties
deleted file mode 100644
index 4d791eb..0000000
--- a/src/test/resources/log4j.properties
+++ /dev/null
@@ -1,42 +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.
-## ------------------------------------------------------------------------
-
-#
-# The logging properties used for testing
-#
-log4j.rootLogger=DEBUG, out, file
-
-#log4j.logger.de.kalpatec.pojosr=DEBUG
-#log4j.logger.org.apache.camel.test.blueprint=DEBUG
-#log4j.logger.org.apache.camel=DEBUG
-#log4j.logger.org.apache.camel.blueprint=TRACE
-
-# CONSOLE appender not used by default
-log4j.appender.out=org.apache.log4j.ConsoleAppender
-log4j.appender.out.layout=org.apache.log4j.PatternLayout
-log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
-# MDC
-#log4j.appender.out.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %-10.10X{camel.breadcrumbId} - %-10.10X{camel.exchangeId} - %-10.10X{camel.correlationId} - %-10.10X{camel.routeId} - %m%n
-
-# File appender
-log4j.appender.file=org.apache.log4j.FileAppender
-log4j.appender.file.layout=org.apache.log4j.PatternLayout
-log4j.appender.file.file=target/camel-test-blueprint.log
-log4j.appender.file.append=true
-log4j.appender.file.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
-# MDC
-#log4j.appender.file.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %-10.10X{camel.breadcrumbId} - %-10.10X{camel.exchangeId} - %-10.10X{camel.correlationId} - %-10.10X{camel.routeId} - %m%n
diff --git a/src/test/resources/org/apache/aries/blueprint/compendium/cm/CmPropertiesTest.xml b/src/test/resources/org/apache/aries/blueprint/compendium/cm/CmPropertiesTest.xml
deleted file mode 100644
index b705ae3..0000000
--- a/src/test/resources/org/apache/aries/blueprint/compendium/cm/CmPropertiesTest.xml
+++ /dev/null
@@ -1,34 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!--
- 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.2.0"
- xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.2.0">
-
- <cm:cm-properties id="myProps" persistent-id="blueprint-sample-properties.pid" />
-
- <service id="myService" auto-export="interfaces">
- <service-properties>
- <entry key="key" value="foo4" />
- <!--<cm:cm-properties persistent-id="org.foo.bar" />-->
- </service-properties>
- <bean class="org.apache.aries.blueprint.compendium.cm.Foo">
- <property name="props" ref="myProps" />
- </bean>
- </service>
-
-
-</blueprint>
diff --git a/src/test/resources/org/apache/aries/blueprint/compendium/cm/ManagedServiceFactoryTest.xml b/src/test/resources/org/apache/aries/blueprint/compendium/cm/ManagedServiceFactoryTest.xml
deleted file mode 100644
index 457e8a8..0000000
--- a/src/test/resources/org/apache/aries/blueprint/compendium/cm/ManagedServiceFactoryTest.xml
+++ /dev/null
@@ -1,61 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!--
- 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.
- -->
-<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
- xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0">
-
- <cm:managed-service-factory id="managed-service-factory"
- factory-pid="blueprint-sample-managed-service-factory"
- interface="org.apache.aries.blueprint.compendium.cm.Foo">
- <service-properties>
- <entry key="key" value="foo1" />
- <cm:cm-properties persistent-id="" />
- </service-properties>
- <cm:managed-component class="org.apache.aries.blueprint.compendium.cm.Foo">
- <cm:managed-properties persistent-id="" />
- <property name="a" value="1" />
- <property name="b" value="default" />
- </cm:managed-component>
- </cm:managed-service-factory>
-
- <cm:managed-service-factory id="managed-service-factory2"
- factory-pid="blueprint-sample-managed-service-factory2"
- interface="org.apache.aries.blueprint.compendium.cm.Foo">
- <service-properties>
- <entry key="key" value="foo2" />
- </service-properties>
- <cm:managed-component class="org.apache.aries.blueprint.compendium.cm.Foo">
- <cm:managed-properties persistent-id="" update-strategy="container-managed" />
- <property name="a" value="1" />
- <property name="b" value="default" />
- </cm:managed-component>
- </cm:managed-service-factory>
-
- <cm:managed-service-factory id="managed-service-factory3"
- factory-pid="blueprint-sample-managed-service-factory3"
- interface="org.apache.aries.blueprint.compendium.cm.Foo">
- <service-properties>
- <entry key="key" value="foo3" />
- <cm:cm-properties persistent-id="" update="true"/>
- </service-properties>
- <cm:managed-component class="org.apache.aries.blueprint.compendium.cm.Foo">
- <cm:managed-properties persistent-id="" update-strategy="container-managed" />
- <property name="a" value="1" />
- <property name="b" value="default" />
- </cm:managed-component>
- </cm:managed-service-factory>
-
-</blueprint>
diff --git a/src/test/resources/test.properties b/src/test/resources/test.properties
new file mode 100644
index 0000000..23ffda0
--- /dev/null
+++ b/src/test/resources/test.properties
@@ -0,0 +1,20 @@
+################################################################################
+#
+# 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.
+#
+################################################################################
+
+key.b=1
diff --git a/src/test/resources/test.xml b/src/test/resources/test.xml
new file mode 100644
index 0000000..9e57a1a
--- /dev/null
+++ b/src/test/resources/test.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+ 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.
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.2.0"
+ default-availability="optional">
+
+ <type-converters>
+ <bean id="converter1" class="org.apache.aries.blueprint.sample.DateTypeConverter">
+ <property name="format" value="yyyy.MM.dd" />
+ </bean>
+ <bean id="converter2"
+ class="org.apache.aries.blueprint.sample.CurrencyTypeConverter" />
+
+ </type-converters>
+
+ <ext:property-placeholder placeholder-prefix="$["
+ placeholder-suffix="]" ignore-missing-locations="true"
+ system-properties="override">
+ <ext:default-properties>
+ <ext:property name="name" value="value" />
+ <ext:property name="a" value="Hello " />
+ <ext:property name="b" value="FooBar" />
+ <ext:property name="key.b" value="-1" />
+ </ext:default-properties>
+ <ext:location>file:///url</ext:location>
+ <ext:location>classpath:test.properties</ext:location>
+ </ext:property-placeholder>
+
+ <bean id="foo" class="org.apache.aries.blueprint.sample.Foo"
+ init-method="init" destroy-method="destroy">
+ <property name="a" value="5" />
+ <property name="b" value="$[key.b]" />
+ <property name="bar" ref="bar" />
+ <property name="currency">
+ <value>PLN</value>
+ </property>
+ <property name="date">
+ <value>2009.04.17</value>
+ </property>
+ </bean>
+
+ <bean id="bar" class="org.apache.aries.blueprint.sample.Bar">
+ <property name="value" value="$[a]$[b]">
+ <!--value>Hello FooBar</value-->
+ </property>
+ <property name="list">
+ <list>
+ <value>a list element</value>
+ <value type="java.lang.Integer">5</value>
+ </list>
+ </property>
+ </bean>
+
+</blueprint>
+
diff --git a/src/test/resources/test2.xml b/src/test/resources/test2.xml
new file mode 100644
index 0000000..40f093a
--- /dev/null
+++ b/src/test/resources/test2.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!--
+ 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.
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.2.0"
+ default-availability="optional">
+
+ <ext:property-placeholder placeholder-prefix="$["
+ placeholder-suffix="]" ignore-missing-locations="true"
+ system-properties="override">
+ <ext:default-properties>
+ <ext:property name="c" value="FooBar" />
+ </ext:default-properties>
+ </ext:property-placeholder>
+
+</blueprint>
+