Move the iPOJO API in the trunk.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@742381 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/api/LICENSE b/ipojo/api/LICENSE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/ipojo/api/LICENSE
@@ -0,0 +1,202 @@
+
+ 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/ipojo/api/LICENSE.asm b/ipojo/api/LICENSE.asm
new file mode 100644
index 0000000..9496b17
--- /dev/null
+++ b/ipojo/api/LICENSE.asm
@@ -0,0 +1,28 @@
+
+ ASM: a very small and fast Java bytecode manipulation framework
+ Copyright (c) 2000-2005 INRIA, France Telecom
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ 3. Neither the name of the copyright holders nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/ipojo/api/NOTICE b/ipojo/api/NOTICE
new file mode 100644
index 0000000..6b4ac5d
--- /dev/null
+++ b/ipojo/api/NOTICE
@@ -0,0 +1,27 @@
+Apache Felix iPOJO API
+Copyright 2008 The Apache Software Foundation
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Copyright (c) 2000-2005 INRIA, France Telecom
+Licensed under BSD License.
+
+II. Used Software
+
+This product uses software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org).
+Copyright (c) OSGi Alliance (2000, 2007).
+Licensed under the Apache License 2.0.
+
+III. License Summary
+- Apache License 2.0
+- BSD Licence
diff --git a/ipojo/api/pom.xml b/ipojo/api/pom.xml
new file mode 100644
index 0000000..234dabb
--- /dev/null
+++ b/ipojo/api/pom.xml
@@ -0,0 +1,102 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>bundle</packaging>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.api
+ </artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <name>iPOJO API</name>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <version>1.4.2</version>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>${pom.artifactId}
+ </Bundle-SymbolicName>
+ <Import-Package>!org.objectweb.asm.tree, *</Import-Package>
+ <Export-Package>org.apache.felix.ipojo.api
+ </Export-Package>
+ <Private-Package>org.apache.felix.ipojo.manipulation,
+ org.apache.felix.ipojo.manipulation.annotations,
+ org.objectweb.asm.commons, org.objectweb.asm</Private-Package>
+ <Include-Resource> META-INF/LICENCE=LICENSE,
+ META-INF/NOTICE=NOTICE, META-INF/LICENCE.asm=LICENSE.asm
+ </Include-Resource>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>rat-maven-plugin</artifactId>
+ <configuration>
+ <excludeSubProjects>false</excludeSubProjects>
+ <useEclipseDefaultExcludes>true</useEclipseDefaultExcludes>
+ <useMavenDefaultExcludes>true</useMavenDefaultExcludes>
+ <excludes>
+ <param>doc/**/*</param>
+ <param>maven-eclipse.xml</param>
+ <param>.checkstyle</param>
+ <param>.externalToolBuilders/*</param>
+ <param>LICENSE.asm</param>
+ <param>.fbprefs</param>
+ </excludes>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-checkstyle-plugin</artifactId>
+ <configuration>
+ <enableRulesSummary>false</enableRulesSummary>
+ <violationSeverity>warning</violationSeverity>
+ <configLocation>http://felix.apache.org/ipojo/dev/checkstyle_ipojo.xml</configLocation>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.ipojo.manipulator
+ </artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>asm</groupId>
+ <artifactId>asm-all</artifactId>
+ <version>3.0</version>
+ <exclusions>
+ <exclusion>
+ <groupId>asm</groupId>
+ <artifactId>asm-tree</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/ComponentType.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/ComponentType.java
new file mode 100644
index 0000000..b45d0b4
--- /dev/null
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/ComponentType.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo.api;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.List;
+import java.util.Properties;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.MissingHandlerException;
+import org.apache.felix.ipojo.UnacceptableConfiguration;
+
+
+/**
+ * The component type class allows specifying a new component type
+ * and its attached factory. It also allows creating instances form
+ * the specified component type.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public abstract class ComponentType {
+
+ /**
+ * The list of instances created from the
+ * current component type.
+ */
+ private List m_instances = new ArrayList();
+
+ /**
+ * Gets the factory attached to the current
+ * component type.
+ * @return the factory
+ */
+ public abstract Factory getFactory();
+
+ /**
+ * Starts the factory attached to this
+ * component type. Once started a factory
+ * and its attached component type
+ * cannot be modified.
+ */
+ public abstract void start();
+
+ /**
+ * Stops the factory attached to this
+ * component type.
+ */
+ public abstract void stop();
+
+
+ /**
+ * Creates a component instance from the current type
+ * with an empty configuration.
+ * @return the component instance object.
+ * @throws UnacceptableConfiguration the configuration is not acceptable
+ * @throws MissingHandlerException the factory in invalid
+ * @throws ConfigurationException the instance configuration failed
+ */
+ public ComponentInstance createInstance() throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
+ ComponentInstance ci = ensureAndGetFactory().createComponentInstance(null);
+ m_instances.add(ci);
+ return ci;
+ }
+
+ /**
+ * Creates a component instance from the current type
+ * with the given name.
+ * @param name the instance name
+ * @return the component instance object.
+ * @throws UnacceptableConfiguration the configuration is not acceptable
+ * @throws MissingHandlerException the factory in invalid
+ * @throws ConfigurationException the instance configuration failed
+ */
+ public ComponentInstance createInstance(String name) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
+ Dictionary dict = null;
+ if (name != null) {
+ dict = new Properties();
+ dict.put("instance.name", name);
+ }
+ ComponentInstance ci = ensureAndGetFactory().createComponentInstance(dict);
+ m_instances.add(ci);
+ return ci;
+ }
+
+ /**
+ * Creates a component instance from the current type
+ * with the given configuration.
+ * @param conf the configuration
+ * @return the component instance object.
+ * @throws UnacceptableConfiguration the configuration is not acceptable
+ * @throws MissingHandlerException the factory in invalid
+ * @throws ConfigurationException the instance configuration failed
+ */
+ public ComponentInstance createInstance(Dictionary conf) throws UnacceptableConfiguration, MissingHandlerException, ConfigurationException {
+ ComponentInstance ci = ensureAndGetFactory().createComponentInstance(conf);
+ m_instances.add(ci);
+ return ci;
+ }
+
+ /**
+ * Disposes the given name. The instance must be created from this
+ * component type.
+ * @param ci the component instance to delete
+ * @return <code>true</code> if the instance was
+ * successfully disposed.
+ */
+ public boolean disposeInstance(ComponentInstance ci) {
+ if (m_instances.remove(ci)) {
+ ci.dispose();
+ return true;
+ } else {
+ System.err.println("The instance was not created from this component type");
+ return false;
+ }
+ }
+
+ /**
+ * Gets the component instance created from this component type.
+ * with the given name.
+ * @param name the instance name.
+ * @return the component instance with the given name and created
+ * from the current component type factory. <code>null</code> if
+ * the instance cannot be found.
+ */
+ public ComponentInstance getInstanceByName(String name) {
+ for (int i = 0; i < m_instances.size(); i++) {
+ ComponentInstance ci = (ComponentInstance) m_instances.get(i);
+ if (ci.getInstanceName().equals(name)) {
+ return ci;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Disposes the instance created with this component type which
+ * has the given name.
+ * @param name the name of the instance to delete.
+ * @return <code>true</code> is the instance is successfully disposed.
+ */
+ public boolean disposeInstance(String name) {
+ ComponentInstance ci = getInstanceByName(name);
+ if (ci == null) {
+ System.err.println("The instance was not found in this component type");
+ return false;
+ } else {
+ return disposeInstance(ci);
+ }
+ }
+
+ /**
+ * Returns the attached factory.
+ * Before returning the factory, the consistency of the
+ * factory is checked.
+ * @return the attached factory to the current component type
+ */
+ private Factory ensureAndGetFactory() {
+ ensureFactory();
+ return getFactory();
+ }
+
+ /**
+ * Checks if the factory is already created.
+ */
+ private void ensureFactory() {
+ if (getFactory() == null) {
+ throw new IllegalStateException("The factory associated with the component type is not created");
+ } else {
+ if (getFactory().getState() == Factory.INVALID) {
+ throw new IllegalStateException("The factory associated with the component type is invalid (not started or missing handlers)");
+ }
+ }
+ }
+
+
+
+
+
+}
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Dependency.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Dependency.java
new file mode 100644
index 0000000..a2dbe29
--- /dev/null
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Dependency.java
@@ -0,0 +1,352 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo.api;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.PrimitiveInstanceDescription;
+import org.apache.felix.ipojo.handlers.dependency.DependencyDescription;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * Allows configuring a service dependencies.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Dependency {
+
+ /**
+ * The dynamic binding policy.
+ */
+ public static final int DYNAMIC = org.apache.felix.ipojo.handlers.dependency.Dependency.DYNAMIC_BINDING_POLICY;
+
+ /**
+ * The static binding policy.
+ */
+ public static final int STATIC = org.apache.felix.ipojo.handlers.dependency.Dependency.STATIC_BINDING_POLICY;
+
+ /**
+ * The dynamic-priority binding policy.
+ */
+ public static final int DYNAMIC_PRIORITY = org.apache.felix.ipojo.handlers.dependency.Dependency.DYNAMIC_PRIORITY_BINDING_POLICY;
+
+ /**
+ * The required specification.
+ */
+ private String m_specification;
+
+ /**
+ * The LDAP filter of the dependency.
+ */
+ private String m_filter;
+
+ /**
+ * The field of the implementation class attached to
+ * this dependency.
+ */
+ private String m_field;
+
+ /**
+ * Is the dependency optional?
+ */
+ private boolean m_optional;
+
+ /**
+ * Is the dependency aggregate?
+ */
+ private boolean m_aggregate;
+
+ /**
+ * Bind method attached to the dependency.
+ */
+ private String m_bind;
+
+ /**
+ * Unbind method attached to the dependency.
+ */
+ private String m_unbind;
+
+ /**
+ * The dependency binding policy.
+ */
+ private int m_policy;
+
+ /**
+ * The dependency comparator.
+ * (used to compare service providers)
+ */
+ private String m_comparator;
+
+ /**
+ * The dependency default-implementation.
+ */
+ private String m_di;
+
+ /**
+ * The dependency specific provider.
+ */
+ private String m_from;
+
+ /**
+ * The dependency id.
+ */
+ private String m_id;
+
+ /**
+ * Does the dependency supports nullable?
+ */
+ private boolean m_nullable = true;
+
+ /**
+ * Gets the dependency metadata.
+ * @return the 'requires' element describing
+ * the current dependency.
+ */
+ public Element getElement() {
+ ensureValidity();
+
+ Element dep = new Element("requires", "");
+ if (m_specification != null) {
+ dep.addAttribute(new Attribute("specification", m_specification));
+ }
+ if (m_filter != null) {
+ dep.addAttribute(new Attribute("filter", m_filter));
+ }
+ if (m_field != null) {
+ dep.addAttribute(new Attribute("field", m_field));
+ }
+ if (m_bind != null) {
+ Element cb = new Element("callback", "");
+ cb.addAttribute(new Attribute("type", "bind"));
+ cb.addAttribute(new Attribute("method", m_bind));
+ dep.addElement(cb);
+ }
+ if (m_unbind != null) {
+ Element cb = new Element("callback", "");
+ cb.addAttribute(new Attribute("type", "unbind"));
+ cb.addAttribute(new Attribute("method", m_unbind));
+ dep.addElement(cb);
+ }
+ if (m_comparator != null) {
+ dep.addAttribute(new Attribute("comparator", m_comparator));
+ }
+ if (m_di != null) {
+ dep.addAttribute(new Attribute("default-implementation", m_di));
+ }
+ if (m_from != null) {
+ dep.addAttribute(new Attribute("from", m_from));
+ }
+ if (m_id != null) {
+ dep.addAttribute(new Attribute("id", m_id));
+ }
+ if (! m_nullable) {
+ dep.addAttribute(new Attribute("nullable", "false"));
+ }
+ if (m_optional) {
+ dep.addAttribute(new Attribute("optional", "true"));
+ }
+ if (m_aggregate) {
+ dep.addAttribute(new Attribute("aggregate", "true"));
+ }
+ if (m_policy != -1) {
+ if (m_policy == DYNAMIC) {
+ dep.addAttribute(new Attribute("policy", "dynamic"));
+ } else if (m_policy == STATIC) {
+ dep.addAttribute(new Attribute("policy", "static"));
+ } else if (m_policy == DYNAMIC_PRIORITY) {
+ dep.addAttribute(new Attribute("policy", "dynamic-priority"));
+ }
+ // No other possibilities.
+ }
+ return dep;
+ }
+
+ /**
+ * Sets the required service specification.
+ * @param spec the specification
+ * @return the current dependency object.
+ */
+ public Dependency setSpecification(String spec) {
+ m_specification = spec;
+ return this;
+ }
+
+ /**
+ * Sets the dependency filter.
+ * @param filter the LDAP filter
+ * @return the current dependency object
+ */
+ public Dependency setFilter(String filter) {
+ m_filter = filter;
+ return this;
+ }
+
+ /**
+ * Sets the field attached to the dependency.
+ * @param field the implementation class field name.
+ * @return the current dependency object
+ */
+ public Dependency setField(String field) {
+ m_field = field;
+ return this;
+ }
+
+ /**
+ * Sets the dependency optionality.
+ * @param opt <code>true</code> to set the
+ * dependency to optional.
+ * @return the current dependency object.
+ */
+ public Dependency setOptional(boolean opt) {
+ m_optional = opt;
+ return this;
+ }
+
+ /**
+ * Sets the dependency cardinality.
+ * @param agg <code>true</code> to set the
+ * dependency to aggregate.
+ * @return the current dependency object.
+ */
+ public Dependency setAggregate(boolean agg) {
+ m_aggregate = agg;
+ return this;
+ }
+
+ /**
+ * Sets if the dependency supports nullable objects.
+ * @param nullable <code>false</code> if the dependency does not
+ * support the nullable object injection
+ * @return the current dependency object.
+ */
+ public Dependency setNullable(boolean nullable) {
+ m_nullable = nullable;
+ return this;
+ }
+
+ /**
+ * Sets the dependency bind method.
+ * @param bind the bind method name
+ * @return the current dependency object.
+ */
+ public Dependency setBindMethod(String bind) {
+ m_bind = bind;
+ return this;
+ }
+
+ /**
+ * Sets the dependency unbind method.
+ * @param unbind the unbind method
+ * @return the current dependency object.
+ */
+ public Dependency setUnbindMethod(String unbind) {
+ m_unbind = unbind;
+ return this;
+ }
+
+ /**
+ * Sets the dependency binding policy.
+ * @param policy the binding policy
+ * @return the current dependency object
+ */
+ public Dependency setBindingPolicy(int policy) {
+ m_policy = policy;
+ return this;
+ }
+
+ /**
+ * Sets the dependency comparator.
+ * @param cmp the comparator class name
+ * @return the current dependency object
+ */
+ public Dependency setComparator(String cmp) {
+ m_comparator = cmp;
+ return this;
+ }
+
+ /**
+ * Sets the dependency default-implementation.
+ * @param di the default-implementation class name
+ * @return the current dependency object
+ */
+ public Dependency setDefaultImplementation(String di) {
+ m_di = di;
+ return this;
+ }
+
+ /**
+ * Sets the dependency 'from' attribute.
+ * @param from the name of the service provider.
+ * @return the current dependency object
+ */
+ public Dependency setFrom(String from) {
+ m_from = from;
+ return this;
+ }
+
+ /**
+ * Sets the dependency id.
+ * @param id the dependency id.
+ * @return the current dependency object.
+ */
+ public Dependency setId(String id) {
+ m_id = id;
+ return this;
+ }
+
+ /**
+ * Checks dependency configuration validity.
+ */
+ private void ensureValidity() {
+ // At least a field or methods.
+ if (m_field == null && m_bind == null && m_unbind == null) {
+ throw new IllegalStateException("A dependency must have a field or bind/unbind methods");
+ }
+ // Check binding policy.
+ if (m_policy != -1) {
+ if (!(m_policy == DYNAMIC || m_policy == STATIC || m_policy == DYNAMIC_PRIORITY)) {
+ throw new IllegalStateException("Unknow binding policy : " + m_policy);
+ }
+ }
+ }
+
+ /**
+ * Gets the dependency description object attached to
+ * this dependency.
+ * @param instance the instance on which searching the dependency
+ * @return the dependency description attached to this dependency or
+ * <code>null</code> if the dependency cannot be found.
+ */
+ public DependencyDescription getDependencyDescription(ComponentInstance instance) {
+ PrimitiveInstanceDescription desc = (PrimitiveInstanceDescription) instance.getInstanceDescription();
+ if (m_id != null) {
+ return desc.getDependency(m_id);
+ }
+ if (m_specification != null) {
+ return desc.getDependency(m_specification);
+ }
+ DependencyDescription[] deps = desc.getDependencies();
+ if (deps.length == 1) {
+ return deps[0];
+ }
+ // Cannot determine the dependency.
+ return null;
+ }
+
+
+}
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/PrimitiveComponentType.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/PrimitiveComponentType.java
new file mode 100644
index 0000000..5626615
--- /dev/null
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/PrimitiveComponentType.java
@@ -0,0 +1,459 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo.api;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.felix.ipojo.ComponentFactory;
+import org.apache.felix.ipojo.ConfigurationException;
+import org.apache.felix.ipojo.Factory;
+import org.apache.felix.ipojo.manipulation.Manipulator;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Allows defining primitive component types.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class PrimitiveComponentType extends ComponentType {
+
+ /**
+ * The bundle context.
+ */
+ private BundleContext m_context;
+
+ /**
+ * The implementation class name.
+ */
+ private String m_classname;
+
+ /**
+ * The component type name.
+ */
+ private String m_name;
+
+ /**
+ * Is the component type immediate.
+ */
+ private boolean m_immediate;
+
+ /**
+ * Manipulation metadata of the component type.
+ */
+ private Element m_manipulation;
+
+ /**
+ * Component factory attached to the component
+ * type.
+ */
+ private ComponentFactory m_factory;
+
+ /**
+ * Component type metadata.
+ */
+ private Element m_metadata;
+
+ /**
+ * List of provided services.
+ */
+ private List m_services = new ArrayList(1);
+
+ /**
+ * List of service dependencies.
+ */
+ private List m_dependencies = new ArrayList();
+
+ /**
+ * List of configuration properties.
+ */
+ private List m_properties = new ArrayList();
+
+ /**
+ * The validate callback.
+ */
+ private String m_validate;
+
+ /**
+ * The invalidate callback.
+ */
+ private String m_invalidate;
+
+ /**
+ * Are the properties propagated to provided services?
+ */
+ private boolean m_propagation;
+
+ /**
+ * The factory method.
+ */
+ private String m_factoryMethod;
+
+ /**
+ * Is the factory public?
+ */
+ private boolean m_public = true;
+
+ /**
+ * The Managed Service PID.
+ */
+ private String m_msPID;
+
+ /**
+ * The temporal dependencies.
+ */
+ private ArrayList m_temporals = new ArrayList();;
+
+ /**
+ * Checks that the component type is not already
+ * started.
+ */
+ private void ensureNotInitialized() {
+ if (m_factory != null) {
+ throw new IllegalStateException("The component type was already initialized, cannot modify metadata");
+ }
+ }
+
+ /**
+ * Checks that the component type description is valid.
+ */
+ private void ensureValidity() {
+ if (m_classname == null) {
+ throw new IllegalStateException("The primitive component type has no implementation class");
+ }
+ if (m_context == null) {
+ throw new IllegalStateException("The primitive component type has no bundle context");
+ }
+ }
+
+ /**
+ * Gets the component factory.
+ * @return the factory attached to this component type.
+ * @see org.apache.felix.ipojo.api.ComponentType#getFactory()
+ */
+ public Factory getFactory() {
+ initializeFactory();
+ return m_factory;
+ }
+
+ /**
+ * Starts the component type.
+ * @see org.apache.felix.ipojo.api.ComponentType#start()
+ */
+ public void start() {
+ initializeFactory();
+ m_factory.start();
+ }
+
+ /**
+ * Stops the component type.
+ * @see org.apache.felix.ipojo.api.ComponentType#stop()
+ */
+ public void stop() {
+ initializeFactory();
+ m_factory.stop();
+ }
+
+ /**
+ * Initializes the factory.
+ */
+ private void initializeFactory() {
+ if (m_factory == null) {
+ createFactory();
+ }
+ }
+
+ /**
+ * Sets the bundle context.
+ * @param bc the bundle context
+ * @return the current component type
+ */
+ public PrimitiveComponentType setBundleContext(BundleContext bc) {
+ ensureNotInitialized();
+ m_context = bc;
+ return this;
+ }
+
+ /**
+ * Sets the implementation class.
+ * @param classname the class name
+ * @return the current component type
+ */
+ public PrimitiveComponentType setClassName(String classname) {
+ ensureNotInitialized();
+ m_classname = classname;
+ return this;
+ }
+
+ /**
+ * Sets the component type name.
+ * @param name the factory name
+ * @return the current component type
+ */
+ public PrimitiveComponentType setComponentTypeName(String name) {
+ ensureNotInitialized();
+ m_name = name;
+ return this;
+ }
+
+ /**
+ * Sets if the component type is immediate or not.
+ * @param immediate <code>true</code> to set the component
+ * type to immediate
+ * @return the current component type
+ */
+ public PrimitiveComponentType setImmediate(boolean immediate) {
+ ensureNotInitialized();
+ m_immediate = immediate;
+ return this;
+ }
+
+ /**
+ * Sets the dependency factory method.
+ * @param method the method used to create pojo object.
+ * @return the current component type
+ */
+ public PrimitiveComponentType setFactoryMethod(String method) {
+ ensureNotInitialized();
+ m_factoryMethod = method;
+ return this;
+ }
+
+ /**
+ * Sets if the component type propagates properties to service properties.
+ * @param propagation <code>true</code> to enable propagation
+ * @return the current component type
+ */
+ public PrimitiveComponentType setPropagation(boolean propagation) {
+ ensureNotInitialized();
+ m_propagation = propagation;
+ return this;
+ }
+
+ /**
+ * Sets the factory public aspect.
+ * @param visible <code>false</code> to create a private factory.
+ * @return the current component type
+ */
+ public PrimitiveComponentType setPublic(boolean visible) {
+ ensureNotInitialized();
+ m_public = visible;
+ return this;
+ }
+
+ /**
+ * Sets the managed service pid.
+ * @param pid the managed service pid
+ * @return the current component type
+ */
+ public PrimitiveComponentType setManagedServicePID(String pid) {
+ ensureNotInitialized();
+ m_msPID = pid;
+ return this;
+ }
+
+ /**
+ * Sets the validate method.
+ * @param method the validate method
+ * @return the current component type
+ */
+ public PrimitiveComponentType setValidateMethod(String method) {
+ ensureNotInitialized();
+ m_validate = method;
+ return this;
+ }
+
+ /**
+ * Sets the invalidate method.
+ * @param method the invalidate method
+ * @return the current component type
+ */
+ public PrimitiveComponentType setInvalidateMethod(String method) {
+ ensureNotInitialized();
+ m_invalidate = method;
+ return this;
+ }
+
+ /**
+ * Generates the component description.
+ * @return the component type description of
+ * the current component type
+ */
+ private Element generateComponentMetadata() {
+ Element element = new Element("component", "");
+ element.addAttribute(new Attribute("classname", m_classname));
+ if (m_name != null) {
+ element.addAttribute(new Attribute("name", m_name));
+ }
+ if (m_factoryMethod != null) {
+ element.addAttribute(new Attribute("factory-method", m_factoryMethod));
+ }
+ if (! m_public) {
+ element.addAttribute(new Attribute("public", "false"));
+ }
+ if (m_immediate) {
+ element.addAttribute(new Attribute("immediate", "true"));
+ }
+ for (int i = 0; i < m_services.size(); i++) {
+ Service svc = (Service) m_services.get(i);
+ element.addElement(svc.getElement());
+ }
+ for (int i = 0; i < m_dependencies.size(); i++) {
+ Dependency dep = (Dependency) m_dependencies.get(i);
+ element.addElement(dep.getElement());
+ }
+ for (int i = 0; i < m_temporals.size(); i++) {
+ TemporalDependency dep = (TemporalDependency) m_temporals.get(i);
+ element.addElement(dep.getElement());
+ }
+ if (m_validate != null) {
+ Element callback = new Element("callback", "");
+ callback.addAttribute(new Attribute("transition", "validate"));
+ callback.addAttribute(new Attribute("method", m_validate));
+ element.addElement(callback);
+ }
+ if (m_invalidate != null) {
+ Element callback = new Element("callback", "");
+ callback.addAttribute(new Attribute("transition", "invalidate"));
+ callback.addAttribute(new Attribute("method", m_invalidate));
+ element.addElement(callback);
+ }
+
+ // Properties
+ // First determine if we need the properties element
+ if (m_propagation || m_msPID != null || ! m_properties.isEmpty()) {
+ Element properties = new Element("properties", "");
+ if (m_propagation) {
+ properties.addAttribute(new Attribute("propagation", "true"));
+ }
+ if (m_msPID != null) {
+ properties.addAttribute(new Attribute("pid", m_msPID));
+ }
+ for (int i = 0; i < m_properties.size(); i++) {
+ Property prop = (Property) m_properties.get(i);
+ properties.addElement(prop.getElement());
+ }
+ element.addElement(properties);
+ }
+
+ return element;
+ }
+
+ /**
+ * Creates the component factory.
+ */
+ private void createFactory() {
+ ensureValidity();
+ byte[] clazz = manipulate();
+ m_metadata = generateComponentMetadata();
+ Element meta = m_metadata;
+ meta.addElement(m_manipulation);
+ try {
+ m_factory = new ComponentFactory(m_context, clazz, meta);
+ } catch (ConfigurationException e) {
+ throw new IllegalStateException("An exception occurs during factory initialization : " + e.getMessage());
+ }
+
+ }
+
+ /**
+ * Manipulates the implementation class.
+ * @return the manipulated class
+ */
+ private byte[] manipulate() {
+ Manipulator manipulator = new Manipulator();
+ try {
+ byte[] array = getClassByteArray();
+ byte[] newclazz = manipulator.manipulate(array);
+ m_manipulation = manipulator.getManipulationMetadata();
+ return newclazz;
+ } catch (IOException e) {
+ throw new IllegalStateException("An exception occurs during implementation class manipulation : " + e.getMessage());
+ }
+ }
+
+ /**
+ * Gets a class file as a byte array.
+ * @return the byte array.
+ * @throws IOException the class file cannot be read.
+ */
+ private byte[] getClassByteArray() throws IOException {
+ String filename = m_classname.replace('.', '/') + ".class";
+ URL url = m_context.getBundle().getResource(filename);
+ if (url == null) {
+ throw new IllegalStateException("An exception occurs during implementation class manipulation : cannot found the class file " + filename);
+ }
+ InputStream is = url.openStream();
+ if (is == null) {
+ throw new IllegalStateException("An exception occurs during implementation class manipulation : cannot read the class file " + url);
+ }
+ byte[] b = new byte[is.available()];
+ is.read(b);
+ return b;
+ }
+
+ /**
+ * Adds a provided service.
+ * @param svc the service to add
+ * @return the current component type
+ */
+ public PrimitiveComponentType addService(Service svc) {
+ ensureNotInitialized();
+ m_services.add(svc);
+ return this;
+ }
+
+ /**
+ * Adds a service dependency.
+ * @param dep the dependency to add
+ * @return the current component type
+ */
+ public PrimitiveComponentType addDependency(Dependency dep) {
+ ensureNotInitialized();
+ m_dependencies.add(dep);
+ return this;
+ }
+
+ /**
+ * Adds a temporal service dependency.
+ * @param dep the temporal dependency to add
+ * @return the current component type
+ */
+ public PrimitiveComponentType addDependency(TemporalDependency dep) {
+ ensureNotInitialized();
+ m_temporals.add(dep);
+ return this;
+ }
+
+ /**
+ * Adds a configuration property.
+ * @param prop the property to add
+ * @return the current component type
+ */
+ public PrimitiveComponentType addProperty(Property prop) {
+ ensureNotInitialized();
+ m_properties.add(prop);
+ return this;
+ }
+
+}
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Property.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Property.java
new file mode 100644
index 0000000..0e510bd
--- /dev/null
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Property.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo.api;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.PrimitiveInstanceDescription;
+import org.apache.felix.ipojo.architecture.PropertyDescription;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * Allows configuring a configuration property.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Property {
+
+ /**
+ * The property name.
+ */
+ private String m_name;
+
+ /**
+ * The property field.
+ */
+ private String m_field;
+
+ /**
+ * The property value.
+ */
+ private String m_value;
+
+ /**
+ * The property method.
+ */
+ private String m_method;
+
+ /**
+ * Is the property mandatory.
+ */
+ private boolean m_mandatory;
+
+ /**
+ * Is the property immutable.
+ */
+ private boolean m_immutable;
+
+ /**
+ * Sets the property name.
+ * @param name the property name
+ * @return the current property object
+ */
+ public Property setName(String name) {
+ m_name = name;
+ return this;
+ }
+
+ /**
+ * Sets the property field.
+ * @param name the property field
+ * @return the current property object
+ */
+ public Property setField(String name) {
+ m_field = name;
+ return this;
+ }
+
+ /**
+ * Sets the property method.
+ * @param name the property method
+ * @return the current property object
+ */
+ public Property setMethod(String name) {
+ m_method = name;
+ return this;
+ }
+
+ /**
+ * Sets the property value.
+ * @param name the property value
+ * @return the current property object
+ */
+ public Property setValue(String name) {
+ m_value = name;
+ return this;
+ }
+
+ /**
+ * Sets if the property is mandatory.
+ * @param mandatory <code>true</code> if the dependency is mandatory.
+ * @return the current property object
+ */
+ public Property setMandatory(boolean mandatory) {
+ m_mandatory = mandatory;
+ return this;
+ }
+
+ /**
+ * Sets if the property is immutable.
+ * @param immutable <code>true</code> if the dependency is immutable.
+ * @return the current property object
+ */
+ public Property setImmutable(boolean immutable) {
+ m_immutable = immutable;
+ return this;
+ }
+
+ /**
+ * Gets the property element.
+ * @return the property element.
+ */
+ public Element getElement() {
+ ensureValidity();
+ Element element = new Element("property", "");
+ if (m_name != null) {
+ element.addAttribute(new Attribute("name", m_name));
+ }
+ if (m_method != null) {
+ element.addAttribute(new Attribute("method", m_method));
+ }
+ if (m_value != null) {
+ element.addAttribute(new Attribute("value", m_value));
+ }
+ if (m_field != null) {
+ element.addAttribute(new Attribute("field", m_field));
+ }
+ if (m_mandatory) {
+ element.addAttribute(new Attribute("mandatory", Boolean.toString(m_mandatory)));
+ }
+ if (m_immutable) {
+ element.addAttribute(new Attribute("immutable", Boolean.toString(m_immutable)));
+ }
+ return element;
+ }
+
+ /**
+ * Checks the configuration validity.
+ */
+ private void ensureValidity() {
+ // Two cases
+ // Field or Method
+ if (m_field == null && m_method == null) {
+ throw new IllegalStateException("A property must have either a field or a method");
+ }
+ if (m_immutable && m_value == null) {
+ throw new IllegalStateException("A immutable service property must have a value");
+ }
+ }
+
+ /**
+ * Gets the property description for the current property.
+ * @param instance the component instance on which looking for the property.
+ * @return the property description associated with the current property
+ * or <code>null</code> if not found.
+ */
+ public PropertyDescription getPropertyDescription(ComponentInstance instance) {
+ PrimitiveInstanceDescription desc = (PrimitiveInstanceDescription) instance.getInstanceDescription();
+ PropertyDescription[] props = desc.getProperties();
+
+ for (int i = 0; i < props.length; i++) {
+ if ((m_name != null && m_name.equals(props[i].getName()))
+ || (m_field != null && m_field.equals(props[i].getName()))) {
+ return props[i];
+ }
+ }
+
+ return null;
+ }
+
+}
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Service.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Service.java
new file mode 100644
index 0000000..f015735
--- /dev/null
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/Service.java
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo.api;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.PrimitiveInstanceDescription;
+import org.apache.felix.ipojo.handlers.providedservice.ProvidedService;
+import org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceDescription;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * Allows configuring a provided service.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Service {
+
+ /**
+ * The provided service specification.
+ */
+ private List m_specifications; // null be default computed.
+
+ /**
+ * The provided service strategy.
+ */
+ private int m_strategy = ProvidedService.SINGLETON_STRATEGY;
+
+ /**
+ * The provided service custom strategy.
+ */
+ private String m_customStrategy;
+
+ /**
+ * The service properties.
+ */
+ private List m_properties = new ArrayList();
+
+ /**
+ * Gets the provided service element.
+ * @return the 'provides' element.
+ */
+ public Element getElement() {
+ ensureValidity();
+ Element element = new Element("provides", "");
+ if (m_specifications != null) {
+ element.addAttribute(new Attribute("specifications", getSpecificationsArray()));
+ }
+ element.addAttribute(new Attribute("strategy", getStringStrategy()));
+ for (int i = 0; i < m_properties.size(); i++) {
+ element.addElement(((ServiceProperty) m_properties.get(i)).getElement());
+ }
+ return element;
+ }
+
+ /**
+ * Gets the provided service description associated with the current service.
+ * @param instance the instance on which looking for the provided service description
+ * @return the provided service description or <code>null</code> if not found.
+ */
+ public ProvidedServiceDescription getProvidedServiceDescription(ComponentInstance instance) {
+ PrimitiveInstanceDescription desc = (PrimitiveInstanceDescription) instance.getInstanceDescription();
+ ProvidedServiceDescription[] pss = desc.getProvidedServices();
+ if (pss.length == 0) {
+ return null;
+ }
+
+ if (pss.length == 1) {
+ return pss[0];
+ }
+
+ if (m_specifications == null) {
+ return null;
+ } else {
+ for (int j = 0; j < pss.length; j++) {
+ ProvidedServiceDescription psd = pss[j];
+ List specs = Arrays.asList(psd.getServiceSpecifications());
+ if (specs.containsAll(m_specifications)) {
+ return psd;
+ }
+ }
+ }
+
+ return null;
+ }
+
+
+
+ /**
+ * Checks the validity of the configuration.
+ */
+ private void ensureValidity() {
+ // No check required.
+ }
+
+
+ /**
+ * The the service specification array as a String.
+ * @return the string-from of the service specifications.
+ */
+ private String getSpecificationsArray() {
+ if (m_specifications.size() == 1) {
+ return (String) m_specifications.get(0);
+ } else {
+ StringBuffer buffer = new StringBuffer("{");
+ for (int i = 0; i < m_specifications.size(); i++) {
+ if (i != 0) {
+ buffer.append(',');
+ }
+ buffer.append(m_specifications.get(i));
+ }
+ buffer.append('}');
+ return buffer.toString();
+ }
+ }
+
+ /**
+ * Adds a service property.
+ * @param ps the service property to add
+ * @return the current service object.
+ */
+ public Service addProperty(ServiceProperty ps) {
+ m_properties.add(ps);
+ return this;
+ }
+
+ /**
+ * Sets the provided service specification.
+ * @param spec the service specification
+ * @return the current service object.
+ */
+ public Service setSpecification(String spec) {
+ m_specifications = new ArrayList(1);
+ m_specifications.add(spec);
+ return this;
+ }
+
+ /**
+ * Sets the provided service specifications.
+ * @param specs the service specifications
+ * @return the current service object.
+ */
+ public Service setSpecifications(List specs) {
+ m_specifications = specs;
+ return this;
+ }
+
+ /**
+ * Sets the creation strategy.
+ * @param strategy the service strategy.
+ * @return the current service object
+ */
+ public Service setCreationStrategy(int strategy) {
+ m_strategy = strategy;
+ return this;
+ }
+
+ /**
+ * Sets the creation strategy.
+ * This method allows using a customized
+ * service strategy.
+ * @param strategy the service strategy
+ * @return the current service object
+ */
+ public Service setCreationStrategy(String strategy) {
+ m_strategy = -1; // Custom
+ m_customStrategy = strategy;
+ return this;
+ }
+
+ /**
+ * Gets the string-form of the creation strategy.
+ * @return the creation strategy string form
+ */
+ private String getStringStrategy() {
+ switch (m_strategy) {
+ case -1: // Custom policies
+ return m_customStrategy;
+ case ProvidedService.SINGLETON_STRATEGY:
+ return "singleton";
+ case ProvidedService.STATIC_STRATEGY:
+ return "method";
+ case ProvidedService.SERVICE_STRATEGY:
+ return "service";
+ case ProvidedService.INSTANCE_STRATEGY:
+ return "instance";
+ default:
+ throw new IllegalStateException("Unknown creation strategy : "
+ + m_strategy);
+ }
+ }
+
+}
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/ServiceProperty.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/ServiceProperty.java
new file mode 100644
index 0000000..7fed046
--- /dev/null
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/ServiceProperty.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo.api;
+
+import org.apache.felix.ipojo.ComponentInstance;
+import org.apache.felix.ipojo.PrimitiveInstanceDescription;
+import org.apache.felix.ipojo.handlers.providedservice.ProvidedServiceDescription;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * Allows configuring a service property.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class ServiceProperty {
+
+ /**
+ * The property name.
+ */
+ private String m_name;
+
+ /**
+ * The property field.
+ */
+ private String m_field;
+
+ /**
+ * The property type.
+ */
+ private String m_type;
+
+ /**
+ * The property value.
+ */
+ private String m_value;
+
+ /**
+ * Is the property mandatory.
+ */
+ private boolean m_mandatory;
+
+ /**
+ * Is the property immutable.
+ */
+ private boolean m_immutable;
+
+ /**
+ * Sets the property name.
+ * @param name the property name
+ * @return the current property object
+ */
+ public ServiceProperty setName(String name) {
+ m_name = name;
+ return this;
+ }
+
+ /**
+ * Sets the property field.
+ * @param name the property field
+ * @return the current property object
+ */
+ public ServiceProperty setField(String name) {
+ m_field = name;
+ return this;
+ }
+
+ /**
+ * Sets the property type.
+ * @param name the property type
+ * @return the current property object
+ */
+ public ServiceProperty setType(String name) {
+ m_type = name;
+ return this;
+ }
+
+ /**
+ * Sets the property value.
+ * @param name the property value
+ * @return the current property object
+ */
+ public ServiceProperty setValue(String name) {
+ m_value = name;
+ return this;
+ }
+
+ /**
+ * Sets if the property is immutable.
+ * @param immutable <code>true</code> if the dependency is immutable.
+ * @return the current property object
+ */
+ public ServiceProperty setImmutable(boolean immutable) {
+ m_immutable = immutable;
+ return this;
+ }
+
+ /**
+ * Sets if the property is mandatory.
+ * @param mandatory <code>true</code> if the dependency is mandatory.
+ * @return the current property object
+ */
+ public ServiceProperty setMandatory(boolean mandatory) {
+ m_mandatory = mandatory;
+ return this;
+ }
+
+
+ /**
+ * Gets the 'property' element.
+ * @return the element describing the current property.
+ */
+ public Element getElement() {
+ ensureValidity();
+ Element element = new Element("property", "");
+ if (m_name != null) {
+ element.addAttribute(new Attribute("name", m_name));
+ }
+ if (m_type != null) {
+ element.addAttribute(new Attribute("type", m_type));
+ }
+ if (m_value != null) {
+ element.addAttribute(new Attribute("value", m_value));
+ }
+ if (m_field != null) {
+ element.addAttribute(new Attribute("field", m_field));
+ }
+ if (m_mandatory) {
+ element.addAttribute(new Attribute("mandatory", Boolean.toString(m_mandatory)));
+ }
+ if (m_immutable) {
+ element.addAttribute(new Attribute("immutable", Boolean.toString(m_immutable)));
+ }
+ return element;
+ }
+
+ /**
+ * Checks the configuration validity.
+ */
+ private void ensureValidity() {
+ // Two cases
+ // Field or type
+ if (m_field == null && m_type == null) {
+ throw new IllegalStateException("A service property must have either a field or a type");
+ }
+ if (m_immutable && m_value == null) {
+ throw new IllegalStateException("A immutable service property must have a value");
+ }
+ }
+
+ /**
+ * Gets the property value of the current property
+ * on the given instance.
+ * @param instance the instance on which looking for
+ * the property value
+ * @return the property value or <code>null</code>
+ * if not found.
+ */
+ public Object getPropertyValue(ComponentInstance instance) {
+ PrimitiveInstanceDescription desc = (PrimitiveInstanceDescription) instance.getInstanceDescription();
+ ProvidedServiceDescription[] pss = desc.getProvidedServices();
+ for (int i = 0; i < pss.length; i++) {
+ // Check with the name
+ if (m_name != null && pss[i].getProperties().containsKey(m_name)) {
+ return pss[i].getProperties().get(m_name);
+ }
+ // Check with the field
+ if (m_field != null && pss[i].getProperties().containsKey(m_field)) {
+ return pss[i].getProperties().get(m_field);
+ }
+ }
+ // Not found.
+ return null;
+ }
+
+
+}
diff --git a/ipojo/api/src/main/java/org/apache/felix/ipojo/api/TemporalDependency.java b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/TemporalDependency.java
new file mode 100644
index 0000000..9344016
--- /dev/null
+++ b/ipojo/api/src/main/java/org/apache/felix/ipojo/api/TemporalDependency.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.felix.ipojo.api;
+
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * Allows configuring a service dependencies.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class TemporalDependency {
+
+ /**
+ * The required specification.
+ */
+ private String m_specification;
+
+ /**
+ * The LDAP filter of the dependency.
+ */
+ private String m_filter;
+
+ /**
+ * The field of the implementation class attached to
+ * this dependency.
+ */
+ private String m_field;
+
+ /**
+ * OnTimeout policy.
+ */
+ private String m_onTimeout;
+
+ /**
+ * Timeout.
+ */
+ private String m_timeout;
+
+ /**
+ * Proxy.
+ */
+ private boolean m_proxy = false;
+
+ /**
+ * Gets the dependency metadata.
+ * @return the 'requires' element describing
+ * the current dependency.
+ */
+ public Element getElement() {
+ ensureValidity();
+
+ Element dep = new Element("requires", "org.apache.felix.ipojo.handler.temporal");
+ if (m_specification != null) {
+ dep.addAttribute(new Attribute("specification", m_specification));
+ }
+ if (m_filter != null) {
+ dep.addAttribute(new Attribute("filter", m_filter));
+ }
+ if (m_field != null) {
+ dep.addAttribute(new Attribute("field", m_field));
+ }
+ if (m_onTimeout != null) {
+ dep.addAttribute(new Attribute("omTimeout", m_onTimeout));
+ }
+ if (m_timeout != null) {
+ dep.addAttribute(new Attribute("timeout", m_timeout));
+ }
+ if (m_proxy) {
+ dep.addAttribute(new Attribute("proxy", "true"));
+ }
+
+ return dep;
+ }
+
+ /**
+ * Sets the required service specification.
+ * @param spec the specification
+ * @return the current dependency object.
+ */
+ public TemporalDependency setSpecification(String spec) {
+ m_specification = spec;
+ return this;
+ }
+
+ /**
+ * Sets the dependency filter.
+ * @param filter the LDAP filter
+ * @return the current dependency object
+ */
+ public TemporalDependency setFilter(String filter) {
+ m_filter = filter;
+ return this;
+ }
+
+ /**
+ * Sets the field attached to the dependency.
+ * @param field the implementation class field name.
+ * @return the current dependency object
+ */
+ public TemporalDependency setField(String field) {
+ m_field = field;
+ return this;
+ }
+
+ /**
+ * Sets if the dependency is injected as a proxy.
+ * @param proxy <code>true</code> to inject proxies.
+ * @return the current dependency object.
+ */
+ public TemporalDependency setProxy(boolean proxy) {
+ m_proxy = proxy;
+ return this;
+ }
+
+ /**
+ * Sets the dependency timeout.
+ * @param time the dependency timeout in ms
+ * 'infinite' for infinite.
+ * @return the current dependency object
+ */
+ public TemporalDependency setTimeout(String time) {
+ m_timeout = time;
+ return this;
+ }
+
+ /**
+ * Sets the dependency ontimeout policy.
+ * Supports null, nullable, empty, and default-implementation.
+ * In this latter case, you must specify the qualified class name
+ * of the default-implementation (instead of default-implementation).
+ * Default: no action (i.e throws a runtime exception)
+ * @param tip the ontimeout policy
+ * @return the current dependency object
+ */
+ public TemporalDependency setOnTimeoutPolicy(String tip) {
+ m_onTimeout = tip;
+ return this;
+ }
+
+
+ /**
+ * Checks dependency configuration validity.
+ */
+ private void ensureValidity() {
+ // At least a field or methods.
+ if (m_field == null) {
+ throw new IllegalStateException("A temporal dependency must have a field");
+ }
+ }
+
+
+}