/* 
 * 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.*;
import java.util.*;
import java.util.zip.ZipFile;
import java.util.zip.ZipEntry;

import org.apache.maven.archiver.*;
import org.apache.maven.artifact.*;
import org.apache.maven.plugin.*;
import org.apache.maven.project.MavenProject;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.jar.*;
import org.codehaus.plexus.util.FileUtils;

import java.net.MalformedURLException;
import java.net.URL;

import org.apache.felix.ipojo.manipulation.Manipulator;
import org.apache.felix.ipojo.manipulation.MethodDescriptor;
import org.apache.felix.ipojo.metadata.Attribute;
import org.apache.felix.ipojo.metadata.Element;

import org.apache.felix.ipojo.parser.ManifestMetadataParser;
import org.apache.felix.ipojo.parser.ParseException;
import org.apache.felix.ipojo.parser.XMLMetadataParser;

import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

/**
 * Package an OSGi jar "bundle."
 * 
 * @author <a href="mailto:felix-dev@incubator.apache.org">Apache Felix Project</a>
 * @version $Rev$, $Date$
 * @goal ipojo-bundle
 * @phase package
 * @requiresDependencyResolution runtime
 * @description build an OSGi bundle jar
 */
public class OsgiJarMojo extends AbstractMojo {
    public static final String OSGI_REFERENCES = "osgi.references";
    public static final String AUTO_DETECT = "auto-detect";

	private static final String[]		EMPTY_STRING_ARRAY		= {};

	int									bundleManifestVersion	= 1;

	/**
     * Jars to Inline
     *
     * @parameter
     */
    private List inlinedArtifacts = new ArrayList();

    /**
     * Packages to ignore when generating import-package header.
     *
     * @parameter
     */
    private String ignorePackage;

	/**
	 * The Maven project.
	 * 
	 * @parameter expression="${project}"
	 * @required
	 * @readonly
	 */
	private MavenProject				project;

	/**
	 * The directory for the generated JAR.
	 * 
	 * @parameter expression="${project.build.directory}"
	 * @required
	 */
	private String						buildDirectory;

	/**
	 * The directory containing generated classes.
	 * 
	 * @parameter expression="${project.build.outputDirectory}"
	 * @required
	 * @readonly
	 */
	private File						outputDirectory;

	/**
	 * The name of the generated JAR file.
	 * 
	 * @parameter alias="jarName" expression="${project.build.finalName}"
	 * @required
	 */
	private String						jarName;

	/**
	 * The Jar archiver.
	 * 
	 * @parameter expression="${component.org.codehaus.plexus.archiver.Archiver#jar}"
	 * @required
	 */
	private JarArchiver					jarArchiver;

	/**
	 * The maven archive configuration to use.
	 */
	private MavenArchiveConfiguration	archiveConfig			= new MavenArchiveConfiguration();

	/**
	 * The comma separated list of tokens to include in the JAR. Default is
	 * '**'.
	 * 
	 * @parameter alias="includes"
	 */
	private String						jarSourceIncludes		= "**";

	/**
	 * The comma separated list of tokens to exclude from the JAR.
	 * 
	 * @parameter alias="excludes"
	 */
	private String						jarSourceExcludes;

	/**
	 * @parameter
	 */
	private String						manifestFile;

	/**
	 * @parameter expression="${org.apache.felix.ipojo.tools.maven.plugin.OsgiManifest}"
	 */
	private OsgiManifest				osgiManifest;
	
	private String[][] namespaces; 

	/**
	 * Execute this Mojo
	 * 
	 * @throws MojoExecutionException
	 */
	public void execute() throws MojoExecutionException {
		File jarFile = new File(buildDirectory, jarName + ".jar");

		try {
			performPackaging(jarFile);
		}
		catch (Exception e) {
			throw new MojoExecutionException("Error assembling JAR bundle", e);
		}
	}

