Applied patch (FELIX-291) to cache component metadata during packaging.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@539992 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/parser/FieldMetadata.java b/ipojo/src/main/java/org/apache/felix/ipojo/parser/FieldMetadata.java
new file mode 100644
index 0000000..46e0875
--- /dev/null
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/parser/FieldMetadata.java
@@ -0,0 +1,112 @@
+/*
+ * 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.parser;
+
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * A Field Metadata represent a field of an implementation class.
+ * This class allow to avoid reflection to get the type and the name of a field.
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class FieldMetadata {
+
+ /**
+ * Name of the field.
+ */
+ private String m_name;
+
+ /**
+ * Type of the field.
+ */
+ private String m_type;
+
+ /**
+ * Constructor.
+ * @param metadata : field manipulation element.
+ */
+ FieldMetadata(Element metadata) {
+ m_name = metadata.getAttribute("name");
+ m_type = metadata.getAttribute("type");
+ }
+
+ public String getFieldName() { return m_name; }
+
+ public String getFieldType() { return m_type; }
+
+ /**
+ * Get the 'reflective' type of the field.
+ * The reflective type is the type used by the Java Reflection API.
+ * @return : the reflective type corresponding to this field.
+ */
+ public String getReflectionType() {
+ // Primitive Array
+ if (m_type.endsWith("[]") && m_type.indexOf(".") == -1) {
+ String t = m_type.substring(0, m_type.length() - 2);
+ return "[" + getInternalPrimitiveType(t);
+ }
+ // Non-Primitive Array
+ if (m_type.endsWith("[]") && m_type.indexOf(".") != -1) {
+ String t = m_type.substring(0, m_type.length() - 2);
+ return "[L" + t + ";";
+ }
+ // Simple type
+ if (!m_type.endsWith("[]")) {
+ return m_type;
+ }
+
+ return null;
+ }
+
+ /**
+ * Get the internal notation for primitive type.
+ * @param string : Stringform of the type
+ * @return the internal notation or null if not found
+ */
+ private String getInternalPrimitiveType(String string) {
+ if (string.equalsIgnoreCase("boolean")) {
+ return "Z";
+ }
+ if (string.equalsIgnoreCase("char")) {
+ return "C";
+ }
+ if (string.equalsIgnoreCase("byte")) {
+ return "B";
+ }
+ if (string.equalsIgnoreCase("short")) {
+ return "S";
+ }
+ if (string.equalsIgnoreCase("int")) {
+ return "I";
+ }
+ if (string.equalsIgnoreCase("float")) {
+ return "F";
+ }
+ if (string.equalsIgnoreCase("long")) {
+ return "J";
+ }
+ if (string.equalsIgnoreCase("double")) {
+ return "D";
+ }
+ System.err.println("No primitive type found for " + m_type);
+ return null;
+ }
+
+}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/parser/ManipulationMetadata.java b/ipojo/src/main/java/org/apache/felix/ipojo/parser/ManipulationMetadata.java
new file mode 100644
index 0000000..62364cb
--- /dev/null
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/parser/ManipulationMetadata.java
@@ -0,0 +1,236 @@
+/*
+ * 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.parser;
+
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * Manipulation Metadata allows getting information about the implementation class
+ * whithout doing reflection.
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class ManipulationMetadata {
+
+ /**
+ * List of implemented interfaces.
+ */
+ private String[] m_interfaces = new String[0];
+
+ /**
+ * List of fields.
+ */
+ private FieldMetadata[] m_fields = new FieldMetadata[0];
+
+ /**
+ * List of methods.
+ */
+ private MethodMetadata[] m_methods = new MethodMetadata[0];
+
+
+ /**
+ * Constructor.
+ * Manipulation Metadata object are created from component type metadata by
+ * parsing manipulation metadata.
+ * @param metadata : component type metadata
+ */
+ public ManipulationMetadata(Element metadata) {
+ Element manip = metadata.getElements("manipulation", "")[0];
+ for (int i = 0; i < manip.getElements().length; i++) {
+ if (manip.getElements()[i].getName().equals("field")) {
+ FieldMetadata fm = new FieldMetadata(manip.getElements()[i]);
+ addField(fm);
+ } else if (manip.getElements()[i].getName().equals("method")) {
+ MethodMetadata fm = new MethodMetadata(manip.getElements()[i]);
+ addMethod(fm);
+ } else if (manip.getElements()[i].getName().equals("interface")) {
+ addInterface(manip.getElements()[i].getAttribute("name"));
+ }
+ }
+ }
+
+ public MethodMetadata[] getMethods() { return m_methods; }
+
+ public FieldMetadata[] getFields() { return m_fields; }
+
+ public String[] getInterfaces() { return m_interfaces; }
+
+ /**
+ * Get the field metadata for the given name.
+ * @param name : name of the field
+ * @return the corresponding field metadata or null if not found
+ */
+ public FieldMetadata getField(String name) {
+ for (int i = 0; i < m_fields.length; i++) {
+ if (m_fields[i].getFieldName().equalsIgnoreCase(name)) { return m_fields[i]; }
+ }
+ return null;
+ }
+
+ /**
+ * Get the field metadata for the given name and type.
+ * @param name : name of the field
+ * @param type : type of the field
+ * @return the corresponding field metadata or null if not found
+ */
+ public FieldMetadata getField(String name, String type) {
+ for (int i = 0; i < m_fields.length; i++) {
+ if (m_fields[i].getFieldName().equalsIgnoreCase(name) && m_fields[i].getFieldType().equalsIgnoreCase(type)) { return m_fields[i]; }
+ }
+ return null;
+ }
+
+ /**
+ * Check if the given interface name is implemented.
+ * @param itf : interface to check.
+ * @return true if the implementation class implement the given interface.
+ */
+ public boolean isInterfaceImplemented(String itf) {
+ for (int i = 0; i < m_interfaces.length; i++) {
+ if (m_interfaces[i].equals(itf)) { return true; }
+ }
+ return false;
+ }
+
+ /**
+ * Get the MethodMetadata corresponding to the method
+ * (contained in the implementation class) to given name.
+ * If several method match, the first one is returned.
+ * @param name : name of the method to look for.
+ * @return the Method Metadate or null if not found
+ */
+ public MethodMetadata getMethod(String name) {
+ for (int i = 0; i < m_methods.length; i++) {
+ if (m_methods[i].getMethodName().equalsIgnoreCase(name)) { return m_methods[i]; }
+ }
+ return null;
+ }
+
+ /**
+ * Get the MethodMetadata list corresponding to the method
+ * (contained in the implementation class) to given name.
+ * All methods contained in the implementation class matching
+ * with the name are in the returned list.
+ * @param name : name of the method to look for.
+ * @return the Method Metadata array or an empty array if not found
+ */
+ public MethodMetadata[] getMethods(String name) {
+ MethodMetadata[] mms = new MethodMetadata[0];
+ for (int i = 0; i < m_methods.length; i++) {
+ if (m_methods[i].getMethodName().equalsIgnoreCase(name)) {
+ if (mms.length > 0) {
+ MethodMetadata[] newInstances = new MethodMetadata[mms.length + 1];
+ System.arraycopy(mms, 0, newInstances, 0, mms.length);
+ newInstances[mms.length] = m_methods[i];
+ mms = newInstances;
+ } else {
+ mms = new MethodMetadata[] { m_methods[i] };
+ }
+ }
+ }
+ return mms;
+ }
+
+ /**
+ * Get the MethodMetadata corresponding to the method
+ * (contained in the implementation class) to given name
+ * and argument types.
+ * @param name : name of the method to look for.
+ * @param types : array of the argument types of the method
+ * @return the Method Metadate or null if not found
+ */
+ public MethodMetadata getMethod(String name, String[] types) {
+ for (int i = 0; i < m_methods.length; i++) {
+ if (m_methods[i].getMethodName().equalsIgnoreCase(name) && m_methods[i].getMethodArguments().length == types.length) {
+ boolean ok = true;
+ for (int j = 0; ok && j < types.length; j++) {
+ if (! types[j].equals(m_methods[i].getMethodArguments()[j])) {
+ ok = false;
+ }
+ }
+ if (ok) { return m_methods[i]; }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Add a method to the list.
+ * @param mm : Method Metadata to add.
+ */
+ private void addMethod(MethodMetadata mm) {
+ for (int i = 0; (m_methods != null) && (i < m_methods.length); i++) {
+ if (m_methods[i] == mm) {
+ return;
+ }
+ }
+
+ if (m_methods.length > 0) {
+ MethodMetadata[] newInstances = new MethodMetadata[m_methods.length + 1];
+ System.arraycopy(m_methods, 0, newInstances, 0, m_methods.length);
+ newInstances[m_methods.length] = mm;
+ m_methods = newInstances;
+ } else {
+ m_methods = new MethodMetadata[] { mm };
+ }
+ }
+
+ /**
+ * Add a field to the list.
+ * @param mm : the Field Metadata to add.
+ */
+ private void addField(FieldMetadata mm) {
+ for (int i = 0; (m_fields != null) && (i < m_fields.length); i++) {
+ if (m_fields[i] == mm) {
+ return;
+ }
+ }
+
+ if (m_fields.length > 0) {
+ FieldMetadata[] newInstances = new FieldMetadata[m_fields.length + 1];
+ System.arraycopy(m_fields, 0, newInstances, 0, m_fields.length);
+ newInstances[m_fields.length] = mm;
+ m_fields = newInstances;
+ } else {
+ m_fields = new FieldMetadata[] { mm };
+ }
+ }
+
+ /**
+ * Add the interface to the list.
+ * @param mm : the interface name to add.
+ */
+ private void addInterface(String mm) {
+ for (int i = 0; (m_interfaces != null) && (i < m_interfaces.length); i++) {
+ if (m_interfaces[i] == mm) {
+ return;
+ }
+ }
+
+ if (m_interfaces.length > 0) {
+ String[] newInstances = new String[m_interfaces.length + 1];
+ System.arraycopy(m_interfaces, 0, newInstances, 0, m_interfaces.length);
+ newInstances[m_interfaces.length] = mm;
+ m_interfaces = newInstances;
+ } else {
+ m_interfaces = new String[] { mm };
+ }
+ }
+
+}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java b/ipojo/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java
new file mode 100644
index 0000000..f0db3fb
--- /dev/null
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/parser/MethodMetadata.java
@@ -0,0 +1,66 @@
+/*
+ * 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.parser;
+
+import org.apache.felix.ipojo.metadata.Element;
+
+/**
+ * A Method Metadata represent a method from the implementation class.
+ * This class allow to get information about a method : name, arguments, return type...
+ *
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+public class MethodMetadata {
+
+ /**
+ * Name of the method.
+ */
+ private String m_name;
+
+ /**
+ * Argument type array.
+ */
+ private String[] m_arguments = new String[0];
+
+ /**
+ * Returned type.
+ */
+ private String m_return = "void";
+
+ /**
+ * Constructor.
+ * @param metadata : method manipulation element.
+ */
+ MethodMetadata(Element metadata) {
+ m_name = metadata.getAttribute("name");
+ if (metadata.containsAttribute("arguments")) {
+ m_arguments = ParseUtils.parseArrays(metadata.getAttribute("arguments"));
+ }
+ if (metadata.containsAttribute("return")) {
+ m_return = metadata.getAttribute("return");
+ }
+ }
+
+ public String getMethodName() { return m_name; }
+
+ public String[] getMethodArguments() { return m_arguments; }
+
+ public String getMethodReturn() { return m_return; }
+
+}
diff --git a/ipojo/src/main/java/org/apache/felix/ipojo/util/Callback.java b/ipojo/src/main/java/org/apache/felix/ipojo/util/Callback.java
index 0ebcd62..de877fd 100644
--- a/ipojo/src/main/java/org/apache/felix/ipojo/util/Callback.java
+++ b/ipojo/src/main/java/org/apache/felix/ipojo/util/Callback.java
@@ -22,6 +22,7 @@
import java.lang.reflect.Method;
import org.apache.felix.ipojo.InstanceManager;
+import org.apache.felix.ipojo.parser.MethodMetadata;
/**
* A callback allows calling a method on the component instances.
@@ -102,6 +103,36 @@
m_args[i] = args[i].getName();
}
}
+
+ /**
+ * Constructor.
+ * @param mm : Method Metadata obtain form manipulation metadata.
+ * @param im : instance manager.
+ */
+ public Callback(MethodMetadata mm, InstanceManager im) {
+ m_isStatic = false;
+ m_method = mm.getMethodName();
+ m_manager = im;
+ String[] args = mm.getMethodArguments();
+ m_args = new String[args.length];
+ for (int i = 0; i < args.length; i++) {
+ // Primitive Array
+ if (args[i].endsWith("[]") && args[i].indexOf(".") == -1) {
+ String t = args[i].substring(0, args[i].length() - 2);
+ m_args[i] = "[" + getInternalPrimitiveType(t);
+ }
+ // Non-Primitive Array
+ if (args[i].endsWith("[]") && args[i].indexOf(".") != -1) {
+ String t = args[i].substring(0, args[i].length() - 2);
+ m_args[i] = "[L" + t + ";";
+ }
+ // Simple type
+ if (!args[i].endsWith("[]")) {
+ m_args[i] = args[i];
+ }
+
+ }
+ }
/**
* Get the internal notation for primitive type.