You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by cl...@apache.org on 2008/10/06 19:08:45 UTC
svn commit: r702202 [4/4] - in /felix/trunk/ipojo:
ant/src/main/java/org/apache/felix/ipojo/task/
core/src/main/java/org/apache/felix/ipojo/
handler/eventadmin/src/main/java/org/apache/felix/ipojo/handlers/event/
handler/eventadmin/src/main/java/org/ap...
Modified: felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java?rev=702202&r1=702201&r2=702202&view=diff
==============================================================================
--- felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java (original)
+++ felix/trunk/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java Mon Oct 6 10:08:45 2008
@@ -1,764 +1,764 @@
-/*
- * 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.manipulator;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.jar.Attributes;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Manifest;
-
-import org.apache.felix.ipojo.manipulation.InnerClassManipulator;
-import org.apache.felix.ipojo.manipulation.Manipulator;
-import org.apache.felix.ipojo.manipulation.annotations.MetadataCollector;
-import org.apache.felix.ipojo.metadata.Attribute;
-import org.apache.felix.ipojo.metadata.Element;
-import org.apache.felix.ipojo.xml.parser.ParseException;
-import org.apache.felix.ipojo.xml.parser.XMLMetadataParser;
-import org.objectweb.asm.ClassReader;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-import org.xml.sax.XMLReader;
-
-/**
- * Pojoization allows creating an iPOJO bundle from a "normal" bundle.
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- */
-public class Pojoization {
-
- /**
- * List of component types.
- */
- private List m_components;
-
- /**
- * Metadata (in internal format).
- */
- private Element[] m_metadata = new Element[0];
-
- /**
- * Errors which occur during the manipulation.
- */
- private List m_errors = new ArrayList();
-
- /**
- * Warnings which occur during the manipulation.
- */
- private List m_warnings = new ArrayList();
-
- /**
- * Class map (jar entry, byte[]).
- */
- private Map m_classes = new HashMap();
-
- /**
- * Referenced packages by the composite.
- */
- private List m_referredPackages;
-
- /**
- * Flag describing if we need of not compute annotations.
- */
- private boolean m_ignoreAnnotations;
-
- /**
- * Add an error in the error list.
- * @param mes : error message.
- */
- private void error(String mes) {
- m_errors.add(mes);
- }
-
- /**
- * Add a warning in the warning list.
- * @param mes : warning message
- */
- public void warn(String mes) {
- m_warnings.add(mes);
- }
-
- public List getErrors() {
- return m_errors;
- }
-
- /**
- * Activate annotation processing.
- */
- public void setAnnotationProcessing() {
- m_ignoreAnnotations = false;
- }
-
- /**
- * Manipulate a normal bundle.
- * It will create an iPOJO bundle based on the given metadata file.
- * The original and final bundle must be different.
- * @param in : original bundle.
- * @param out : final bundle.
- * @param metadataFile : iPOJO metadata file (XML).
- */
- public void pojoization(File in, File out, File metadataFile) {
- // Get the metadata.xml location if not null
- if (metadataFile != null) {
- String path = metadataFile.getAbsolutePath();
- if (!path.startsWith("/")) {
- path = "/" + path;
- }
- m_metadata = parseXMLMetadata(path);
- if (m_metadata == null) {
- return;
- }
- }
-
- JarFile inputJar;
- try {
- inputJar = new JarFile(in);
- } catch (IOException e) {
- error("The input file " + in.getAbsolutePath() + " is not a Jar file");
- return;
- }
-
- // Get the list of declared component
- m_components = getDeclaredComponents(m_metadata);
-
- // Start the manipulation
- manipulation(inputJar, out);
-
- // Check that all declared components are manipulated
- for (int i = 0; i < m_components.size(); i++) {
- ComponentInfo ci = (ComponentInfo) m_components.get(i);
- if (!ci.m_isManipulated) {
- error("The component " + ci.m_classname + " is declared but not in the bundle");
- }
- }
- }
-
- /**
- * Parse the content of the input Jar file to detect annotated classes.
- * @param inC : the class to inspect.
- */
- private void computeAnnotations(byte[] inC) {
- ClassReader cr = new ClassReader(inC);
- MetadataCollector xml = new MetadataCollector();
- cr.accept(xml, 0);
- if (xml.isAnnotated()) {
- boolean toskip = false;
- for (int i = 0; !toskip && i < m_metadata.length; i++) {
- if (m_metadata[i].containsAttribute("name")
- && m_metadata[i].getAttribute("name").equalsIgnoreCase(xml.getElem().getAttribute("name"))) {
- toskip = true;
- warn("The component " + xml.getElem().getAttribute("name") + " is overriden by the metadata file");
- }
- }
- if (!toskip) {
- if (m_metadata != null || m_metadata.length != 0) {
- Element[] newElementsList = new Element[m_metadata.length + 1];
- System.arraycopy(m_metadata, 0, newElementsList, 0, m_metadata.length);
- newElementsList[m_metadata.length] = xml.getElem();
- m_metadata = newElementsList;
- } else {
- m_metadata = new Element[] { xml.getElem() };
- }
- String name = m_metadata[m_metadata.length - 1].getAttribute("classname");
- name = name.replace('.', '/');
- name += ".class";
- m_components.add(new ComponentInfo(name, m_metadata[m_metadata.length - 1]));
- }
- }
- }
-
- /**
- * Manipulate the Bundle.
- * @param inputJar : original bundle (JarFile)
- * @param out : final bundle
- */
- private void manipulation(JarFile inputJar, File out) {
- manipulateComponents(inputJar); // Manipulate classes
- m_referredPackages = getReferredPackages();
- Manifest mf = doManifest(inputJar); // Compute the manifest
-
- // Create a new Jar file
- FileOutputStream fos = null;
- JarOutputStream jos = null;
- try {
- fos = new FileOutputStream(out);
- jos = new JarOutputStream(fos, mf);
- } catch (FileNotFoundException e1) {
- error("Cannot manipulate the Jar file : the output file " + out.getAbsolutePath() + " is not found");
- return;
- } catch (IOException e) {
- error("Cannot manipulate the Jar file : cannot access to " + out.getAbsolutePath());
- return;
- }
-
- try {
- // Copy classes and resources
- Enumeration entries = inputJar.entries();
- while (entries.hasMoreElements()) {
- JarEntry curEntry = (JarEntry) entries.nextElement();
- // Check if we need to manipulate the class
- if (m_classes.containsKey(curEntry.getName())) {
- JarEntry je = new JarEntry(curEntry.getName());
- byte[] outClazz = (byte[]) m_classes.get(curEntry.getName());
- if (outClazz.length != 0) {
- jos.putNextEntry(je); // copy the entry header to jos
- jos.write(outClazz);
- jos.closeEntry();
- } else { // The class is already manipulated
- jos.putNextEntry(curEntry);
- InputStream currIn = inputJar.getInputStream(curEntry);
- int c;
- int i = 0;
- while ((c = currIn.read()) >= 0) {
- jos.write(c);
- i++;
- }
- currIn.close();
- jos.closeEntry();
- }
- } else {
- // Do not copy the manifest
- if (!curEntry.getName().equals("META-INF/MANIFEST.MF")) {
- // copy the entry header to jos
- jos.putNextEntry(curEntry);
- InputStream currIn = inputJar.getInputStream(curEntry);
- int c;
- int i = 0;
- while ((c = currIn.read()) >= 0) {
- jos.write(c);
- i++;
- }
- currIn.close();
- jos.closeEntry();
- }
- }
- }
- } catch (IOException e) {
- error("Cannot manipulate the Jar file : " + e.getMessage());
- return;
- }
-
- try {
- inputJar.close();
- jos.close();
- fos.close();
- jos = null;
- fos = null;
- } catch (IOException e) {
- error("Cannot close the new Jar file : " + e.getMessage());
- return;
- }
- }
-
- /**
- * Manipulate classes of the input Jar.
- * @param inputJar : input bundle.
- */
- private void manipulateComponents(JarFile inputJar) {
- Enumeration entries = inputJar.entries();
- while (entries.hasMoreElements()) {
- JarEntry curEntry = (JarEntry) entries.nextElement();
- if (curEntry.getName().endsWith(".class")) {
- try {
- InputStream currIn = inputJar.getInputStream(curEntry);
- byte[] in = new byte[0];
- int c;
- while ((c = currIn.read()) >= 0) {
- byte[] in2 = new byte[in.length + 1];
- System.arraycopy(in, 0, in2, 0, in.length);
- in2[in.length] = (byte) c;
- in = in2;
- }
- currIn.close();
- if (! m_ignoreAnnotations) {
- computeAnnotations(in);
- }
- // Check if we need to manipulate the class
- for (int i = 0; i < m_components.size(); i++) {
- ComponentInfo ci = (ComponentInfo) m_components.get(i);
- if (ci.m_classname.equals(curEntry.getName())) {
- byte[] outClazz = manipulateComponent(in, curEntry, ci);
- m_classes.put(curEntry.getName(), outClazz);
-
- // Manipulate inner classes ?
- if (!ci.m_inners.isEmpty()) {
- for (int k = 0; k < ci.m_inners.size(); k++) {
- JarEntry inner = inputJar.getJarEntry((String) ci.m_inners.get(k) + ".class");
- manipulateInnerClass(inputJar, inner, (String) ci.m_inners.get(k), ci);
- }
- }
- }
- }
- } catch (IOException e) {
- error("Cannot read the class : " + curEntry.getName());
- return;
- }
- }
- }
- }
-
- /**
- * Manipulates an inner class.
- * @param inputJar input jar
- * @param je inner class jar entry
- * @param innerClassName inner class name
- * @param ci component info of the component owning the inner class
- * @throws IOException the inner class cannot be read
- */
- private void manipulateInnerClass(JarFile inputJar, JarEntry je, String innerClassName, ComponentInfo ci) throws IOException {
- InputStream currIn = inputJar.getInputStream(je);
- byte[] in = new byte[0];
- int c;
- while ((c = currIn.read()) >= 0) {
- byte[] in2 = new byte[in.length + 1];
- System.arraycopy(in, 0, in2, 0, in.length);
- in2[in.length] = (byte) c;
- in = in2;
- }
-
- InnerClassManipulator man = new InnerClassManipulator(ci.m_classname.substring(0, ci.m_classname.length() - 6), ci.m_fields);
- byte[] out = man.manipulate(in);
-
- m_classes.put(je.getName(), out);
-
- }
-
- /**
- * Create the manifest.
- * Set the bundle activator, imports, iPOJO-components clauses
- * @param initial : initial Jar file.
- * @return the generated manifest.
- */
- private Manifest doManifest(JarFile initial) {
- Manifest mf = null;
- try {
- mf = initial.getManifest(); // Get the initial manifest
- } catch (IOException e) {
- e.printStackTrace();
- }
- Attributes att = mf.getMainAttributes();
- setImports(att); // Set the imports (add ipojo and handler namespaces
- setPOJOMetadata(att); // Add iPOJO-Component
- setCreatedBy(att); // Add iPOJO to the creators
- return mf;
- }
-
- /**
- * Manipulate a component class.
- * @param in : the byte array of the class to manipulate
- * @param je : Jar entry of the classes
- * @param ci : attached component info (containing metadata and manipulation metadata)
- * @return the generated class (byte array)
- */
- private byte[] manipulateComponent(byte[] in, JarEntry je, ComponentInfo ci) {
- Manipulator man = new Manipulator();
- try {
- byte[] out = man.manipulate(in); // iPOJO manipulation
- ci.detectMissingFields(man.getFields()); // Detect missing field
- // Insert information to metadata
- ci.m_componentMetadata.addElement(man.getManipulationMetadata());
- ci.m_isManipulated = true;
- ci.m_inners = man.getInnerClasses();
- ci.m_fields = man.getFields().keySet();
- return out;
- } catch (IOException e) {
- error("Cannot manipulate the class " + je.getName() + " : " + e.getMessage());
- return null;
- }
- }
-
- /**
- * Return the list of "concrete" component.
- * @param meta : metadata.
- * @return the list of component info requiring a manipulation.
- */
- private List getDeclaredComponents(Element[] meta) {
- List componentClazzes = new ArrayList();
- for (int i = 0; i < meta.length; i++) {
- String name = meta[i].getAttribute("classname");
- if (name != null) { // Only handler and component have a classname attribute
- name = name.replace('.', '/');
- name += ".class";
- componentClazzes.add(new ComponentInfo(name, meta[i]));
- }
- }
- return componentClazzes;
- }
-
- /**
- * Component Info.
- * Represent a component type to be manipulated or already manipulated.
- * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
- */
- private class ComponentInfo {
- /**
- * Component Type metadata.
- */
- Element m_componentMetadata;
-
- /**
- * Component Type implementation class.
- */
- String m_classname;
-
- /**
- * Is the class already manipulated.
- */
- boolean m_isManipulated;
-
- /**
- * List of inner classes of the implementation class.
- */
- List m_inners;
-
- /**
- * Set of fields of the implementation class.
- */
- Set m_fields;
-
- /**
- * Constructor.
- * @param cn : class name
- * @param met : component type metadata
- */
- ComponentInfo(String cn, Element met) {
- this.m_classname = cn;
- this.m_componentMetadata = met;
- m_isManipulated = false;
- }
-
- /**
- * Detects missing fields.
- * If a referenced field does not exist in the class
- * the method throws an error breaking the build process.
- * @param fields : field found in the manipulated class
- */
- void detectMissingFields(Map fields) {
- // First, compute the list of referred fields
- List list = new ArrayList();
- computeReferredFields(list, m_componentMetadata);
- // Then, try to find each referred field in the given field map
- for (int i = 0; i < list.size(); i++) {
- if (!fields.containsKey(list.get(i))) {
- error("The field " + list.get(i) + " is referenced in the "
- + "metadata but does not exist in the " + m_classname + " class");
- }
- }
- }
-
- /**
- * Looks for 'field' attribute in the given metadata.
- * @param list : discovered field (accumulator)
- * @param metadata : metadata to inspect
- */
- private void computeReferredFields(List list, Element metadata) {
- String field = metadata.getAttribute("field");
- if (field != null && ! list.contains(field)) {
- list.add(field);
- }
- for (int i = 0; i < metadata.getElements().length; i++) {
- computeReferredFields(list, metadata.getElements()[i]);
- }
- }
-
- }
-
- /**
- * Set the create-by in the manifest.
- * @param att : manifest attribute.
- */
- private void setCreatedBy(Attributes att) {
- String prev = att.getValue("Created-By");
- att.putValue("Created-By", prev + " & iPOJO");
- }
-
- /**
- * Add imports to the given manifest attribute list. This method add ipojo imports and handler imports (if needed).
- * @param att : the manifest attribute list to modify.
- */
- private void setImports(Attributes att) {
- Map imports = parseHeader(att.getValue("Import-Package"));
- Map ver = new TreeMap();
- ver.put("version", "0.9.0");
- if (!imports.containsKey("org.apache.felix.ipojo")) {
- imports.put("org.apache.felix.ipojo", ver);
- }
- if (!imports.containsKey("org.apache.felix.ipojo.architecture")) {
- imports.put("org.apache.felix.ipojo.architecture", ver);
- }
- if (!imports.containsKey("org.osgi.service.cm")) {
- Map verCM = new TreeMap();
- verCM.put("version", "1.2");
- imports.put("org.osgi.service.cm", verCM);
- }
- if (!imports.containsKey("org.osgi.service.log")) {
- Map verCM = new TreeMap();
- verCM.put("version", "1.3");
- imports.put("org.osgi.service.log", verCM);
- }
-
- // Add referred imports from the metadata
- for (int i = 0; i < m_referredPackages.size(); i++) {
- String pack = (String) m_referredPackages.get(i);
- imports.put(pack, new TreeMap());
- }
-
- // Write imports
- att.putValue("Import-Package", printClauses(imports, "resolution:"));
- }
-
- /**
- * Add iPOJO-Components to the given manifest attribute list. This method add the iPOJO-Components header and its value (according to the metadata) to the manifest.
- * @param att : the manifest attribute list to modify.
- */
- private void setPOJOMetadata(Attributes att) {
- String meta = "";
- for (int i = 0; i < m_metadata.length; i++) {
- meta += buildManifestMetadata(m_metadata[i], "");
- }
- if (!meta.equals("")) {
- att.putValue("iPOJO-Components", meta);
- }
- }
-
- /**
- * Standard OSGi header parser. This parser can handle the format clauses ::= clause ( ',' clause ) + clause ::= name ( ';' name ) (';' key '=' value )
- * This is mapped to a Map { name => Map { attr|directive => value } }
- *
- * @param value : String to parse.
- * @return parsed map.
- */
- public Map parseHeader(String value) {
- if (value == null || value.trim().length() == 0) {
- return new HashMap();
- }
-
- Map result = new HashMap();
- QuotedTokenizer qt = new QuotedTokenizer(value, ";=,");
- char del;
- do {
- boolean hadAttribute = false;
- Map clause = new HashMap();
- List aliases = new ArrayList();
- aliases.add(qt.nextToken());
- del = qt.getSeparator();
- while (del == ';') {
- String adname = qt.nextToken();
- if ((del = qt.getSeparator()) != '=') {
- if (hadAttribute) {
- throw new IllegalArgumentException("Header contains name field after attribute or directive: " + adname + " from " + value);
- }
- aliases.add(adname);
- } else {
- String advalue = qt.nextToken();
- clause.put(adname, advalue);
- del = qt.getSeparator();
- hadAttribute = true;
- }
- }
- for (Iterator i = aliases.iterator(); i.hasNext();) {
- result.put(i.next(), clause);
- }
- } while (del == ',');
- return result;
- }
-
- /**
- * Print a standard Map based OSGi header.
- *
- * @param exports : map { name => Map { attribute|directive => value } }
- * @param allowedDirectives : list of allowed directives.
- * @return the clauses
- */
- public String printClauses(Map exports, String allowedDirectives) {
- StringBuffer sb = new StringBuffer();
- String del = "";
- for (Iterator i = exports.keySet().iterator(); i.hasNext();) {
- String name = (String) i.next();
- Map map = (Map) exports.get(name);
- sb.append(del);
- sb.append(name);
-
- for (Iterator j = map.keySet().iterator(); j.hasNext();) {
- String key = (String) j.next();
-
- // Skip directives we do not recognize
- if (key.endsWith(":") && allowedDirectives.indexOf(key) < 0) {
- continue;
- }
-
- String value = (String) map.get(key);
- sb.append(";");
- sb.append(key);
- sb.append("=");
- boolean dirty = value.indexOf(',') >= 0 || value.indexOf(';') >= 0;
- if (dirty) {
- sb.append("\"");
- }
- sb.append(value);
- if (dirty) {
- sb.append("\"");
- }
- }
- del = ", ";
- }
- return sb.toString();
- }
-
- /**
- * Parse XML Metadata.
- * @param path : path of the file to parse.
- * @return the parsed element array.
- */
- private Element[] parseXMLMetadata(String path) {
- File metadata = new File(path);
- URL url;
- Element[] meta = null;
- try {
- url = metadata.toURL();
- if (url == null) {
- warn("Cannot find the metadata file : " + path);
- return new Element[0];
- }
-
- InputStream stream = url.openStream();
- XMLReader parser = (XMLReader) Class.forName("org.apache.xerces.parsers.SAXParser").newInstance();
- XMLMetadataParser handler = new XMLMetadataParser();
- parser.setContentHandler(handler);
- parser.setFeature("http://xml.org/sax/features/validation",
- true);
- parser.setFeature("http://apache.org/xml/features/validation/schema",
- true);
-
- parser.setErrorHandler(handler);
-
- InputSource is = new InputSource(stream);
- parser.parse(is);
- meta = handler.getMetadata();
- stream.close();
-
- } catch (MalformedURLException e) {
- error("Malformed Metadata URL for " + path);
- return null;
- } catch (IOException e) {
- error("Cannot open the file : " + path);
- return null;
- } catch (ParseException e) {
- error("Parsing Error when parsing the XML file " + path + " : " + e.getMessage());
- return null;
- } catch (SAXParseException e) {
- error("Error during metadata parsing at line " + e.getLineNumber() + " : " + e.getMessage());
- return null;
- } catch (SAXException e) {
- error("Parsing Error when parsing (Sax Error) the XML file " + path + " : " + e.getMessage());
- return null;
- } catch (InstantiationException e) {
- error("Cannot instantiate the SAX parser for the XML file " + path + " : " + e.getMessage());
- return null;
- } catch (IllegalAccessException e) {
- error("Cannot instantiate the SAX parser (IllegalAccess) for the XML file " + path + " : " + e.getMessage());
- return null;
- } catch (ClassNotFoundException e) {
- error("Cannot load the Sax Parser : " + e.getMessage());
- return null;
- }
-
- if (meta == null || meta.length == 0) {
- warn("Neither component types, nor instances in " + path);
- }
-
- return meta;
- }
-
- /**
- * Get packages referenced by composite.
- * @return the list of referenced packages.
- */
- private List getReferredPackages() {
- List referred = new ArrayList();
- for (int i = 0; i < m_metadata.length; i++) {
- if (m_metadata[i].getName().equalsIgnoreCase("composite")) {
- Element[] elems = m_metadata[i].getElements();
- for (int j = 0; j < elems.length; j++) {
- String att = elems[j].getAttribute("specification");
- if (att != null) {
- int last = att.lastIndexOf('.');
- if (last != -1) {
- referred.add(att.substring(0, last));
- }
- }
- }
- }
- }
- return referred;
- }
-
- /**
- * Generate manipulation metadata.
- * @param element : actual element.
- * @param actual : actual manipulation metadata.
- * @return : given manipulation metadata + manipulation metadata of the given element.
- */
- private String buildManifestMetadata(Element element, String actual) {
- String result = "";
- if (element.getNameSpace() == null) {
- result = actual + element.getName() + " { ";
- } else {
- result = actual + element.getNameSpace() + ":" + element.getName() + " { ";
- }
-
- Attribute[] atts = element.getAttributes();
- for (int i = 0; i < atts.length; i++) {
- Attribute current = (Attribute) atts[i];
- if (current.getNameSpace() == null) {
- result = result + "$" + current.getName() + "=\"" + current.getValue() + "\" ";
- } else {
- result = result + "$" + current.getNameSpace() + ":" + current.getName() + "=\"" + current.getValue() + "\" ";
- }
- }
-
- Element[] elems = element.getElements();
- for (int i = 0; i < elems.length; i++) {
- result = buildManifestMetadata(elems[i], result);
- }
-
- return result + "}";
- }
-
- public List getWarnings() {
- return m_warnings;
- }
-
-}
-
+/*
+ * 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.manipulator;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.jar.Attributes;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+
+import org.apache.felix.ipojo.manipulation.InnerClassManipulator;
+import org.apache.felix.ipojo.manipulation.Manipulator;
+import org.apache.felix.ipojo.manipulation.annotations.MetadataCollector;
+import org.apache.felix.ipojo.metadata.Attribute;
+import org.apache.felix.ipojo.metadata.Element;
+import org.apache.felix.ipojo.xml.parser.ParseException;
+import org.apache.felix.ipojo.xml.parser.XMLMetadataParser;
+import org.objectweb.asm.ClassReader;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.XMLReader;
+
+/**
+ * Pojoization allows creating an iPOJO bundle from a "normal" bundle.
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ */
+public class Pojoization {
+
+ /**
+ * List of component types.
+ */
+ private List m_components;
+
+ /**
+ * Metadata (in internal format).
+ */
+ private Element[] m_metadata = new Element[0];
+
+ /**
+ * Errors which occur during the manipulation.
+ */
+ private List m_errors = new ArrayList();
+
+ /**
+ * Warnings which occur during the manipulation.
+ */
+ private List m_warnings = new ArrayList();
+
+ /**
+ * Class map (jar entry, byte[]).
+ */
+ private Map m_classes = new HashMap();
+
+ /**
+ * Referenced packages by the composite.
+ */
+ private List m_referredPackages;
+
+ /**
+ * Flag describing if we need of not compute annotations.
+ */
+ private boolean m_ignoreAnnotations;
+
+ /**
+ * Add an error in the error list.
+ * @param mes : error message.
+ */
+ private void error(String mes) {
+ m_errors.add(mes);
+ }
+
+ /**
+ * Add a warning in the warning list.
+ * @param mes : warning message
+ */
+ public void warn(String mes) {
+ m_warnings.add(mes);
+ }
+
+ public List getErrors() {
+ return m_errors;
+ }
+
+ /**
+ * Activate annotation processing.
+ */
+ public void setAnnotationProcessing() {
+ m_ignoreAnnotations = false;
+ }
+
+ /**
+ * Manipulate a normal bundle.
+ * It will create an iPOJO bundle based on the given metadata file.
+ * The original and final bundle must be different.
+ * @param in : original bundle.
+ * @param out : final bundle.
+ * @param metadataFile : iPOJO metadata file (XML).
+ */
+ public void pojoization(File in, File out, File metadataFile) {
+ // Get the metadata.xml location if not null
+ if (metadataFile != null) {
+ String path = metadataFile.getAbsolutePath();
+ if (!path.startsWith("/")) {
+ path = "/" + path;
+ }
+ m_metadata = parseXMLMetadata(path);
+ if (m_metadata == null) {
+ return;
+ }
+ }
+
+ JarFile inputJar;
+ try {
+ inputJar = new JarFile(in);
+ } catch (IOException e) {
+ error("The input file " + in.getAbsolutePath() + " is not a Jar file");
+ return;
+ }
+
+ // Get the list of declared component
+ m_components = getDeclaredComponents(m_metadata);
+
+ // Start the manipulation
+ manipulation(inputJar, out);
+
+ // Check that all declared components are manipulated
+ for (int i = 0; i < m_components.size(); i++) {
+ ComponentInfo ci = (ComponentInfo) m_components.get(i);
+ if (!ci.m_isManipulated) {
+ error("The component " + ci.m_classname + " is declared but not in the bundle");
+ }
+ }
+ }
+
+ /**
+ * Parse the content of the input Jar file to detect annotated classes.
+ * @param inC : the class to inspect.
+ */
+ private void computeAnnotations(byte[] inC) {
+ ClassReader cr = new ClassReader(inC);
+ MetadataCollector xml = new MetadataCollector();
+ cr.accept(xml, 0);
+ if (xml.isAnnotated()) {
+ boolean toskip = false;
+ for (int i = 0; !toskip && i < m_metadata.length; i++) {
+ if (m_metadata[i].containsAttribute("name")
+ && m_metadata[i].getAttribute("name").equalsIgnoreCase(xml.getElem().getAttribute("name"))) {
+ toskip = true;
+ warn("The component " + xml.getElem().getAttribute("name") + " is overriden by the metadata file");
+ }
+ }
+ if (!toskip) {
+ if (m_metadata != null || m_metadata.length != 0) {
+ Element[] newElementsList = new Element[m_metadata.length + 1];
+ System.arraycopy(m_metadata, 0, newElementsList, 0, m_metadata.length);
+ newElementsList[m_metadata.length] = xml.getElem();
+ m_metadata = newElementsList;
+ } else {
+ m_metadata = new Element[] { xml.getElem() };
+ }
+ String name = m_metadata[m_metadata.length - 1].getAttribute("classname");
+ name = name.replace('.', '/');
+ name += ".class";
+ m_components.add(new ComponentInfo(name, m_metadata[m_metadata.length - 1]));
+ }
+ }
+ }
+
+ /**
+ * Manipulate the Bundle.
+ * @param inputJar : original bundle (JarFile)
+ * @param out : final bundle
+ */
+ private void manipulation(JarFile inputJar, File out) {
+ manipulateComponents(inputJar); // Manipulate classes
+ m_referredPackages = getReferredPackages();
+ Manifest mf = doManifest(inputJar); // Compute the manifest
+
+ // Create a new Jar file
+ FileOutputStream fos = null;
+ JarOutputStream jos = null;
+ try {
+ fos = new FileOutputStream(out);
+ jos = new JarOutputStream(fos, mf);
+ } catch (FileNotFoundException e1) {
+ error("Cannot manipulate the Jar file : the output file " + out.getAbsolutePath() + " is not found");
+ return;
+ } catch (IOException e) {
+ error("Cannot manipulate the Jar file : cannot access to " + out.getAbsolutePath());
+ return;
+ }
+
+ try {
+ // Copy classes and resources
+ Enumeration entries = inputJar.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry curEntry = (JarEntry) entries.nextElement();
+ // Check if we need to manipulate the class
+ if (m_classes.containsKey(curEntry.getName())) {
+ JarEntry je = new JarEntry(curEntry.getName());
+ byte[] outClazz = (byte[]) m_classes.get(curEntry.getName());
+ if (outClazz.length != 0) {
+ jos.putNextEntry(je); // copy the entry header to jos
+ jos.write(outClazz);
+ jos.closeEntry();
+ } else { // The class is already manipulated
+ jos.putNextEntry(curEntry);
+ InputStream currIn = inputJar.getInputStream(curEntry);
+ int c;
+ int i = 0;
+ while ((c = currIn.read()) >= 0) {
+ jos.write(c);
+ i++;
+ }
+ currIn.close();
+ jos.closeEntry();
+ }
+ } else {
+ // Do not copy the manifest
+ if (!curEntry.getName().equals("META-INF/MANIFEST.MF")) {
+ // copy the entry header to jos
+ jos.putNextEntry(curEntry);
+ InputStream currIn = inputJar.getInputStream(curEntry);
+ int c;
+ int i = 0;
+ while ((c = currIn.read()) >= 0) {
+ jos.write(c);
+ i++;
+ }
+ currIn.close();
+ jos.closeEntry();
+ }
+ }
+ }
+ } catch (IOException e) {
+ error("Cannot manipulate the Jar file : " + e.getMessage());
+ return;
+ }
+
+ try {
+ inputJar.close();
+ jos.close();
+ fos.close();
+ jos = null;
+ fos = null;
+ } catch (IOException e) {
+ error("Cannot close the new Jar file : " + e.getMessage());
+ return;
+ }
+ }
+
+ /**
+ * Manipulate classes of the input Jar.
+ * @param inputJar : input bundle.
+ */
+ private void manipulateComponents(JarFile inputJar) {
+ Enumeration entries = inputJar.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry curEntry = (JarEntry) entries.nextElement();
+ if (curEntry.getName().endsWith(".class")) {
+ try {
+ InputStream currIn = inputJar.getInputStream(curEntry);
+ byte[] in = new byte[0];
+ int c;
+ while ((c = currIn.read()) >= 0) {
+ byte[] in2 = new byte[in.length + 1];
+ System.arraycopy(in, 0, in2, 0, in.length);
+ in2[in.length] = (byte) c;
+ in = in2;
+ }
+ currIn.close();
+ if (! m_ignoreAnnotations) {
+ computeAnnotations(in);
+ }
+ // Check if we need to manipulate the class
+ for (int i = 0; i < m_components.size(); i++) {
+ ComponentInfo ci = (ComponentInfo) m_components.get(i);
+ if (ci.m_classname.equals(curEntry.getName())) {
+ byte[] outClazz = manipulateComponent(in, curEntry, ci);
+ m_classes.put(curEntry.getName(), outClazz);
+
+ // Manipulate inner classes ?
+ if (!ci.m_inners.isEmpty()) {
+ for (int k = 0; k < ci.m_inners.size(); k++) {
+ JarEntry inner = inputJar.getJarEntry((String) ci.m_inners.get(k) + ".class");
+ manipulateInnerClass(inputJar, inner, (String) ci.m_inners.get(k), ci);
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ error("Cannot read the class : " + curEntry.getName());
+ return;
+ }
+ }
+ }
+ }
+
+ /**
+ * Manipulates an inner class.
+ * @param inputJar input jar
+ * @param je inner class jar entry
+ * @param innerClassName inner class name
+ * @param ci component info of the component owning the inner class
+ * @throws IOException the inner class cannot be read
+ */
+ private void manipulateInnerClass(JarFile inputJar, JarEntry je, String innerClassName, ComponentInfo ci) throws IOException {
+ InputStream currIn = inputJar.getInputStream(je);
+ byte[] in = new byte[0];
+ int c;
+ while ((c = currIn.read()) >= 0) {
+ byte[] in2 = new byte[in.length + 1];
+ System.arraycopy(in, 0, in2, 0, in.length);
+ in2[in.length] = (byte) c;
+ in = in2;
+ }
+
+ InnerClassManipulator man = new InnerClassManipulator(ci.m_classname.substring(0, ci.m_classname.length() - 6), ci.m_fields);
+ byte[] out = man.manipulate(in);
+
+ m_classes.put(je.getName(), out);
+
+ }
+
+ /**
+ * Create the manifest.
+ * Set the bundle activator, imports, iPOJO-components clauses
+ * @param initial : initial Jar file.
+ * @return the generated manifest.
+ */
+ private Manifest doManifest(JarFile initial) {
+ Manifest mf = null;
+ try {
+ mf = initial.getManifest(); // Get the initial manifest
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ Attributes att = mf.getMainAttributes();
+ setImports(att); // Set the imports (add ipojo and handler namespaces
+ setPOJOMetadata(att); // Add iPOJO-Component
+ setCreatedBy(att); // Add iPOJO to the creators
+ return mf;
+ }
+
+ /**
+ * Manipulate a component class.
+ * @param in : the byte array of the class to manipulate
+ * @param je : Jar entry of the classes
+ * @param ci : attached component info (containing metadata and manipulation metadata)
+ * @return the generated class (byte array)
+ */
+ private byte[] manipulateComponent(byte[] in, JarEntry je, ComponentInfo ci) {
+ Manipulator man = new Manipulator();
+ try {
+ byte[] out = man.manipulate(in); // iPOJO manipulation
+ ci.detectMissingFields(man.getFields()); // Detect missing field
+ // Insert information to metadata
+ ci.m_componentMetadata.addElement(man.getManipulationMetadata());
+ ci.m_isManipulated = true;
+ ci.m_inners = man.getInnerClasses();
+ ci.m_fields = man.getFields().keySet();
+ return out;
+ } catch (IOException e) {
+ error("Cannot manipulate the class " + je.getName() + " : " + e.getMessage());
+ return null;
+ }
+ }
+
+ /**
+ * Return the list of "concrete" component.
+ * @param meta : metadata.
+ * @return the list of component info requiring a manipulation.
+ */
+ private List getDeclaredComponents(Element[] meta) {
+ List componentClazzes = new ArrayList();
+ for (int i = 0; i < meta.length; i++) {
+ String name = meta[i].getAttribute("classname");
+ if (name != null) { // Only handler and component have a classname attribute
+ name = name.replace('.', '/');
+ name += ".class";
+ componentClazzes.add(new ComponentInfo(name, meta[i]));
+ }
+ }
+ return componentClazzes;
+ }
+
+ /**
+ * Component Info.
+ * Represent a component type to be manipulated or already manipulated.
+ * @author <a href="mailto:felix-dev@incubator.apache.org">Felix Project Team</a>
+ */
+ private class ComponentInfo {
+ /**
+ * Component Type metadata.
+ */
+ Element m_componentMetadata;
+
+ /**
+ * Component Type implementation class.
+ */
+ String m_classname;
+
+ /**
+ * Is the class already manipulated.
+ */
+ boolean m_isManipulated;
+
+ /**
+ * List of inner classes of the implementation class.
+ */
+ List m_inners;
+
+ /**
+ * Set of fields of the implementation class.
+ */
+ Set m_fields;
+
+ /**
+ * Constructor.
+ * @param cn : class name
+ * @param met : component type metadata
+ */
+ ComponentInfo(String cn, Element met) {
+ this.m_classname = cn;
+ this.m_componentMetadata = met;
+ m_isManipulated = false;
+ }
+
+ /**
+ * Detects missing fields.
+ * If a referenced field does not exist in the class
+ * the method throws an error breaking the build process.
+ * @param fields : field found in the manipulated class
+ */
+ void detectMissingFields(Map fields) {
+ // First, compute the list of referred fields
+ List list = new ArrayList();
+ computeReferredFields(list, m_componentMetadata);
+ // Then, try to find each referred field in the given field map
+ for (int i = 0; i < list.size(); i++) {
+ if (!fields.containsKey(list.get(i))) {
+ error("The field " + list.get(i) + " is referenced in the "
+ + "metadata but does not exist in the " + m_classname + " class");
+ }
+ }
+ }
+
+ /**
+ * Looks for 'field' attribute in the given metadata.
+ * @param list : discovered field (accumulator)
+ * @param metadata : metadata to inspect
+ */
+ private void computeReferredFields(List list, Element metadata) {
+ String field = metadata.getAttribute("field");
+ if (field != null && ! list.contains(field)) {
+ list.add(field);
+ }
+ for (int i = 0; i < metadata.getElements().length; i++) {
+ computeReferredFields(list, metadata.getElements()[i]);
+ }
+ }
+
+ }
+
+ /**
+ * Set the create-by in the manifest.
+ * @param att : manifest attribute.
+ */
+ private void setCreatedBy(Attributes att) {
+ String prev = att.getValue("Created-By");
+ att.putValue("Created-By", prev + " & iPOJO");
+ }
+
+ /**
+ * Add imports to the given manifest attribute list. This method add ipojo imports and handler imports (if needed).
+ * @param att : the manifest attribute list to modify.
+ */
+ private void setImports(Attributes att) {
+ Map imports = parseHeader(att.getValue("Import-Package"));
+ Map ver = new TreeMap();
+ ver.put("version", "0.9.0");
+ if (!imports.containsKey("org.apache.felix.ipojo")) {
+ imports.put("org.apache.felix.ipojo", ver);
+ }
+ if (!imports.containsKey("org.apache.felix.ipojo.architecture")) {
+ imports.put("org.apache.felix.ipojo.architecture", ver);
+ }
+ if (!imports.containsKey("org.osgi.service.cm")) {
+ Map verCM = new TreeMap();
+ verCM.put("version", "1.2");
+ imports.put("org.osgi.service.cm", verCM);
+ }
+ if (!imports.containsKey("org.osgi.service.log")) {
+ Map verCM = new TreeMap();
+ verCM.put("version", "1.3");
+ imports.put("org.osgi.service.log", verCM);
+ }
+
+ // Add referred imports from the metadata
+ for (int i = 0; i < m_referredPackages.size(); i++) {
+ String pack = (String) m_referredPackages.get(i);
+ imports.put(pack, new TreeMap());
+ }
+
+ // Write imports
+ att.putValue("Import-Package", printClauses(imports, "resolution:"));
+ }
+
+ /**
+ * Add iPOJO-Components to the given manifest attribute list. This method add the iPOJO-Components header and its value (according to the metadata) to the manifest.
+ * @param att : the manifest attribute list to modify.
+ */
+ private void setPOJOMetadata(Attributes att) {
+ String meta = "";
+ for (int i = 0; i < m_metadata.length; i++) {
+ meta += buildManifestMetadata(m_metadata[i], "");
+ }
+ if (!meta.equals("")) {
+ att.putValue("iPOJO-Components", meta);
+ }
+ }
+
+ /**
+ * Standard OSGi header parser. This parser can handle the format clauses ::= clause ( ',' clause ) + clause ::= name ( ';' name ) (';' key '=' value )
+ * This is mapped to a Map { name => Map { attr|directive => value } }
+ *
+ * @param value : String to parse.
+ * @return parsed map.
+ */
+ public Map parseHeader(String value) {
+ if (value == null || value.trim().length() == 0) {
+ return new HashMap();
+ }
+
+ Map result = new HashMap();
+ QuotedTokenizer qt = new QuotedTokenizer(value, ";=,");
+ char del;
+ do {
+ boolean hadAttribute = false;
+ Map clause = new HashMap();
+ List aliases = new ArrayList();
+ aliases.add(qt.nextToken());
+ del = qt.getSeparator();
+ while (del == ';') {
+ String adname = qt.nextToken();
+ if ((del = qt.getSeparator()) != '=') {
+ if (hadAttribute) {
+ throw new IllegalArgumentException("Header contains name field after attribute or directive: " + adname + " from " + value);
+ }
+ aliases.add(adname);
+ } else {
+ String advalue = qt.nextToken();
+ clause.put(adname, advalue);
+ del = qt.getSeparator();
+ hadAttribute = true;
+ }
+ }
+ for (Iterator i = aliases.iterator(); i.hasNext();) {
+ result.put(i.next(), clause);
+ }
+ } while (del == ',');
+ return result;
+ }
+
+ /**
+ * Print a standard Map based OSGi header.
+ *
+ * @param exports : map { name => Map { attribute|directive => value } }
+ * @param allowedDirectives : list of allowed directives.
+ * @return the clauses
+ */
+ public String printClauses(Map exports, String allowedDirectives) {
+ StringBuffer sb = new StringBuffer();
+ String del = "";
+ for (Iterator i = exports.keySet().iterator(); i.hasNext();) {
+ String name = (String) i.next();
+ Map map = (Map) exports.get(name);
+ sb.append(del);
+ sb.append(name);
+
+ for (Iterator j = map.keySet().iterator(); j.hasNext();) {
+ String key = (String) j.next();
+
+ // Skip directives we do not recognize
+ if (key.endsWith(":") && allowedDirectives.indexOf(key) < 0) {
+ continue;
+ }
+
+ String value = (String) map.get(key);
+ sb.append(";");
+ sb.append(key);
+ sb.append("=");
+ boolean dirty = value.indexOf(',') >= 0 || value.indexOf(';') >= 0;
+ if (dirty) {
+ sb.append("\"");
+ }
+ sb.append(value);
+ if (dirty) {
+ sb.append("\"");
+ }
+ }
+ del = ", ";
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Parse XML Metadata.
+ * @param path : path of the file to parse.
+ * @return the parsed element array.
+ */
+ private Element[] parseXMLMetadata(String path) {
+ File metadata = new File(path);
+ URL url;
+ Element[] meta = null;
+ try {
+ url = metadata.toURL();
+ if (url == null) {
+ warn("Cannot find the metadata file : " + path);
+ return new Element[0];
+ }
+
+ InputStream stream = url.openStream();
+ XMLReader parser = (XMLReader) Class.forName("org.apache.xerces.parsers.SAXParser").newInstance();
+ XMLMetadataParser handler = new XMLMetadataParser();
+ parser.setContentHandler(handler);
+ parser.setFeature("http://xml.org/sax/features/validation",
+ true);
+ parser.setFeature("http://apache.org/xml/features/validation/schema",
+ true);
+
+ parser.setErrorHandler(handler);
+
+ InputSource is = new InputSource(stream);
+ parser.parse(is);
+ meta = handler.getMetadata();
+ stream.close();
+
+ } catch (MalformedURLException e) {
+ error("Malformed metadata URL for " + path);
+ return null;
+ } catch (IOException e) {
+ error("Cannot open the file : " + path);
+ return null;
+ } catch (ParseException e) {
+ error("Parsing error when parsing the XML file " + path + " : " + e.getMessage());
+ return null;
+ } catch (SAXParseException e) {
+ error("Error during metadata parsing at line " + e.getLineNumber() + " : " + e.getMessage());
+ return null;
+ } catch (SAXException e) {
+ error("Parsing error when parsing (Sax Error) the XML file " + path + " : " + e.getMessage());
+ return null;
+ } catch (InstantiationException e) {
+ error("Cannot instantiate the SAX parser for the XML file " + path + " : " + e.getMessage());
+ return null;
+ } catch (IllegalAccessException e) {
+ error("Cannot instantiate the SAX parser (IllegalAccess) for the XML file " + path + " : " + e.getMessage());
+ return null;
+ } catch (ClassNotFoundException e) {
+ error("Cannot load the SAX Parser : " + e.getMessage());
+ return null;
+ }
+
+ if (meta == null || meta.length == 0) {
+ warn("Neither component types, nor instances in " + path);
+ }
+
+ return meta;
+ }
+
+ /**
+ * Get packages referenced by composite.
+ * @return the list of referenced packages.
+ */
+ private List getReferredPackages() {
+ List referred = new ArrayList();
+ for (int i = 0; i < m_metadata.length; i++) {
+ if (m_metadata[i].getName().equalsIgnoreCase("composite")) {
+ Element[] elems = m_metadata[i].getElements();
+ for (int j = 0; j < elems.length; j++) {
+ String att = elems[j].getAttribute("specification");
+ if (att != null) {
+ int last = att.lastIndexOf('.');
+ if (last != -1) {
+ referred.add(att.substring(0, last));
+ }
+ }
+ }
+ }
+ }
+ return referred;
+ }
+
+ /**
+ * Generate manipulation metadata.
+ * @param element : actual element.
+ * @param actual : actual manipulation metadata.
+ * @return : given manipulation metadata + manipulation metadata of the given element.
+ */
+ private String buildManifestMetadata(Element element, String actual) {
+ String result = "";
+ if (element.getNameSpace() == null) {
+ result = actual + element.getName() + " { ";
+ } else {
+ result = actual + element.getNameSpace() + ":" + element.getName() + " { ";
+ }
+
+ Attribute[] atts = element.getAttributes();
+ for (int i = 0; i < atts.length; i++) {
+ Attribute current = (Attribute) atts[i];
+ if (current.getNameSpace() == null) {
+ result = result + "$" + current.getName() + "=\"" + current.getValue() + "\" ";
+ } else {
+ result = result + "$" + current.getNameSpace() + ":" + current.getName() + "=\"" + current.getValue() + "\" ";
+ }
+ }
+
+ Element[] elems = element.getElements();
+ for (int i = 0; i < elems.length; i++) {
+ result = buildManifestMetadata(elems[i], result);
+ }
+
+ return result + "}";
+ }
+
+ public List getWarnings() {
+ return m_warnings;
+ }
+
+}
+
Modified: felix/trunk/ipojo/plugin/src/main/java/org/apache/felix/ipojo/plugin/ManipulatorMojo.java
URL: http://svn.apache.org/viewvc/felix/trunk/ipojo/plugin/src/main/java/org/apache/felix/ipojo/plugin/ManipulatorMojo.java?rev=702202&r1=702201&r2=702202&view=diff
==============================================================================
--- felix/trunk/ipojo/plugin/src/main/java/org/apache/felix/ipojo/plugin/ManipulatorMojo.java (original)
+++ felix/trunk/ipojo/plugin/src/main/java/org/apache/felix/ipojo/plugin/ManipulatorMojo.java Mon Oct 6 10:08:45 2008
@@ -1,177 +1,177 @@
-/*
- * 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.plugin;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.List;
-
-import org.apache.felix.ipojo.manipulator.Pojoization;
-import org.apache.maven.plugin.AbstractMojo;
-import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.project.MavenProject;
-import org.apache.maven.project.MavenProjectHelper;
-
-/**
- * Packages an OSGi jar "bundle" as an "iPOJO bundle".
- *
- * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
- * @version $Rev$, $Date$
- * @goal ipojo-bundle
- * @phase package
- * @requiresDependencyResolution runtime
- * @description manipulate an OSGi bundle jar to build an iPOJO bundle
- */
-public class ManipulatorMojo extends AbstractMojo {
-
- /**
- * The directory for the generated JAR.
- *
- * @parameter expression="${project.build.directory}"
- * @required
- */
- private String m_buildDirectory;
-
- /**
- * The directory containing generated classes.
- *
- * @parameter expression="${project.build.outputDirectory}"
- * @required
- * @readonly
- */
- private File m_outputDirectory;
-
- /**
- * The name of the generated JAR file.
- *
- * @parameter alias="jarName" expression="${project.build.finalName}"
- * @required
- */
- private String m_jarName;
-
- /**
- * Location of the metadata file.
- * @parameter alias="metadata" default-value="metadata.xml"
- */
- private String m_metadata;
-
- /**
- * If set, the manipulated jar will be attached to the project as a separate artifact.
- *
- * @parameter alias="classifier" expression="${ipojo.classifier}"
- */
- private String m_classifier;
-
- /**
- * The Maven project.
- *
- * @parameter expression="${project}"
- * @required
- * @readonly
- */
- private MavenProject m_project;
-
- /**
- * Used for attaching new artifacts.
- * @component
- * @required
- */
- private MavenProjectHelper m_helper;
-
- /**
- * Project types which this plugin supports.
- * @parameter
- */
- private List m_supportedProjectTypes = Arrays.asList(new String[]{"bundle"});
-
- /**
- * Ignore annotations parameter.
- * @parameter alias="ignoreAnnotations" default-value="false"
- */
- private boolean m_ignoreAnnotations;
-
- protected MavenProject getProject() {
- return this.m_project;
- }
-
- /**
- * Execute method : this method launches the pojoization.
- * @throws MojoExecutionException : an exception occurs during the manipulation.
- * @see org.apache.maven.plugin.AbstractMojo#execute()
- */
- public void execute() throws MojoExecutionException {
- // ignore project types not supported, useful when the plugin is configured in the parent pom
- if (!this.m_supportedProjectTypes.contains(this.getProject().getArtifact().getType())) {
- this.getLog().debug("Ignoring project " + this.getProject().getArtifact() + " : type " + this.getProject().getArtifact().getType() + " is not supported by ipojo plugin, supported types are " + this.m_supportedProjectTypes);
- return;
- }
-
- getLog().info("Start bundle manipulation");
- // Get metadata file
-
- // Look for the metadata file in the output directory
- File meta = new File(m_outputDirectory + File.separator + m_metadata);
-
- // If not found look inside the pom directory
- if (! meta.exists()) {
- meta = new File(m_project.getBasedir() + File.separator + m_metadata);
- }
-
- getLog().info("Metadata File : " + meta.getAbsolutePath());
- if (!meta.exists()) {
- // Verify if annotations are ignored
- if (m_ignoreAnnotations) {
- getLog().info("No metadata file found - ignore annotations");
- return;
- } else {
- getLog().info("No metadata file found - try to use only annotations");
- meta = null;
- }
- }
-
- // Get input bundle
- File in = new File(m_buildDirectory + File.separator + m_jarName + ".jar");
- getLog().info("Input Bundle File : " + in.getAbsolutePath());
- if (!in.exists()) {
- throw new MojoExecutionException("the specified bundle file does not exists");
- }
-
- File out = new File(m_buildDirectory + File.separator + "_out.jar");
-
- Pojoization pojo = new Pojoization();
- if (!m_ignoreAnnotations) { pojo.setAnnotationProcessing(); }
- pojo.pojoization(in, out, meta);
- for (int i = 0; i < pojo.getWarnings().size(); i++) {
- getLog().warn((String) pojo.getWarnings().get(i));
- }
- if (pojo.getErrors().size() > 0) { throw new MojoExecutionException((String) pojo.getErrors().get(0)); }
-
- if (m_classifier != null) {
- // The user want to attach the resulting jar
- // Do not delete in File
- m_helper.attachArtifact(m_project, "jar", m_classifier, out);
- } else {
- // Usual behavior
- in.delete();
- out.renameTo(in);
- }
- getLog().info("Bundle manipulation - SUCCESS");
- }
-
-}
+/*
+ * 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.plugin;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+import org.apache.felix.ipojo.manipulator.Pojoization;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.project.MavenProject;
+import org.apache.maven.project.MavenProjectHelper;
+
+/**
+ * Packages an OSGi jar "bundle" as an "iPOJO bundle".
+ *
+ * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
+ * @version $Rev$, $Date$
+ * @goal ipojo-bundle
+ * @phase package
+ * @requiresDependencyResolution runtime
+ * @description manipulate an OSGi bundle jar to build an iPOJO bundle
+ */
+public class ManipulatorMojo extends AbstractMojo {
+
+ /**
+ * The directory for the generated JAR.
+ *
+ * @parameter expression="${project.build.directory}"
+ * @required
+ */
+ private String m_buildDirectory;
+
+ /**
+ * The directory containing generated classes.
+ *
+ * @parameter expression="${project.build.outputDirectory}"
+ * @required
+ * @readonly
+ */
+ private File m_outputDirectory;
+
+ /**
+ * The name of the generated JAR file.
+ *
+ * @parameter alias="jarName" expression="${project.build.finalName}"
+ * @required
+ */
+ private String m_jarName;
+
+ /**
+ * Location of the metadata file.
+ * @parameter alias="metadata" default-value="metadata.xml"
+ */
+ private String m_metadata;
+
+ /**
+ * If set, the manipulated jar will be attached to the project as a separate artifact.
+ *
+ * @parameter alias="classifier" expression="${ipojo.classifier}"
+ */
+ private String m_classifier;
+
+ /**
+ * The Maven project.
+ *
+ * @parameter expression="${project}"
+ * @required
+ * @readonly
+ */
+ private MavenProject m_project;
+
+ /**
+ * Used for attaching new artifacts.
+ * @component
+ * @required
+ */
+ private MavenProjectHelper m_helper;
+
+ /**
+ * Project types which this plugin supports.
+ * @parameter
+ */
+ private List m_supportedProjectTypes = Arrays.asList(new String[]{"bundle"});
+
+ /**
+ * Ignore annotations parameter.
+ * @parameter alias="ignoreAnnotations" default-value="false"
+ */
+ private boolean m_ignoreAnnotations;
+
+ protected MavenProject getProject() {
+ return this.m_project;
+ }
+
+ /**
+ * Execute method : this method launches the pojoization.
+ * @throws MojoExecutionException : an exception occurs during the manipulation.
+ * @see org.apache.maven.plugin.AbstractMojo#execute()
+ */
+ public void execute() throws MojoExecutionException {
+ // ignore project types not supported, useful when the plugin is configured in the parent pom
+ if (!this.m_supportedProjectTypes.contains(this.getProject().getArtifact().getType())) {
+ this.getLog().debug("Ignoring project " + this.getProject().getArtifact() + " : type " + this.getProject().getArtifact().getType() + " is not supported by iPOJO plugin, supported types are " + this.m_supportedProjectTypes);
+ return;
+ }
+
+ getLog().info("Start bundle manipulation");
+ // Get metadata file
+
+ // Look for the metadata file in the output directory
+ File meta = new File(m_outputDirectory + File.separator + m_metadata);
+
+ // If not found look inside the pom directory
+ if (! meta.exists()) {
+ meta = new File(m_project.getBasedir() + File.separator + m_metadata);
+ }
+
+ getLog().info("Metadata file : " + meta.getAbsolutePath());
+ if (!meta.exists()) {
+ // Verify if annotations are ignored
+ if (m_ignoreAnnotations) {
+ getLog().info("No metadata file found - ignoring annotations");
+ return;
+ } else {
+ getLog().info("No metadata file found - trying to use only annotations");
+ meta = null;
+ }
+ }
+
+ // Get input bundle
+ File in = new File(m_buildDirectory + File.separator + m_jarName + ".jar");
+ getLog().info("Input Bundle File : " + in.getAbsolutePath());
+ if (!in.exists()) {
+ throw new MojoExecutionException("the specified bundle file does not exist");
+ }
+
+ File out = new File(m_buildDirectory + File.separator + "_out.jar");
+
+ Pojoization pojo = new Pojoization();
+ if (!m_ignoreAnnotations) { pojo.setAnnotationProcessing(); }
+ pojo.pojoization(in, out, meta);
+ for (int i = 0; i < pojo.getWarnings().size(); i++) {
+ getLog().warn((String) pojo.getWarnings().get(i));
+ }
+ if (pojo.getErrors().size() > 0) { throw new MojoExecutionException((String) pojo.getErrors().get(0)); }
+
+ if (m_classifier != null) {
+ // The user want to attach the resulting jar
+ // Do not delete in File
+ m_helper.attachArtifact(m_project, "jar", m_classifier, out);
+ } else {
+ // Usual behavior
+ in.delete();
+ out.renameTo(in);
+ }
+ getLog().info("Bundle manipulation - SUCCESS");
+ }
+
+}