	/**
	 * Generates the JAR bundle file.
	 * 
	 * @param jarFile the target JAR file
	 * @throws IOException
	 * @throws ArchiverException
	 * @throws ManifestException
	 * @throws DependencyResolutionRequiredException
	 */
	private void performPackaging(File jarFile) throws IOException,
			ArchiverException, ManifestException,
			DependencyResolutionRequiredException, MojoExecutionException {

		outputDirectory.mkdirs();
		
		verifyDeclaredBundleManifestVersion();

		getLog().info("Generating JAR bundle " + jarFile.getAbsolutePath());

		MavenArchiver archiver = new MavenArchiver();

		archiver.setArchiver(jarArchiver);
		archiver.setOutputFile(jarFile);

		addManifestFile();
		addManifestEntries();
		
		// Inline the contents of the indicated jar artifacts
        inlineArtifacts();

		// Add the JARs that were specified in the POM
		// as "not" provided
		addEmbeddedJars();
		addBundleVersion();
		
		// Insert iPOJO Manipulation
		iPojoManipulation();

		jarArchiver.addDirectory(outputDirectory, getIncludes(), getExcludes());

		// Parse the output directory as if it was a JAR file.
		// This creates special entries for classes, packageinfo
		// and embedded JAR files (which are parsed as well).
		Jar mainJar = new Jar(null, jarName, outputDirectory);

		// Calculate the Bundle Classpath from the embedded
		// JAR files. We hardcode the bcp as ., <embedded jars>
		// TODO we add all the found JARs to the Bcp, maybe we
		// should look if they are needed by traversing the imports.
		List bundleClassPath = getBundleClassPath(mainJar);
		bundleClassPath.add(0, ".");
		createBundleClasspathHeader(bundleClassPath);

		// Calculate the exports (contained) and imports (referred)
		// The bundleClassPath contains the JARs in the right order
		Set contained = new HashSet(); // package name
		Set referred = new HashSet(); // package name
		Map uses = new HashMap(); // package name => Set of package name

		// Iterate over the bundle class path and calculate the contained
		// and referred packages as well as the uses.
		for (Iterator i = bundleClassPath.iterator(); i.hasNext();) {
			String path = (String) i.next();
			Jar jar = path.equals(".") ? mainJar : (Jar) mainJar.resources
					.get(path);
			analyzeJar(jar, contained, referred, uses);
		}

        referred.removeAll(contained);

        // Check if the osgi.references property is set and display result
        // if necessary.
		checkReferencesProperty(uses);

        // Dump referenced package information if debug logging is enabled.
		if (getLog().isDebugEnabled()) {
		    printReferencedPackages(uses);
		}

		Map exports = parseHeader(osgiManifest.getExportPackage());
		Map imports = parseHeader(osgiManifest.getImportPackage());
		Map dynamicImports = parseHeader(osgiManifest.getDynamicImportPackage());

		if (dynamicImports != null) {
			// Remove any dynamic imports from the referred set.
			referred = new HashSet(referred);
			referred.removeAll(dynamicImports.keySet());
		}

		if (exports != null) {
			verifyDeclaredExports(exports, contained);
			createExportHeader(exports, uses);
		}

        // Remove any ignored packages from the referred set.
        Set ignorePackage = parseIgnorePackage();
        referred.removeAll(ignorePackage);

		// If the POM file contains an import declaration,
		// we verify its validity. Otherwise, we generate the
		// import package header from the referred. Exports
		// are added to automatically imports for R4 bundles.
		if (imports == null) {
			createImportHeader(referred, exports == null ? new HashSet()
					: exports.keySet());
		}
		else {
			verifyDeclaredImports(referred, imports);
		}

		//verifyBundleActivator(mainJar); // Replace it by setBundleActivator
		
		archiver.createArchive(project, archiveConfig);
		project.getArtifact().setFile(jarFile);
	}

//	private void verifyBundleActivator(Jar mainJar) {
//		String ba = osgiManifest.getBundleActivator();
//		if (ba == null || ba.trim().length() == 0) {
//			switch ( mainJar.activators.size() ) {
//				case 0: break;
//				case 1: archiveConfig.addManifestEntry("Bundle-Activator", mainJar.activators.get(0));
//				break;
//				default:
//					getLog().info("[OSGi] No Bundle-Activator specified and multiple found" );
//				break;
//			}
//		}
//		else {
//			if( ! mainJar.activators.contains(ba))
//				getLog().warn("[OSGi] UNABLE TO VERIFY BUNDLE ACTIVATOR: " + ba);
//		}
//	}

