Fix issue Felix-943.
The new manipulator is now able to manipulate class from a directory.
In this mode, the manifest location can also be set (by default META-INF/MANIFEST.MF).
The Ant task was modified to support this mode.
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@744877 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/ipojo/ant/src/main/java/org/apache/felix/ipojo/task/IPojoTask.java b/ipojo/ant/src/main/java/org/apache/felix/ipojo/task/IPojoTask.java
index 046ebc2..acdb568 100644
--- a/ipojo/ant/src/main/java/org/apache/felix/ipojo/task/IPojoTask.java
+++ b/ipojo/ant/src/main/java/org/apache/felix/ipojo/task/IPojoTask.java
@@ -39,6 +39,12 @@
/** Output bundle. */
private File m_output;
+
+ /** Input directory. */
+ private File m_directory;
+
+ /** Input manifest. */
+ private File m_manifest;
/** Flag describing if we need to ignore annotation of not. */
private boolean m_ignoreAnnotations = false;
@@ -59,6 +65,14 @@
}
/**
+ * Set the manifest file.
+ * @param manifest : the manifest file.
+ */
+ public void setManifest(File manifest) {
+ m_manifest = manifest;
+ }
+
+ /**
* Set the input bundle.
* @param in : the input bundle
*/
@@ -67,6 +81,14 @@
}
/**
+ * Set the input directory.
+ * @param dir : the input directory
+ */
+ public void setDir(File dir) {
+ m_directory = dir;
+ }
+
+ /**
* Set the output bundle.
* @param out : the output bundle
*/
@@ -96,14 +118,36 @@
*/
public void execute() {
- if (m_input == null) {
- throw new BuildException("No input bundle specified");
+ if (m_input == null && m_directory == null) {
+ throw new BuildException("Neither input bundle nor directory specified");
}
- if (!m_input.exists()) {
+
+ if (m_input != null && !m_input.exists()) {
throw new BuildException("The input bundle " + m_input.getAbsolutePath() + " does not exist");
}
- log("Input bundle file : " + m_input.getAbsolutePath());
+ if (m_directory != null && !m_directory.exists()) {
+ throw new BuildException("The input directory " + m_directory.getAbsolutePath() + " does not exist");
+ }
+ if (m_directory != null && !m_directory.isDirectory()) {
+ throw new BuildException("The input directory " + m_directory.getAbsolutePath() + " is not a directory");
+ }
+
+
+ if (m_input != null) {
+ log("Input bundle file : " + m_input.getAbsolutePath());
+ } else {
+ log("Input directory : " + m_directory.getAbsolutePath());
+ }
+
+ if (m_manifest != null) {
+ if (m_input != null) {
+ throw new BuildException("The manifest location cannot be used when manipulating an existing bundle");
+ }
+ if (! m_manifest.exists()) {
+ throw new BuildException("The manifest file " + m_manifest.getAbsolutePath() + " does not exist");
+ }
+ }
// Get metadata file
if (m_metadata == null) {
@@ -128,18 +172,20 @@
log("Metadata file : " + m_metadata.getAbsolutePath());
}
}
+
- log("Start bundle manipulation");
+ log("Start manipulation");
- if (m_output == null) {
- m_output = new File("./_out.jar");
+ if (m_input != null) { // Prepare output file
+ if (m_output == null) {
+ m_output = new File("./_out.jar");
+ }
+ if (m_output.exists()) {
+ boolean r = m_output.delete();
+ if (!r) { throw new BuildException("The file " + m_output.getAbsolutePath() + " cannot be deleted"); }
+ }
}
-
- if (m_output.exists()) {
- boolean r = m_output.delete();
- if (!r) { throw new BuildException("The file " + m_output.getAbsolutePath() + " cannot be deleted"); }
- }
-
+
Pojoization pojo = new Pojoization();
if (! m_ignoreAnnotations) {
pojo.setAnnotationProcessing();
@@ -147,28 +193,41 @@
if (! m_ignoreLocalXSD) {
pojo.setUseLocalXSD();
}
- pojo.pojoization(m_input, m_output, m_metadata);
+ if (m_input != null) {
+ pojo.pojoization(m_input, m_output, m_metadata);
+ } else {
+ pojo.directoryPojoization(m_directory,m_metadata, m_manifest);
+ }
for (int i = 0; i < pojo.getWarnings().size(); i++) {
log((String) pojo.getWarnings().get(i), Project.MSG_WARN);
}
if (pojo.getErrors().size() > 0) { throw new BuildException((String) pojo.getErrors().get(0)); }
- String out;
- if (m_output.getName().equals("_out.jar")) {
- if (m_input.delete()) {
- if (! m_output.renameTo(m_input)) {
- log("Cannot rename the output jar to " + m_input.getAbsolutePath(), Project.MSG_WARN);
- }
+ if (m_input != null) {
+ String out;
+ if (m_output.getName().equals("_out.jar")) {
+ if (m_input.delete()) {
+ if (! m_output.renameTo(m_input)) {
+ log("Cannot rename the output jar to " + m_input.getAbsolutePath(), Project.MSG_WARN);
+ }
+ } else {
+ log("Cannot delete the input file : " + m_input.getAbsolutePath(), Project.MSG_WARN);
+ }
+ out = m_input.getAbsolutePath();
} else {
- log("Cannot delete the input file : " + m_input.getAbsolutePath(), Project.MSG_WARN);
+ out = m_output.getAbsolutePath();
}
- out = m_input.getAbsolutePath();
- } else {
- out = m_output.getAbsolutePath();
- }
- log("Bundle manipulation - SUCCESS");
- log("Output file : " + out);
+ log("Bundle manipulation - SUCCESS");
+ log("Output file : " + out);
+ } else {
+ log("Manipulation - SUCCESS");
+ log("Output files : " + m_directory.getAbsolutePath());
+ if (m_manifest != null) {
+ log("Manifest : " + m_manifest.getAbsolutePath());
+ }
+
+ }
}
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/InnerClassManipulator.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/InnerClassManipulator.java
index 9c0fdd9..605ac23 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/InnerClassManipulator.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulation/InnerClassManipulator.java
@@ -34,7 +34,7 @@
public class InnerClassManipulator {
/**
- * Component implementation class name.
+ * Outer class class name.
*/
private String m_outer;
diff --git a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
index 9f23b5c..e6ca46b 100644
--- a/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
+++ b/ipojo/manipulator/src/main/java/org/apache/felix/ipojo/manipulator/Pojoization.java
@@ -19,10 +19,12 @@
package org.apache.felix.ipojo.manipulator;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
@@ -33,6 +35,7 @@
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+import java.util.Vector;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
@@ -62,7 +65,7 @@
/**
* iPOJO Imported Package Version.
*/
- public static final String IPOJO_PACKAGE_VERSION = " 1.2.0";
+ public static final String IPOJO_PACKAGE_VERSION = " 1.3.0";
/**
* List of component types.
@@ -85,7 +88,7 @@
private List m_warnings = new ArrayList();
/**
- * Class map (jar entry, byte[]).
+ * Class map (class name, byte[]).
*/
private Map m_classes = new HashMap();
@@ -105,6 +108,21 @@
* If <code>true</code> the local XSD are not used.
*/
private boolean m_ignoreLocalXSD;
+
+ /**
+ * Input jar file.
+ */
+ private JarFile m_inputJar;
+
+ /**
+ * The manipulated directory.
+ */
+ private File m_dir;
+
+ /**
+ * The manifest location.
+ */
+ private File m_manifest;
/**
* Add an error in the error list.
@@ -150,7 +168,7 @@
* @param metadata the iPOJO metadata input stream.
*/
public void pojoization(File in, File out, InputStream metadata) {
- m_metadata = parseXMLMetadata(metadata);
+ parseXMLMetadata(metadata);
if (m_metadata == null) { // An error occurs during the parsing.
return;
}
@@ -158,19 +176,18 @@
// array with component type description. It also can be null
// if no metadata file is given.
- JarFile inputJar;
try {
- inputJar = new JarFile(in);
+ m_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);
+ computeDeclaredComponents();
// Start the manipulation
- manipulation(inputJar, out);
+ manipulateJarFile(out);
// Check that all declared components are manipulated
for (int i = 0; i < m_components.size(); i++) {
@@ -192,46 +209,21 @@
public void pojoization(File in, File out, File metadataFile) {
// Get the metadata.xml location if not null
if (metadataFile != null) {
- try {
- InputStream stream = null;
- URL url = metadataFile.toURL();
- if (url == null) {
- warn("Cannot find the metadata file : " + metadataFile.getAbsolutePath());
- m_metadata = new Element[0];
- } else {
- stream = url.openStream();
- m_metadata = parseXMLMetadata(stream);
- }
- } catch (MalformedURLException e) {
- error("Cannot open the metadata input stream from " + metadataFile.getAbsolutePath() + ": " + e.getMessage());
- m_metadata = null;
- } catch (IOException e) {
- error("Cannot open the metadata input stream: " + metadataFile.getAbsolutePath() + ": " + e.getMessage());
- m_metadata = null;
- }
-
- if (m_metadata == null) { // An error occurs during the parsing.
- return;
- }
-
- // m_metadata can be either an empty array or an Element
- // array with component type description. It also can be null
- // if no metadata file is given.
+ parseXMLMetadata(metadataFile);
}
- JarFile inputJar;
try {
- inputJar = new JarFile(in);
+ m_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);
+ computeDeclaredComponents();
// Start the manipulation
- manipulation(inputJar, out);
+ manipulateJarFile(out);
// Check that all declared components are manipulated
for (int i = 0; i < m_components.size(); i++) {
@@ -241,10 +233,56 @@
}
}
}
+
+ /**
+ * Manipulates an expanded bundles.
+ * Classes are in the specified directory.
+ * this method allows to update a customized manifest.
+ * @param directory the directory containing classes
+ * @param metadataFile the metadata file
+ * @param manifestFile the manifest file. <code>null</code> to use directory/META-INF/MANIFEST.mf
+ */
+ public void directoryPojoization(File directory, File metadataFile, File manifestFile) {
+ // Get the metadata.xml location if not null
+ if (metadataFile != null) {
+ parseXMLMetadata(metadataFile);
+ }
+
+ if (directory.exists() && directory.isDirectory()) {
+ m_dir = directory;
+ } else {
+ error("The directory " + directory.getAbsolutePath() + " does not exist or is not a directory.");
+ }
+
+
+ if (manifestFile != null) {
+ if (manifestFile.exists()) {
+ m_manifest = manifestFile;
+ } else {
+ error("The manifest file " + manifestFile.getAbsolutePath() + " does not exist");
+ }
+ }
+ // If the manifest is not specified, the m_dir/META-INF/MANIFEST.MF is used.
+
+ // Get the list of declared component
+ computeDeclaredComponents();
+
+ // Start the manipulation
+ manipulateDirectory();
+
+ // 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.
+ * Parse the content of the class to detect annotated classes.
+ * @param inC the class to inspect.
*/
private void computeAnnotations(byte[] inC) {
ClassReader cr = new ClassReader(inC);
@@ -278,14 +316,13 @@
}
/**
- * Manipulate the Bundle.
- * @param inputJar : original bundle (JarFile)
- * @param out : final bundle
+ * Manipulate the input bundle.
+ * @param out final bundle
*/
- private void manipulation(JarFile inputJar, File out) {
- manipulateComponents(inputJar); // Manipulate classes
+ private void manipulateJarFile(File out) {
+ manipulateComponents(); // Manipulate classes
m_referredPackages = getReferredPackages();
- Manifest mf = doManifest(inputJar); // Compute the manifest
+ Manifest mf = doManifest(); // Compute the manifest
// Create a new Jar file
FileOutputStream fos = null;
@@ -303,7 +340,7 @@
try {
// Copy classes and resources
- Enumeration entries = inputJar.entries();
+ Enumeration entries = m_inputJar.entries();
while (entries.hasMoreElements()) {
JarEntry curEntry = (JarEntry) entries.nextElement();
// Check if we need to manipulate the class
@@ -316,7 +353,7 @@
jos.closeEntry();
} else { // The class is already manipulated
jos.putNextEntry(curEntry);
- InputStream currIn = inputJar.getInputStream(curEntry);
+ InputStream currIn = m_inputJar.getInputStream(curEntry);
int c;
int i = 0;
while ((c = currIn.read()) >= 0) {
@@ -331,7 +368,7 @@
if (!curEntry.getName().equals("META-INF/MANIFEST.MF")) {
// copy the entry header to jos
jos.putNextEntry(curEntry);
- InputStream currIn = inputJar.getInputStream(curEntry);
+ InputStream currIn = m_inputJar.getInputStream(curEntry);
int c;
int i = 0;
while ((c = currIn.read()) >= 0) {
@@ -349,7 +386,7 @@
}
try {
- inputJar.close();
+ m_inputJar.close();
jos.close();
fos.close();
jos = null;
@@ -359,93 +396,279 @@
return;
}
}
+
+ /**
+ * Manipulate the input directory.
+ */
+ private void manipulateDirectory() {
+ manipulateComponents(); // Manipulate classes
+ m_referredPackages = getReferredPackages();
+ Manifest mf = doManifest(); // Compute the manifest
+ if (mf == null) {
+ error("Cannot found input manifest");
+ return;
+ }
+
+ // Write every manipulated file.
+ Iterator it = m_classes.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry entry = (Map.Entry) it.next();
+ String classname = (String) entry.getKey();
+ byte[] clazz = (byte[]) entry.getValue();
+ // The class name is already a path
+ File classFile = new File(m_dir, classname);
+ try {
+ OutputStream os = new FileOutputStream(classFile);
+ os.write(clazz);
+ os.close();
+ } catch (IOException e) {
+ error("Cannot manipulate the file : the output file " + classname + " is not found");
+ return;
+ }
+ }
+
+ // Write manifest
+ if (m_manifest == null) {
+ m_manifest = new File(m_dir, "META-INF/MANIFEST.MF");
+ if (! m_manifest.exists()) {
+ error("Cannot find the manifest file : " + m_manifest.getAbsolutePath());
+ return;
+ }
+ } else {
+ if (! m_manifest.exists()) {
+ error("Cannot find the manifest file : " + m_manifest.getAbsolutePath());
+ return;
+ }
+ }
+ try {
+ mf.write(new FileOutputStream(m_manifest));
+ } catch (IOException e) {
+ error("Cannot write the manifest file : " + e.getMessage());
+ }
+
+ }
/**
* Manipulate classes of the input Jar.
- * @param inputJar : input bundle.
*/
- private void manipulateComponents(JarFile inputJar) {
- Enumeration entries = inputJar.entries();
+ private void manipulateComponents() {
+ //Enumeration entries = inputJar.entries();
+ Enumeration entries = getClassFiles();
+
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);
- }
+ String curName = (String) entries.nextElement();
+ try {
+ InputStream currIn = getInputStream(curName);
+ 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); // This method adds the class to the
+ // component list.
+ }
+ // 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(curName)) {
+ byte[] outClazz = manipulateComponent(in, ci);
+ m_classes.put(ci.m_classname, outClazz);
+
+ // Manipulate inner classes ?
+ if (!ci.m_inners.isEmpty()) {
+ for (int k = 0; k < ci.m_inners.size(); k++) {
+ String innerCN = (String) ci.m_inners.get(k)
+ + ".class";
+ InputStream innerStream = getInputStream(innerCN);
+ // manipulateInnerClass(inputJar, inner,
+ // (String) ci.m_inners.get(k), ci);
+ manipulateInnerClass(innerStream, innerCN, ci);
}
}
}
- } catch (IOException e) {
- error("Cannot read the class : " + curEntry.getName());
- return;
}
+ } catch (IOException e) {
+ error("Cannot read the class : " + curName);
+ return;
}
+
}
}
/**
+ * Gets an input stream on the given class.
+ * This methods manages Jar files and directories.
+ * @param classname the class name
+ * @return the input stream
+ * @throws IOException if the file cannot be read
+ */
+ private InputStream getInputStream(String classname) throws IOException {
+ if (m_inputJar != null) {
+ if (! classname.endsWith(".class")) {
+ classname += ".class";
+ }
+ JarEntry je = m_inputJar.getJarEntry(classname);
+ if (je == null) {
+ throw new IOException("The class " + classname + " connot be found in the input Jar file");
+ } else {
+ return m_inputJar.getInputStream(je);
+ }
+ } else {
+ // Directory
+ File file = new File(m_dir, classname);
+ return new FileInputStream(file);
+ }
+ }
+
+ /**
+ * Gets the list of class files.
+ * The content of the returned enumeration contains file names.
+ * It is possible to get input stream on those file by using the
+ * {@link Pojoization#getInputStream(String)} method.
+ * @return the list of class files.
+ */
+ private Enumeration getClassFiles() {
+ Vector files = new Vector();
+ if (m_inputJar != null) {
+ Enumeration enumeration = m_inputJar.entries();
+ while (enumeration.hasMoreElements()) {
+ JarEntry je = (JarEntry) enumeration.nextElement();
+ if (je.getName().endsWith(".class")) {
+ files.add(je.getName());
+ }
+ }
+ } else {
+ searchClassFiles(m_dir, files);
+ }
+ return files.elements();
+ }
+
+ /**
+ * Navigates across directories to find class files.
+ * @param dir the directory to analyze
+ * @param classes discovered classes
+ */
+ private void searchClassFiles(File dir, List classes) {
+ File[] files = dir.listFiles();
+ for (int i = 0; i < files.length; i++) {
+ if (files[i].isDirectory()) {
+ searchClassFiles(files[i], classes);
+ } else if (files[i].getName().endsWith(".class")) {
+ classes.add(computeRelativePath(files[i].getAbsolutePath()));
+ }
+ }
+ }
+
+// /**
+// * 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;
+// }
+// // Remove '.class' from class name.
+// 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);
+//
+// }
+
+ /**
+ * Computes a relative path for the given absolute path.
+ * This methods computes the relative path according to the directory
+ * containing classes for the given class path.
+ * @param absolutePath the absolute path of the class
+ * @return the relative path of the class based on the directory containing
+ * classes.
+ */
+ private String computeRelativePath(String absolutePath) {
+ String root = m_dir.getAbsolutePath();
+ return absolutePath.substring(root.length() + 1);
+ }
+
+ /**
* Manipulates an inner class.
- * @param inputJar input jar
- * @param je inner class jar entry
- * @param innerClassName inner class name
+ * @param clazz input stream on the inner file to manipulate
+ * @param cn the inner class name (ends with .class)
* @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);
+ private void manipulateInnerClass(InputStream clazz, String cn, ComponentInfo ci) throws IOException {
byte[] in = new byte[0];
int c;
- while ((c = currIn.read()) >= 0) {
+ while ((c = clazz.read()) >= 0) {
byte[] in2 = new byte[in.length + 1];
System.arraycopy(in, 0, in2, 0, in.length);
in2[in.length] = (byte) c;
in = in2;
}
-
+ // Remove '.class' from class name.
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);
+ m_classes.put(cn, out);
}
+
+ /**
+ * Gets the manifest.
+ * This method handles Jar and directories.
+ * For Jar file, the input jar manifest is returned.
+ * For directories, if specified the specifies manifest is returned.
+ * Otherwise, try directory/META-INF/MANIFEST.MF
+ * @return the Manifest.
+ * @throws IOException if the manifest cannot be found
+ */
+ private Manifest getManifest() throws IOException {
+ if (m_inputJar != null) {
+ return m_inputJar.getManifest();
+ } else {
+ if (m_manifest == null) {
+ File manFile = new File(m_dir, "META-INF/MANIFEST.MF");
+ if (manFile.exists()) {
+ return new Manifest(new FileInputStream(manFile));
+ } else {
+ throw new IOException("Cannot find the manifest file : " + manFile.getAbsolutePath());
+ }
+ } else {
+ if (m_manifest.exists()) {
+ return new Manifest(new FileInputStream(m_manifest));
+ } else {
+ throw new IOException("Cannot find the manifest file : " + m_manifest.getAbsolutePath());
+ }
+ }
+ }
+ }
/**
* Create the manifest.
- * Set the bundle activator, imports, iPOJO-components clauses
- * @param initial : initial Jar file.
+ * Set the bundle imports and iPOJO-components clauses
* @return the generated manifest.
*/
- private Manifest doManifest(JarFile initial) {
+ private Manifest doManifest() {
Manifest mf = null;
try {
- mf = initial.getManifest(); // Get the initial manifest
+ mf = getManifest();
} catch (IOException e) {
// Could not happen, the input bundle is a bundle so must have a manifest.
- error("Cannot get the manifest from the input bundle : " + e.getMessage());
+ error("Cannot get the manifest : " + e.getMessage());
return null;
}
Attributes att = mf.getMainAttributes();
@@ -458,11 +681,10 @@
/**
* 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) {
+ private byte[] manipulateComponent(byte[] in, ComponentInfo ci) {
Manipulator man = new Manipulator();
try {
byte[] out = man.manipulate(in); // iPOJO manipulation
@@ -474,27 +696,25 @@
ci.m_fields = man.getFields().keySet();
return out;
} catch (IOException e) {
- error("Cannot manipulate the class " + je.getName() + " : " + e.getMessage());
+ error("Cannot manipulate the class " + ci.m_classname + " : " + 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) {
+ private void computeDeclaredComponents() {
List componentClazzes = new ArrayList();
- for (int i = 0; i < meta.length; i++) {
- String name = meta[i].getAttribute("classname");
+ for (int i = 0; i < m_metadata.length; i++) {
+ String name = m_metadata[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]));
+ componentClazzes.add(new ComponentInfo(name, m_metadata[i]));
}
}
- return componentClazzes;
+ m_components = componentClazzes;
}
/**
@@ -581,7 +801,9 @@
*/
private void setCreatedBy(Attributes att) {
String prev = att.getValue("Created-By");
- att.putValue("Created-By", prev + " & iPOJO");
+ if (! prev.contains("iPOJO")) { // Avoid appending iPOJO several times
+ att.putValue("Created-By", prev + " & iPOJO");
+ }
}
/**
@@ -719,13 +941,40 @@
}
return sb.toString();
}
+
+ /**
+ * Parse the XML metadata from the given file.
+ * @param metadataFile the metadata file
+ */
+ private void parseXMLMetadata(File metadataFile) {
+ try {
+ InputStream stream = null;
+ URL url = metadataFile.toURL();
+ if (url == null) {
+ warn("Cannot find the metadata file : " + metadataFile.getAbsolutePath());
+ m_metadata = new Element[0];
+ } else {
+ stream = url.openStream();
+ parseXMLMetadata(stream); // m_metadata is set by the method.
+ }
+ } catch (MalformedURLException e) {
+ error("Cannot open the metadata input stream from " + metadataFile.getAbsolutePath() + ": " + e.getMessage());
+ m_metadata = null;
+ } catch (IOException e) {
+ error("Cannot open the metadata input stream: " + metadataFile.getAbsolutePath() + ": " + e.getMessage());
+ m_metadata = null;
+ }
+
+ // m_metadata can be either an empty array or an Element
+ // array with component type description. It also can be null
+ // if no metadata file is given.
+ }
/**
* Parse XML Metadata.
* @param stream metadata input stream.
- * @return the parsed element array.
*/
- private Element[] parseXMLMetadata(InputStream stream) {
+ private void parseXMLMetadata(InputStream stream) {
Element[] meta = null;
try {
XMLReader parser = (XMLReader) Class.forName("org.apache.xerces.parsers.SAXParser").newInstance();
@@ -749,32 +998,25 @@
} catch (IOException e) {
error("Cannot open the metadata input stream: " + e.getMessage());
- return null;
} catch (ParseException e) {
error("Parsing error when parsing the XML file: " + 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: " + e.getMessage());
- return null;
} catch (InstantiationException e) {
error("Cannot instantiate the SAX parser for the XML file: " + e.getMessage());
- return null;
} catch (IllegalAccessException e) {
error("Cannot instantiate the SAX parser (IllegalAccess) to the XML file: " + 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 the metadata");
}
- return meta;
+ m_metadata = meta;
}
/**