/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 2007-2008 Bull S.A.S.
 * Contact: jonas-team@ow2.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 *
 * --------------------------------------------------------------------------
 * $Id: Bnd.java 21566 2011-08-08 12:28:12Z cazauxj $
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.extension.loader;

import aQute.lib.osgi.Analyzer;
import aQute.lib.osgi.Builder;
import aQute.lib.osgi.Jar;
import aQute.lib.osgi.Verifier;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Perform the wrap operation of the bnd tool, force the
 * <code>DynamicImport-Package</code> header to '*'.
 * @author Guillaume Sauthier
 */
public class Bnd {

    /**
     * List of error messages that can be reported to the user.
     */
    private List<String> errors;

    /**
     * Wrap (using bnd) a jar file into an OSGi bundle
     * @param source original jar file
     * @param output target bundle created by this operation
     * @return the numbers of errors encountered during this bundle creation
     * @throws Exception if some file handling errors occurs.
     */
    public boolean wrap(final File source, final File output) throws Exception {
        // Init the properties
        Properties properties = new Properties();
        properties.setProperty(Analyzer.DYNAMICIMPORT_PACKAGE, "*");

        errors = new ArrayList<String>();

        Analyzer analyzer = new Analyzer();
        try {
            analyzer.setJar(source);
            Jar dot = analyzer.getJar();

            if (properties != null) {
                analyzer.setProperties(properties);
            }

            if (analyzer.getProperty(Analyzer.IMPORT_PACKAGE) == null)
                analyzer.setProperty(Analyzer.IMPORT_PACKAGE,
                        "*;resolution:=optional");

            if (analyzer.getProperty(Analyzer.BUNDLE_SYMBOLICNAME) == null) {
                Pattern p = Pattern.compile("("
                        + Verifier.SYMBOLICNAME.pattern()
                        + ")(-[0-9])?.*\\.jar");
                String base = source.getName();
                Matcher m = p.matcher(base);
                base = "Untitled";
                if (m.matches()) {
                    base = m.group(1);
                } else {
                    throw new IOException("Can not calculate symbolic name of bundle, " +
                                          "rename jar to respect pattern <name>(-<version>).jar" + source);
                }
                analyzer.setProperty(Analyzer.BUNDLE_SYMBOLICNAME, base);
            }

            if (analyzer.getProperty(Analyzer.EXPORT_PACKAGE) == null) {
                String export = analyzer.calculateExportsFromContents(dot);
                analyzer.setProperty(Analyzer.EXPORT_PACKAGE, export);
            }

            analyzer.mergeManifest(dot.getManifest());

            //
            // Cleanup the version ..
            //
            String version = analyzer.getProperty(Analyzer.BUNDLE_VERSION);
            if (version != null) {
                version = Builder.cleanupVersion(version);
                analyzer.setProperty(Analyzer.BUNDLE_VERSION, version);
            }

            analyzer.calcManifest();
            Jar jar = analyzer.getJar();
            jar.write(output);
            jar.close();

            errors.addAll(analyzer.getErrors());
            return analyzer.getErrors().size() == 0;
        } finally {
            analyzer.close();
        }

    }

    public List<String> getErrors() {
        return errors;
    }
}