	private void createBundleClasspathHeader(List bundleClassPath) {
		StringBuffer sb = new StringBuffer();
		for (Iterator i = bundleClassPath.iterator(); i.hasNext(); ) {
			sb.append(i.next());
            if (i.hasNext()) {
                sb.append(",");
            }
		}
		if (sb.length() > 0)
			archiveConfig.addManifestEntry("Bundle-Classpath", sb.toString());
	}

	/**
	 * Iterate over the declared exports from the POM, verify that they are
	 * present, add the uses clause if necessary and finally add the manifest
	 * entry.
	 * 
	 * @param contained Set of contained packages
	 * @param exports Map with the export clauses from the POM
	 * @throws MojoExecutionException
	 */
	void verifyDeclaredExports(Map exports, Set contained)
			throws MojoExecutionException {
		Set declaredExports = exports.keySet();
		for (Iterator i = declaredExports.iterator(); i.hasNext();) {
			String pack = (String) i.next();
			if (!contained.contains(pack)) {
				getLog()
						.error("[OSGi] EXPORTED PACKAGE NOT IN BUNDLE: " + pack);
				throw new MojoExecutionException(
						"Exported Package not found in bundle or JARs on bundle class path "
								+ pack);
			}

		}
	}

	/**
	 * Print out the export headers after adding the uses clause.
	 * 
	 * @param exports
	 * @param uses
	 * @throws MojoExecutionException
	 */
	void createExportHeader(Map exports, Map uses)
			throws MojoExecutionException {
		if (exports.size() > 0) {
			Set declaredExports = exports.keySet();
			for (Iterator i = declaredExports.iterator(); i.hasNext();) {
				String pack = (String) i.next();
				Map clause = (Map) exports.get(pack);

				if (bundleManifestVersion >= 2) {
					Set t = (Set) uses.get(pack);
					if (t != null && !t.isEmpty()) {
						StringBuffer sb = new StringBuffer();
						String del = "\"";
						for (Iterator u = t.iterator(); u.hasNext();) {
							String usedPackage = (String) u.next();
							if (!usedPackage.equals(pack)) {
								sb.append(del);
								sb.append(usedPackage);
								del = ",";
							}
						}
						sb.append("\"");
						clause.put("uses:", sb.toString());
					}
				}
			}
			archiveConfig.addManifestEntry(
					"Export-Package",
					printClauses(exports));
		}
	}

	/**
	 * Verify that the declared imports match the referred packages.
	 * 
	 * @param referred referred package
	 * @param imports imported packages from POM
	 * @throws MojoExecutionException
	 */
	void verifyDeclaredImports(Set referred, Map imports)
			throws MojoExecutionException {
		Set declaredImports = imports.keySet();
		Set test = new HashSet(referred);
		test.removeAll(declaredImports);
		for (Iterator m = test.iterator(); m.hasNext();) {
			Object o = m.next();
			// For backwards compatibility with existing builds, only
            // issue a warning for missing imports. Other the other hand,
            // if packages are being ignored, then this is a new build
            // so be more strict and throw an error.
            if (osgiManifest.getIgnorePackage() == null) {
                getLog().warn("[OSGi] MISSING IMPORT: " + o);
            }
            else {
                getLog().error("[OSGi] MISSING IMPORT: " + o);
                throw new MojoExecutionException("Missing Import " + o);
            }
		}

		test = new HashSet(declaredImports);
		test.removeAll(referred);
		for (Iterator m = test.iterator(); m.hasNext();) {
			getLog().warn("[OSGi] SUPERFLUOUS IMPORT: " + m.next());
			getLog()
					.warn(
							"[OSGi] Removing the POM Import-Package element will automatically generate the import clauses");
		}
	}

	/**
	 * 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
	 * @return
	 * @throws MojoExecutionException
	 */
	static Map parseHeader(String value) throws MojoExecutionException {
		if (value == null || value.trim().length() == 0)
			return null;

		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 MojoExecutionException(
								"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;
	}

	/**
	 * Create the import header, taking into account R4 automatic import clauses
	 * for the exports.
	 * 
	 * @param referred
	 * @param contained
	 */
	void createImportHeader(Set referred, Set contained) {
		// Add handler import
		for(int j = 0; j < namespaces.length; j++) {
			for(int k = 0; k < namespaces[j].length; k++) {
				if(!namespaces[j][k].equals("")) {
					int lastIndex = namespaces[j][k].lastIndexOf('.');
					String ns = namespaces[j][k].substring(0, lastIndex);
					referred.add(ns);
				}
			}
		}
		
		// Add org.apache.felix.ipojo, org.apache.felix.ipojo.architecture is not already in the set
		referred.add(IPojoPluginConfiguration.ipojo_package);
		referred.add(IPojoPluginConfiguration.ipojo_arch_package);
		referred.add(IPojoPluginConfiguration.config_admin_package);
		
		if (referred.isEmpty())
			return;

		referred = new TreeSet(referred);

		if (bundleManifestVersion > 1) {
			referred.addAll(contained);
		}
		
		StringBuffer sb = new StringBuffer();
		String del = "";

		for (Iterator i = referred.iterator(); i.hasNext();) {
			sb.append(del);
			sb.append(i.next());
			del = ", ";
		}	
		archiveConfig.addManifestEntry("Import-Package", sb.toString());
		getLog().info("Set Imports to : " + sb.toString());
	}

	/**
	 * Calculate the bundle class path based on the list of JARs in our bundle.
	 * This list includes outselves. We also calculate the Bundle-Classpath
	 * header (a bit clumsy) This is a bit cheap, so maybe this needs to be
	 * changed 

	 * 
	 * @param mainJar
	 * @return
	 */
	List getBundleClassPath(Jar mainJar) {
		List result = new ArrayList();
		for (Iterator i = mainJar.resources.keySet().iterator(); i.hasNext();) {
			String path = (String) i.next();
			Object resource = mainJar.resources.get(path);
			if (resource instanceof Jar) {
				result.add(path);
			}
		}
		return result;
	}

	/**
	 * We traverse through al the classes that we can find and calculate the
	 * contained and referred set and uses.
	 * 
	 * @param jar
	 * @param contained
	 * @param referred
	 * @param uses
	 */
	void analyzeJar(Jar jar, Set contained, Set referred, Map uses) {
		String prefix = "";
		Set set = jar.getEntryPaths(prefix);
		for (Iterator r = set.iterator(); r.hasNext();) {
			String path = (String) r.next();
			Object resource = jar.getEntry(path);
			if (resource instanceof Clazz) {
				Clazz clazz = (Clazz) resource;
				String pathOfClass = path.substring(prefix.length());
				String pack = Clazz.getPackage(pathOfClass);
				contained.add(pack);
				referred.addAll(clazz.getReferred());

				// Add all the used packages
				// to this package
				Set t = (Set) uses.get(pack);
				if (t == null)
					uses.put(pack, t = new HashSet());
				t.addAll(clazz.getReferred());
				t.remove(pack);
			}
		}
	}

	/**
	 * Print a standard Map based OSGi header.
	 * 
	 * @param exports map { name => Map { attribute|directive => value } }
	 * @return the clauses
	 */
	String printClauses(Map exports) {
		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();
				String value = (String) map.get(key);
				sb.append(";");
				sb.append(key);
				sb.append("=");
				sb.append(value);
			}
			del = ", ";
		}
		return sb.toString();
	}

	/**
	 * Check if the BundleManifest version is set correctly, base the manifest
	 * version on it.
	 * 
	 * @throws MojoExecutionException
	 */
	void verifyDeclaredBundleManifestVersion() throws MojoExecutionException {
		String mfv = osgiManifest.getBundleManifestVersion();
		if (mfv != null && mfv.trim().length() != 0) {
			try {
				bundleManifestVersion = Integer.parseInt(mfv);
				if (bundleManifestVersion != 2)
					throw new MojoExecutionException(
							"Bundle-ManifestVersion must be 2, it is " + mfv);
			}
			catch (Exception e) {
				throw new MojoExecutionException(
						"Bundle-ManifestVersion must be an integer: " + mfv);
			}
		}
	}

	/**
	 * TODO: Decide if we accept merging of entire manifest.mf files Here's a
	 * big question to make a final decision at some point: Do accept merging of
	 * manifest entries located in some file somewhere in the project directory?
	 * If so, do we allow both file and configuration based entries to be
	 * specified simultaneously and how do we merge these?
	 */
	private void addManifestFile() {
		if (manifestFile != null) {
			File file = new File(project.getBasedir().getAbsolutePath(),
					manifestFile);
			getLog().info(
					"Manifest file: " + file.getAbsolutePath()
							+ " will be used");
			archiveConfig.setManifestFile(file);
		}
		else {
			getLog().info("No manifest file specified. Default will be used.");
		}
	}

	/**
	 * Look for any OSGi specified manifest entries in the maven-osgi-plugin
	 * configuration section of the POM. If we find some, then add them to the
	 * target artifact's manifest.
	 */
	private void addManifestEntries() {
		 if (osgiManifest.getBundleVersion() == null) {
            addBundleVersion();
        } 
        if (osgiManifest != null && osgiManifest.getEntries().size() > 0) {
			Map entries = osgiManifest.getEntries();

			getLog().debug(
					"Bundle manifest will be modified with the following entries: "
							+ entries.toString());
			archiveConfig.addManifestEntries(entries);
		}
		else {
			getLog()
					.info(
							"No OSGi bundle manifest entries have been specified in the POM.");
		}
	}

	/**
	 * We are going to iterate through the POM's specified JAR dependencies. If
	 * a dependency has a scope of either RUNTIME or COMPILE, then we'll JAR
	 * them up inside the OSGi bundle artifact. We will then add the
	 * Bundle-Classpath manifest entry.
     *
     * Artifacts which are inlined will not be included.
	 */
	private void addEmbeddedJars() throws MojoExecutionException {
		Set artifacts = project.getArtifacts();

		for (Iterator it = artifacts.iterator(); it.hasNext();) {
			Artifact artifact = (Artifact) it.next();
			if (!Artifact.SCOPE_PROVIDED.equals(artifact.getScope())
					&& !Artifact.SCOPE_TEST.equals(artifact.getScope())) {
				String type = artifact.getType();

				if ("jar".equals(type)) {
                    // Do not include artifacts which are inlined
                    if (!(inlinedArtifacts.contains(artifact.getArtifactId()))) {
                        File depFile = artifact.getFile();

                        try {
                            FileUtils.copyFileToDirectory(depFile, outputDirectory);

                        }
                        catch (Exception e) {
                            String errmsg = "Error copying "
                                            + depFile.getAbsolutePath() + " to "
                                            + outputDirectory.getAbsolutePath();
                            throw new MojoExecutionException(errmsg, e);
                        }
                    }
                }
			}
		}
	}

	/**
	 * Auto-set the bundle version.
	 */
	private void addBundleVersion() {
		// Maven uses a '-' to separate the version qualifier,
	    // while OSGi uses a '.', so we need to convert to a '.'
        String version = project.getVersion().replace('-', '.');
        osgiManifest.setBundleVersion(version);
	}

	/**
	 * Returns a string array of the includes to be used when assembling/copying
	 * the war.
	 * 
	 * @return an array of tokens to include
	 */
	private String[] getIncludes() {
		return new String[] {jarSourceIncludes};
	}

	/**
	 * Returns a string array of the excludes to be used when assembling/copying
	 * the jar.
	 * 
	 * @return an array of tokens to exclude
	 */
	private String[] getExcludes() {
		List excludeList = new ArrayList(FileUtils.getDefaultExcludesAsList());

		if (jarSourceExcludes != null && !"".equals(jarSourceExcludes)) {
			excludeList.add(jarSourceExcludes);
		}

		return (String[]) excludeList.toArray(EMPTY_STRING_ARRAY);
	}

    private Set parseIgnorePackage() {
        HashSet result = new HashSet();
        if ((ignorePackage == null) && (osgiManifest.getIgnorePackage() != null)) {
            ignorePackage = osgiManifest.getIgnorePackage();
            getLog().warn("DEPRECATED METADATA! "
                + "The <ignorePackage> tag should be set inside the <configuration> "
                + "tag, not in the <osgiManifest> tag.");            
        }
        if (ignorePackage != null) {
            StringTokenizer st = new StringTokenizer(ignorePackage, ",", false);
            while (st.hasMoreTokens()) {
                result.add(st.nextToken().trim());
            }
        }
        return result;
    }

    private void checkReferencesProperty(Map uses) {
        String interestedIn = System.getProperty(OSGI_REFERENCES);
        if (interestedIn == null) {
            return;
        }
        StringBuffer buf = new StringBuffer();
        Iterator it1 = uses.entrySet().iterator();
        while (it1.hasNext()) {
            Map.Entry entry = (Map.Entry) it1.next();
            String pack = (String) entry.getKey();
            Set references = (Set) entry.getValue();
            Iterator it2 = references.iterator();
            while (it2.hasNext()) {
                String packReferred = (String) it2.next();
                if (interestedIn.equals(packReferred)) {
                    buf.append("          |-- ");
                    buf.append(pack);
                    buf.append('\n');
                    break;
                }
            }
        }
        if (buf.length() == 0) {
            getLog().info("Noone uses " + interestedIn);
        }
        else {
            int changePos = buf.lastIndexOf("|");
            buf.setCharAt(changePos, '+');
            getLog().info(interestedIn + " used by;\n" + buf);
        }
    }

    private void printReferencedPackages(Map uses) {
        StringBuffer buf = new StringBuffer();
        Iterator it1 = uses.entrySet().iterator();
        while (it1.hasNext()) {
            Map.Entry entry = (Map.Entry) it1.next();
            String pack = (String) entry.getKey();
            buf.append(pack);
            buf.append('\n');
            Set references = (Set) entry.getValue();
            Iterator it2 = references.iterator();
            while (it2.hasNext()) {
                String packReferred = (String) it2.next();
                buf.append("          |-- ");
                buf.append(packReferred);
                buf.append('\n');
            }
            int changePos = buf.lastIndexOf("|");
            if (changePos >= 0) {
                buf.setCharAt(changePos, '+');
            }
            buf.append('\n');
        }
        getLog().debug("Referenced package list: \n" + buf.toString());
    }
    
        private void inlineArtifacts() throws MojoExecutionException {
		Set artifacts = project.getArtifacts();

		for (Iterator it = artifacts.iterator(); it.hasNext();) {
			Artifact artifact = (Artifact) it.next();
			if (!Artifact.SCOPE_PROVIDED.equals(artifact.getScope())
					&& !Artifact.SCOPE_TEST.equals(artifact.getScope())) {
				String type = artifact.getType();

				if ("jar".equals(type)) {
                    if ((inlinedArtifacts.contains(artifact.getArtifactId()))) {
                        File depFile = artifact.getFile();

                        try {
                            ZipFile inlinedJar = new ZipFile(depFile);
                            Enumeration entries = inlinedJar.entries();
                            byte[] buffer = new byte[4096];
                            while (entries.hasMoreElements()) {
                                ZipEntry entry = (ZipEntry) entries.nextElement();
                                if (entry.isDirectory()) {
                                    new File(outputDirectory, entry.getName()).mkdirs();
                                } else {
                                    // Have to do this because some JARs ship without directories, i.e., just files.
                                    new File(outputDirectory, entry.getName()).getParentFile().mkdirs();
                                    FileOutputStream out = new FileOutputStream(new File(outputDirectory, entry.getName()));
                                    InputStream in = inlinedJar.getInputStream(entry);
                                    for (int read = in.read(buffer); read != -1; read = in.read(buffer)) {
                                        out.write(buffer, 0, read);
                                    }
                                    in.close();
                                    out.close();
                                }
                            }
                        } catch (Exception e) {
                            String errmsg = "Error inlining "
                                            + depFile.getAbsolutePath() + " to "
                                            + outputDirectory.getAbsolutePath();
                            throw new MojoExecutionException(errmsg, e);
                        }
                    }
                }
			}
		}
    }
	
	// ===== iPOJO's methods =====
	
	private Element[] parseXMLMetadata(String path) throws MojoExecutionException {
		File metadata = new File(outputDirectory+path);
		URL url;
		Element[] meta = null;
		try {
			url = metadata.toURI().toURL();
			if (url == null) { 
				getLog().error("No metadata at : " + outputDirectory+path);
				throw new MojoExecutionException("[iPOJO] No metadata at : " + outputDirectory+path); 
			}
			
			InputStream stream = url.openStream();			
			XMLReader parser = XMLReaderFactory.createXMLReader("org.apache.xerces.parsers.SAXParser");
			XMLMetadataParser handler = new XMLMetadataParser();
			parser.setContentHandler(handler);
			InputSource is = new InputSource(stream);
			parser.parse(is);
		    
		    meta = handler.getMetadata();
		    
		} catch (MalformedURLException e) {
			getLog().error("Malformed URL for " + outputDirectory+path+ "("+e.getMessage()+")");
			throw new MojoExecutionException("[iPOJO] Malformed URL for " + outputDirectory+path);
		} catch (IOException e) { 
        	getLog().error("Cannot open the file : " + outputDirectory+path + "("+e.getMessage()+")");
			throw new MojoExecutionException("[iPOJO] Cannot open the file : " + outputDirectory+path);
		} catch (Exception e) {
			getLog().error("Parsing Error when parsing the XML file " + outputDirectory+path+ "("+e.getMessage()+")");
			throw new MojoExecutionException("[iPOJO] Parsing Error when parsing the XML file " + outputDirectory+path);
		}
		
		if(meta == null || meta.length == 0) {
			getLog().error("No component in " + outputDirectory+path); //TODO : change the message
			throw new MojoExecutionException("[iPOJO] No component in " + outputDirectory+path);
		}
		
		return meta;
	}
	
	private Element[] parseManifestMetadata(String metadata) throws MojoExecutionException {
		Element[] components = null;
		ManifestMetadataParser parser = new ManifestMetadataParser();
    	try {
			parser.parse(metadata);
			components = parser.getComponentsMetadata();
		} catch (ParseException e) {
			getLog().error("Parsing Error when parsing the Manifest metadata " +  metadata + "("+e.getMessage()+")");
			throw new MojoExecutionException("[iPOJO] Parsing Error when parsing the Manifest metadata " +  metadata);
			
		}
    	
		if(components == null || components.length == 0) {
			getLog().error("No component in " + metadata);
			throw new MojoExecutionException("[iPOJO] No component in " + metadata);
		}
        
        return components;
	}
	
	private void iPojoManipulation() throws MojoExecutionException {
		//Try to read the content of a file of the ouptut directory
		getLog().info("iPOJO Manipulation ...");
		
		Element[] original_meta = null;
		
		// Get the metadata.xml location 
		String path = (String) osgiManifest.getEntries().get("iPOJO-Metadata");
		
		if(path != null) {
			if(!path.startsWith("/")) { path = "/" + path; }
			original_meta = parseXMLMetadata(path);
		} else {
			String meta_ = (String) osgiManifest.getEntries().get("iPOJO-Components");
			if(meta_ != null) {
				original_meta = parseManifestMetadata(meta_);
			} else {
				getLog().error("Neither iPOJO-Metadata nor iPOJO-Components are in the manifest, please in the osgi-bundle packaging instead og ipojo-bundle");
				throw new MojoExecutionException("[iPOJO] Neither iPOJO-Metadata nor iPOJO-Components are in the manifest");
			}				
		}
		
		Manipulator manipulator = new Manipulator();
		String[] metadata = new String[original_meta.length];
		String meta = "";
		
		if(namespaces == null) { namespaces = new String[original_meta.length][]; } //NO
        for(int i = 0; i < original_meta.length; i++) {
        	if(original_meta[i].getName().equalsIgnoreCase("component")) { 
        		namespaces[i] = original_meta[i].getNamespaces(); 
        		try {
        			manipulator.preProcess(original_meta[i].getAttribute("className"), outputDirectory);
        		} catch (Exception e) {
        			getLog().error("Manipulation error in the class : " + original_meta[i].getAttribute("className") + "("+e.getMessage()+")");
        			throw new MojoExecutionException("[iPOJO] Manipulation error in the class : " + original_meta[i].getAttribute("className"));
        		}
        	
        		// Insert information to metadata
        		Element elem = new Element("Manipulation", "");
        		for(int j = 0; j < manipulator.getInterfaces().length; j++) {
        			// Create an interface element for each implemented interface
        			Element itf = new Element("Interface", "");
        			Attribute att =new Attribute("name", manipulator.getInterfaces()[j]);
        			itf.addAttribute(att);
        			elem.addElement(itf);
        		}

        		for(Iterator it = manipulator.getFields().keySet().iterator(); it.hasNext(); ) {
        			Element field = new Element("Field", "");
        			String name = (String) it.next();
        			String type = (String) manipulator.getFields().get(name);
        			Attribute attName =new Attribute("name", name);
        			Attribute attType =new Attribute("type", type);
        			field.addAttribute(attName);
        			field.addAttribute(attType);
        			elem.addElement(field);
        		}
        		
        		for(int j= 0; j < manipulator.getMethods().size(); j++) {
        			MethodDescriptor method = (MethodDescriptor) manipulator.getMethods().get(j);
        			elem.addElement(method.getElement());
        		}

        		original_meta[i].addElement(elem);
        	} else { namespaces[i] = new String[0]; }

        	
        	// Transform the metadate to manifest metadata
        	metadata[i] = buildManifestMetadata(original_meta[i], "");
        	meta = meta + metadata[i];
        }
        
	    archiveConfig.addManifestEntry("iPOJO-Components", meta);
	        
	    setBundleActivator();
			
	    getLog().info("iPOJO Packaging ... SUCCESS");
	}

	private String buildManifestMetadata(Element element, String actual) {
		String result="";
		if(element.getNameSpace().equals("")) { result = actual + element.getName() + " { "; }
		else { result = actual + element.getNameSpace()+":"+element.getName() + " { ";	}
		
		for(int i = 0; i < element.getAttributes().length; i++) {
			if(element.getAttributes()[i].getNameSpace().equals("")) { 
				result = result + "$" + element.getAttributes()[i].getName() + "=\""+element.getAttributes()[i].getValue() + "\" ";
			}
			else {
				result = result + "$" + element.getAttributes()[i].getNameSpace()+ ":" + element.getAttributes()[i].getName() + "=\""+element.getAttributes()[i].getValue() + "\" ";
			}
		}
		for(int i = 0; i < element.getElements().length; i++) {
			result = buildManifestMetadata(element.getElements()[i], result);
		}
		return result +"}";
	}

	private void setBundleActivator() throws MojoExecutionException {
		archiveConfig.addManifestEntry("Bundle-Activator", "org.apache.felix.ipojo.Activator");
	}
}
