/*
 * 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.bundleplugin;


import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.TreeMap;
import java.util.jar.Attributes;
import java.util.jar.Manifest;

import org.apache.maven.archiver.ManifestSection;
import org.apache.maven.archiver.MavenArchiveConfiguration;
import org.apache.maven.archiver.MavenArchiver;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactCollector;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.Exclusion;
import org.apache.maven.model.License;
import org.apache.maven.model.Model;
import org.apache.maven.model.Resource;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.DefaultProjectBuildingRequest;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.apache.maven.project.MavenProjectHelper;
import org.apache.maven.project.ProjectBuildingException;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
import org.apache.maven.shared.dependency.graph.DependencyNode;
import org.apache.maven.shared.osgi.DefaultMaven2OsgiConverter;
import org.apache.maven.shared.osgi.Maven2OsgiConverter;
import org.codehaus.plexus.archiver.UnArchiver;
import org.codehaus.plexus.archiver.manager.ArchiverManager;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.PropertyUtils;
import org.codehaus.plexus.util.StringUtils;
import org.codehaus.plexus.util.WriterFactory;
import org.sonatype.plexus.build.incremental.BuildContext;

import aQute.bnd.header.Attrs;
import aQute.bnd.header.OSGiHeader;
import aQute.bnd.header.Parameters;
import aQute.bnd.osgi.Analyzer;
import aQute.bnd.osgi.Builder;
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.Descriptors.PackageRef;
import aQute.bnd.osgi.EmbeddedResource;
import aQute.bnd.osgi.FileResource;
import aQute.bnd.osgi.Instruction;
import aQute.bnd.osgi.Instructions;
import aQute.bnd.osgi.Jar;
import aQute.bnd.osgi.Packages;
import aQute.bnd.osgi.Processor;
import aQute.lib.collections.ExtList;
import aQute.lib.spring.SpringXMLType;
import aQute.libg.generics.Create;


/**
 * Create an OSGi bundle from Maven project
 *
 */
@Mojo( name = "bundle", requiresDependencyResolution = ResolutionScope.TEST,
       threadSafe = true,
       defaultPhase = LifecyclePhase.PACKAGE )
public class BundlePlugin extends AbstractMojo
{
    /**
     * Directory where the manifest will be written
     */
    @Parameter( property = "manifestLocation", defaultValue = "${project.build.outputDirectory}/META-INF" )
    protected File manifestLocation;

    /**
     * Output a nicely formatted manifest that still respects the 72 character line limit.
     */
    @Parameter( property = "niceManifest", defaultValue = "false" )
    protected boolean niceManifest;
    /**
     * File where the BND instructions will be dumped
     */
    @Parameter( property = "dumpInstructions" )
    protected File dumpInstructions;

    /**
     * File where the BND class-path will be dumped
     */
    @Parameter( property = "dumpClasspath" )
    protected File dumpClasspath;

    /**
     * When true, unpack the bundle contents to the outputDirectory
     */
    @Parameter( property = "unpackBundle" )
    protected boolean unpackBundle;

    /**
     * Comma separated list of artifactIds to exclude from the dependency classpath passed to BND (use "true" to exclude everything)
     */
    @Parameter( property = "excludeDependencies" )
    protected String excludeDependencies;

    /**
     * Final name of the bundle (without classifier or extension)
     */
    @Parameter( defaultValue = "${project.build.finalName}")
    private String finalName;

    /**
     * Classifier type of the bundle to be installed.  For example, "jdk14".
     * Defaults to none which means this is the project's main bundle.
     */
    @Parameter
    protected String classifier;

    /**
     * Packaging type of the bundle to be installed.  For example, "jar".
     * Defaults to none which means use the same packaging as the project.
     */
    @Parameter
    protected String packaging;

    /**
     * If true, remove any inlined or embedded dependencies from the resulting pom.
     */
    @Parameter
    protected boolean createDependencyReducedPom;

    /**
     * Where to put the dependency reduced pom. Note: setting a value for this parameter with a directory other than
     * ${basedir} will change the value of ${basedir} for all executions that come after the shade execution. This is
     * often not what you want. This is considered an open issue with this plugin.
     */
    @Parameter( defaultValue = "${basedir}/dependency-reduced-pom.xml" )
    protected File dependencyReducedPomLocation;

    /**
     * Directory where the SCR files will be written
     */
    @Parameter(defaultValue="${project.build.outputDirectory}")
    protected File scrLocation;

    /**
     * When true, dump the generated SCR files
     */
    @Parameter
    protected boolean exportScr;
    
    @Component
    private MavenProjectHelper m_projectHelper;

    @Component
    private ArchiverManager m_archiverManager;

    @Component
    private ArtifactHandlerManager m_artifactHandlerManager;

    /* The current Maven session.  */
    @Parameter( defaultValue = "${session}", readonly = true )
    protected MavenSession session;


    /**
     * ProjectBuilder, needed to create projects from the artifacts.
     */
    @Component
    protected MavenProjectBuilder mavenProjectBuilder;

    @Component
    protected DependencyGraphBuilder dependencyGraphBuilder;

    @Component
    private ArtifactMetadataSource artifactMetadataSource;

    @Component
    private ArtifactCollector artifactCollector;

    @Component
    protected ArtifactFactory artifactFactory;

    /**
     * Artifact resolver, needed to download source jars for inclusion in classpath.
     */
    @Component
    protected ArtifactResolver artifactResolver;


    /**
     * Local maven repository.
     */
    @Parameter( readonly = true, required = true, defaultValue = "${localRepository}" )
    protected ArtifactRepository localRepository;

    /**
     * Remote repositories which will be searched for source attachments.
     */
    @Parameter( readonly = true, required = true, defaultValue = "${project.remoteArtifactRepositories}" )
    protected List<ArtifactRepository> remoteArtifactRepositories;



    /**
     * Project types which this plugin supports.
     */
    @Parameter
    protected List<String> supportedProjectTypes = Arrays.asList("jar", "bundle");

    /**
     * Project types which are not supported, but silently ignored.
     */
    @Parameter
    protected List<String> noWarningProjectTypes = Collections.emptyList();

    /**
     * The directory for the generated bundles.
     */
    @Parameter( defaultValue = "${project.build.outputDirectory}" )
    private File outputDirectory;

    /**
     * The directory for the generated JAR.
     */
    @Parameter( defaultValue = "${project.build.directory}" )
    private String buildDirectory;

    /**
     * The Maven project.
     */
    @Parameter( defaultValue = "${project}", readonly = true, required = true )
    protected MavenProject project;

    /**
     * The BND instructions for the bundle.
     * Maven will expand property macros in these values. If you want to use a BND macro, you must double the dollar sign
     * for the plugin to pass it to BND correctly. For example: <br>
     * {@code <_consumer-policy>$${range;[===,+)}<code>}<code>{@code </_consumer-policy> }
     */
    @Parameter
    private Map<String, String> instructions = new LinkedHashMap<>();

    /**
     * Use locally patched version for now.
     */
    private final Maven2OsgiConverter m_maven2OsgiConverter = new DefaultMaven2OsgiConverter();

    /**
     * The archive configuration to use.
     */
    @Parameter
    private MavenArchiveConfiguration archive; // accessed indirectly in JarPluginConfiguration

    @Parameter( defaultValue = "${session}", readonly = true, required = true )
    private MavenSession m_mavenSession;

    @Component
    protected BuildContext buildContext;
    
    private static final String MAVEN_SYMBOLICNAME = "maven-symbolicname";
    private static final String MAVEN_RESOURCES = "{maven-resources}";
    private static final String MAVEN_TEST_RESOURCES = "{maven-test-resources}";
    private static final String LOCAL_PACKAGES = "{local-packages}";
    private static final String MAVEN_SOURCES = "{maven-sources}";
    private static final String MAVEN_TEST_SOURCES = "{maven-test-sources}";
    private static final String BUNDLE_PLUGIN_EXTENSION = "BNDExtension-";
    private static final String BUNDLE_PLUGIN_PREPEND_EXTENSION = "BNDPrependExtension-";

    private static final String[] EMPTY_STRING_ARRAY =
        {};
    private static final String[] DEFAULT_INCLUDES =
        { "**/**" };

    private static final String NL = System.getProperty( "line.separator" );


    protected Maven2OsgiConverter getMaven2OsgiConverter()
    {
        return m_maven2OsgiConverter;
    }


    protected MavenProject getProject()
    {
        return project;
    }

    protected Map<String, String> getInstructions() {
        return instructions;
    }

    /**
     * @see org.apache.maven.plugin.AbstractMojo#execute()
     */
    public void execute() throws MojoExecutionException
    {
        String projectType = getProject().getArtifact().getType();

        // ignore unsupported project types, useful when bundleplugin is configured in parent pom
        if ( !supportedProjectTypes.contains( projectType ) )
        {
            if (!noWarningProjectTypes.contains( projectType ) )
            {
                getLog().warn(
                        "Ignoring project type " + projectType + " - supportedProjectTypes = " + supportedProjectTypes);
            }
            return;
        }

        try
        {
            execute( instructions, getClasspath( project) );
        }
        catch ( IOException e )
        {
            throw new MojoExecutionException( "Error calculating classpath for project " + project, e );
        }
    }


    /* transform directives from their XML form to the expected BND syntax (eg. _include becomes -include) */
    protected static Map<String, String> transformDirectives( Map<String, String> originalInstructions )
    {
        Map<String, String> transformedInstructions = new LinkedHashMap<>();
        for ( Map.Entry<String, String> e : originalInstructions.entrySet() )
        {
            String key = e.getKey();
            if ( key.startsWith( "_" ) )
            {
                key = "-" + key.substring( 1 );
            }

            String value = e.getValue();
            if ( null == value )
            {
                value = "";
            }
            else
            {
                value = value.replaceAll( "\\p{Blank}*[\r\n]\\p{Blank}*", "" );
            }

            if ( Analyzer.WAB.equals( key ) && value.isEmpty() )
            {
                // provide useful default
                value = "src/main/webapp/";
            }

            transformedInstructions.put( key, value );
        }
        return transformedInstructions;
    }


    protected boolean reportErrors( String prefix, Analyzer analyzer )
    {
        List<String> errors = analyzer.getErrors();
        List<String> warnings = analyzer.getWarnings();

        for ( String msg : warnings )
        {
            getLog().warn( prefix + " : " + msg );
        }

        boolean hasErrors = false;
        String fileNotFound = "Input file does not exist: ";
        for ( String msg : errors )
        {
            if ( msg.startsWith(fileNotFound) && msg.endsWith( "~" ) )
            {
                // treat as warning; this error happens when you have duplicate entries in Include-Resource
                String duplicate = Processor.removeDuplicateMarker( msg.substring( fileNotFound.length() ) );
                getLog().warn( prefix + " : Duplicate path '" + duplicate + "' in Include-Resource" );
            }
            else
            {
                getLog().error( prefix + " : " + msg );
                hasErrors = true;
            }
        }
        return hasErrors;
    }


    protected void execute(Map<String, String> originalInstructions,
                           ClassPathItem[] classpath) throws MojoExecutionException
    {
        try
        {
            File jarFile = new File( getBuildDirectory(), getBundleName( project ) );
            Builder builder = buildOSGiBundle( project, originalInstructions, classpath );
            boolean hasErrors = reportErrors( "Bundle " + project.getArtifact(), builder );
            if ( hasErrors )
            {
                String failok = builder.getProperty( "-failok" );
                if ( null == failok || "false".equalsIgnoreCase( failok ) )
                {
                    jarFile.delete();

                    throw new MojoFailureException( "Error(s) found in bundle configuration" );
                }
            }

            // attach bundle to maven project
            jarFile.getParentFile().mkdirs();
            builder.getJar().write( jarFile );

            Artifact mainArtifact = project.getArtifact();

            if ( "bundle".equals( mainArtifact.getType() ) )
            {
                // workaround for MNG-1682: force maven to install artifact using the "jar" handler
                mainArtifact.setArtifactHandler( m_artifactHandlerManager.getArtifactHandler( "jar" ) );
            }

            boolean customClassifier = null != classifier && classifier.trim().length() > 0;
            boolean customPackaging = null != packaging && packaging.trim().length() > 0;

            if ( customClassifier && customPackaging )
            {
                m_projectHelper.attachArtifact( project, packaging, classifier, jarFile );
            }
            else if ( customClassifier )
            {
                m_projectHelper.attachArtifact( project, jarFile, classifier );
            }
            else if ( customPackaging )
            {
                m_projectHelper.attachArtifact( project, packaging, jarFile );
            }
            else
            {
                mainArtifact.setFile( jarFile );
            }

            if ( unpackBundle )
            {
                unpackBundle( jarFile );
            }

            if ( manifestLocation != null )
            {
                File outputFile = new File( manifestLocation, "MANIFEST.MF" );

                try
                {
                    ManifestPlugin.writeManifest( builder, outputFile, niceManifest, exportScr, scrLocation, buildContext, getLog() );
                }
                catch ( IOException e )
                {
                    getLog().error( "Error trying to write Manifest to file " + outputFile, e );
                }
            }

            // cleanup...
            builder.close();
        }
        catch ( MojoFailureException e )
        {
            getLog().error( e.getLocalizedMessage() );
            throw new MojoExecutionException( "Error(s) found in bundle configuration", e );
        }
        catch ( Exception e )
        {
            getLog().error( "An internal error occurred", e );
            throw new MojoExecutionException( "Internal error in maven-bundle-plugin", e );
        }
    }


    protected Builder getOSGiBuilder( MavenProject currentProject, Map<String, String> originalInstructions,
        ClassPathItem[] classpath ) throws Exception
    {
        Properties properties = new Properties();
        properties.putAll( getDefaultProperties( currentProject ) );
        properties.putAll( transformDirectives( originalInstructions ) );

        // process overrides from project
        final Map<String, String> addProps = new HashMap<>();
        for ( Entry<Object, Object> entry : currentProject.getProperties().entrySet() )
        {
            final String key = entry.getKey().toString();
            if ( key.startsWith(BUNDLE_PLUGIN_EXTENSION) )
            {
                final String oKey = key.substring(BUNDLE_PLUGIN_EXTENSION.length());
                final String currentValue = properties.getProperty(oKey);
                if ( currentValue == null )
                {
                    addProps.put(oKey, entry.getValue().toString());
                }
                else
                {
                    addProps.put(oKey, currentValue + ',' + entry.getValue());
                }
            }
            if ( key.startsWith(BUNDLE_PLUGIN_PREPEND_EXTENSION) )
            {
                final String oKey = key.substring(BUNDLE_PLUGIN_PREPEND_EXTENSION.length());
                final String currentValue = properties.getProperty(oKey);
                if ( currentValue == null )
                {
                    addProps.put(oKey, entry.getValue().toString());
                }
                else
                {
                    addProps.put(oKey, entry.getValue() + "," + currentValue);
                }
            }
        }
        properties.putAll( addProps );
        for ( String key : addProps.keySet() )
        {
            properties.remove(BUNDLE_PLUGIN_EXTENSION + key);
            properties.remove(BUNDLE_PLUGIN_PREPEND_EXTENSION + key);
        }

        if (properties.getProperty("Bundle-Activator") != null
                && properties.getProperty("Bundle-Activator").isEmpty())
        {
            properties.remove("Bundle-Activator");
        }
        if (properties.containsKey("-disable-plugin"))
        {
            String[] disabled = properties.remove("-disable-plugin").toString().replaceAll(" ", "").split(",");
            String[] enabled = properties.getProperty(Analyzer.PLUGIN, "").replaceAll(" ", "").split(",");
            Set<String> plugin = new LinkedHashSet<>();
            plugin.addAll(Arrays.asList(enabled));
            plugin.removeAll(Arrays.asList(disabled));
            StringBuilder sb = new StringBuilder();
            for (String s : plugin)
            {
                if (sb.length() > 0)
                {
                    sb.append(",");
                }
                sb.append(s);
            }
            properties.setProperty(Analyzer.PLUGIN, sb.toString());
        }

        Builder builder = new Builder();
        synchronized ( BundlePlugin.class ) // protect setBase...getBndLastModified which uses static DateFormat
        {
            builder.setBase( getBase( currentProject ) );
        }
        builder.setProperties( sanitize( properties ) );
        if ( classpath != null )
        {
            List<Jar> jars = new ArrayList<>();
            for ( int i = 0; i < classpath.length; i++ ) {
                if ( classpath[i].file.exists() ) {
                    jars.add( new Jar( classpath[i].id, classpath[i].file ) );
                }
            }
            builder.setClasspath( jars );
        }

        return builder;
    }


    protected static Properties sanitize( Properties properties )
    {
        // convert any non-String keys/values to Strings
        Properties sanitizedEntries = new Properties();
        for ( Iterator<Map.Entry<Object,Object>> itr = properties.entrySet().iterator(); itr.hasNext(); )
        {
            Map.Entry<Object,Object> entry = itr.next();
            if ( !(entry.getKey() instanceof String) )
            {
                String key = sanitize(entry.getKey());
                if ( !properties.containsKey( key ) )
                {
                    sanitizedEntries.setProperty( key, sanitize( entry.getValue() ) );
                }
                itr.remove();
            }
            else if ( !(entry.getValue() instanceof String) )
            {
                entry.setValue( sanitize( entry.getValue() ) );
            }
        }
        properties.putAll( sanitizedEntries );
        return properties;
    }


    protected static String sanitize( Object value )
    {
        if ( value instanceof String )
        {
            return ( String ) value;
        }
        else if ( value instanceof Iterable )
        {
            String delim = "";
            StringBuilder buf = new StringBuilder();
            for ( Object i : ( Iterable<?> ) value )
            {
                buf.append( delim ).append( i );
                delim = ", ";
            }
            return buf.toString();
        }
        else if ( value.getClass().isArray() )
        {
            String delim = "";
            StringBuilder buf = new StringBuilder();
            for ( int i = 0, len = Array.getLength( value ); i < len; i++ )
            {
                buf.append( delim ).append( Array.get( value, i ) );
                delim = ", ";
            }
            return buf.toString();
        }
        else
        {
            return String.valueOf( value );
        }
    }


    protected void addMavenInstructions(MavenProject currentProject, Builder builder) throws Exception
    {
        if ( currentProject.getBasedir() != null )
        {
            // update BND instructions to add included Maven resources
            includeMavenResources(currentProject, builder, getLog());

            // Fixup error messages
            includeJava9Fixups(currentProject, builder);

            // calculate default export/private settings based on sources
            addLocalPackages(outputDirectory, builder);

            // tell BND where the current project source resides
            addMavenSourcePath(currentProject, builder, getLog());
        }

        // update BND instructions to embed selected Maven dependencies
        Collection<Artifact> embeddableArtifacts = getEmbeddableArtifacts( currentProject, builder );
        DependencyEmbedder dependencyEmbedder = new DependencyEmbedder(getLog(), embeddableArtifacts);
        dependencyEmbedder.processHeaders(builder);

        Collection<Artifact> embeddedArtifacts = dependencyEmbedder.getEmbeddedArtifacts();
        if ( !embeddedArtifacts.isEmpty() && createDependencyReducedPom )
        {
            Set<String> embeddedIds = new HashSet<>();
            for ( Artifact artifact : embeddedArtifacts )
            {
                embeddedIds.add( getId( artifact ) );
            }
            createDependencyReducedPom( embeddedIds );

        }

        if ( dumpInstructions != null || getLog().isDebugEnabled() )
        {
            StringBuilder buf = new StringBuilder();
            getLog().debug( "BND Instructions:" + NL + dumpInstructions( builder.getProperties(), buf ) );
            if ( dumpInstructions != null )
            {
                getLog().info( "Writing BND instructions to " + dumpInstructions );
                dumpInstructions.getParentFile().mkdirs();
                FileUtils.fileWrite( dumpInstructions, "# BND instructions" + NL + buf );
            }
        }



        if ( dumpClasspath != null || getLog().isDebugEnabled() )
        {
            StringBuilder buf = new StringBuilder();
            getLog().debug("BND Classpath:" + NL + dumpClasspath(builder.getClasspath(), buf));
            if ( dumpClasspath != null )
            {
                getLog().info( "Writing BND classpath to " + dumpClasspath );
                dumpClasspath.getParentFile().mkdirs();
                FileUtils.fileWrite( dumpClasspath, "# BND classpath" + NL + buf );
            }
        }
    }


    // We need to find the direct dependencies that have been included in the uber JAR so that we can modify the
    // POM accordingly.
    private void createDependencyReducedPom( Set<String> artifactsToRemove )
            throws IOException, ProjectBuildingException, DependencyGraphBuilderException {
        Model model = project.getOriginalModel();
        List<Dependency> dependencies = new ArrayList<>();

        boolean modified = false;

        List<Dependency> transitiveDeps = new ArrayList<>();

        for ( Artifact artifact : project.getArtifacts() )
        {
            if ( "pom".equals( artifact.getType() ) )
            {
                // don't include pom type dependencies in dependency reduced pom
                continue;
            }

            //promote
            Dependency dep = new Dependency();
            dep.setArtifactId( artifact.getArtifactId() );
            if ( artifact.hasClassifier() )
            {
                dep.setClassifier( artifact.getClassifier() );
            }
            dep.setGroupId( artifact.getGroupId() );
            dep.setOptional( artifact.isOptional() );
            dep.setScope( artifact.getScope() );
            dep.setType( artifact.getType() );
            dep.setVersion( artifact.getVersion() );

            //we'll figure out the exclusions in a bit.

            transitiveDeps.add( dep );
        }
        List<Dependency> origDeps = project.getDependencies();

        for (Dependency d : origDeps)
        {
            dependencies.add(d);

            String id = getId(d);

            if (artifactsToRemove.contains(id))
            {
                modified = true;

                dependencies.remove(d);
            }
        }

        // Check to see if we have a reduction and if so rewrite the POM.
        if ( modified )
        {
            while ( modified )
            {

                model.setDependencies( dependencies );

                if ( dependencyReducedPomLocation == null )
                {
                    // MSHADE-123: We can't default to 'target' because it messes up uses of ${project.basedir}
                    dependencyReducedPomLocation = new File ( project.getBasedir(), "dependency-reduced-pom.xml" );
                }

                File f = dependencyReducedPomLocation;
                if ( f.exists() )
                {
                    f.delete();
                }

                Writer w = WriterFactory.newXmlWriter( f );

                String origRelativePath = null;
                String replaceRelativePath = null;
                if ( model.getParent() != null)
                {
                    origRelativePath = model.getParent().getRelativePath();

                }
                replaceRelativePath = origRelativePath;

                if ( origRelativePath == null )
                {
                    origRelativePath = "../pom.xml";
                }

                if ( model.getParent() != null )
                {
                    File parentFile = new File( project.getBasedir(), model.getParent().getRelativePath() ).getCanonicalFile();
                    if ( !parentFile.isFile() )
                    {
                        parentFile = new File( parentFile, "pom.xml");
                    }

                    parentFile = parentFile.getCanonicalFile();

                    String relPath = RelativizePath.convertToRelativePath( parentFile, f );
                    model.getParent().setRelativePath( relPath );
                }

                try
                {
                    new MavenXpp3Writer().write( w, model );
                }
                finally
                {
                    if ( model.getParent() != null )
                    {
                        model.getParent().setRelativePath( replaceRelativePath );
                    }
                    w.close();
                }

                MavenProject p2 = mavenProjectBuilder.build( f, localRepository, null );
                modified = updateExcludesInDeps( p2, dependencies, transitiveDeps );

            }

            project.setFile( dependencyReducedPomLocation );
        }
    }

    private String getId( Artifact artifact )
    {
        return getId( artifact.getGroupId(), artifact.getArtifactId(), artifact.getType(), artifact.getClassifier() );
    }

    private String getId( Dependency dependency )
    {
        return getId( dependency.getGroupId(), dependency.getArtifactId(), dependency.getType(),
                dependency.getClassifier() );
    }

    private String getId( String groupId, String artifactId, String type, String classifier )
    {
        return groupId + ":" + artifactId + ":" + type + ":" + ( ( classifier != null ) ? classifier : "" );
    }

    public boolean updateExcludesInDeps( MavenProject project, List<Dependency> dependencies, List<Dependency> transitiveDeps )
            throws DependencyGraphBuilderException
    {
        ProjectBuildingRequest request = new DefaultProjectBuildingRequest();
        request.setProject(project);
        request.setRepositorySession(session.getRepositorySession());
        DependencyNode node = dependencyGraphBuilder.buildDependencyGraph(request, null);
        boolean modified = false;
        for (DependencyNode n2 : node.getChildren())
        {
            for (DependencyNode n3 : n2.getChildren())
            {
                //anything two levels deep that is marked "included"
                //is stuff that was excluded by the original poms, make sure it
                //remains excluded IF promoting transitives.
                if (true)
                {
                    //check if it really isn't in the list of original dependencies.  Maven
                    //prior to 2.0.8 may grab versions from transients instead of
                    //from the direct deps in which case they would be marked included
                    //instead of OMITTED_FOR_DUPLICATE

                    //also, if not promoting the transitives, level 2's would be included
                    boolean found = false;
                    for (Dependency dep : transitiveDeps)
                    {
                        if (dep.getArtifactId().equals(n3.getArtifact().getArtifactId())
                                && dep.getGroupId().equals(n3.getArtifact().getGroupId()))
                        {
                            found = true;
                        }

                    }

                    if (!found)
                    {
                        for (Dependency dep : dependencies)
                        {
                            if (dep.getArtifactId().equals(n2.getArtifact().getArtifactId())
                                    && dep.getGroupId().equals(n2.getArtifact().getGroupId()))
                            {
                                Exclusion exclusion = new Exclusion();
                                exclusion.setArtifactId(n3.getArtifact().getArtifactId());
                                exclusion.setGroupId(n3.getArtifact().getGroupId());
                                dep.addExclusion(exclusion);
                                modified = true;
                                break;
                            }
                        }
                    }
                }
            }
        }
        return modified;
    }


    protected Builder buildOSGiBundle(MavenProject currentProject, Map<String, String> originalInstructions,
                                      ClassPathItem[] classpath) throws Exception
    {
        Builder builder = getOSGiBuilder( currentProject, originalInstructions, classpath );

        addMavenInstructions( currentProject, builder );

        builder.build();

        mergeMavenManifest(currentProject, builder);

        return builder;
    }


    protected static StringBuilder dumpInstructions( Properties properties, StringBuilder buf )
    {
        try
        {
            buf.append( "#-----------------------------------------------------------------------" + NL );
            Properties stringProperties = new Properties();
            for ( Enumeration<String> e = (Enumeration<String>) properties.propertyNames(); e.hasMoreElements(); )
            {
                // we can only store String properties
                String key = e.nextElement();
                String value = properties.getProperty( key );
                if ( value != null )
                {
                    stringProperties.setProperty( key, value );
                }
            }
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            stringProperties.store( out, null ); // properties encoding is 8859_1
            buf.append( out.toString( "8859_1" ) );
            buf.append("#-----------------------------------------------------------------------").append(NL);
        }
        catch ( Throwable e )
        {
            // ignore...
        }
        return buf;
    }


    protected static StringBuilder dumpClasspath( List<Jar> classpath, StringBuilder buf )
    {
        try
        {
            buf.append("#-----------------------------------------------------------------------").append(NL);
            buf.append("-classpath:\\").append(NL);
            for ( Iterator<Jar> i = classpath.iterator(); i.hasNext(); )
            {
                File path = i.next().getSource();
                if ( path != null )
                {
                    buf.append(' ').append(path.toString()).append(i.hasNext() ? ",\\" : "").append(NL);
                }
            }
            buf.append("#-----------------------------------------------------------------------").append(NL);
        }
        catch ( Throwable e )
        {
            // ignore...
        }
        return buf;
    }


    protected static StringBuilder dumpManifest( Manifest manifest, StringBuilder buf )
    {
        try
        {
            buf.append("#-----------------------------------------------------------------------").append(NL);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            ManifestWriter.outputManifest(manifest, out, true); // manifest encoding is UTF8
            buf.append( out.toString( "UTF8" ) );
            buf.append("#-----------------------------------------------------------------------").append(NL);
        }
        catch ( Throwable e )
        {
            // ignore...
        }
        return buf;
    }


    protected static void includeMavenResources( MavenProject currentProject, Analyzer analyzer, Log log )
    {
        // pass maven resource paths onto BND analyzer
        final String mavenResourcePaths = getMavenResourcePaths( currentProject, false );
        final String mavenTestResourcePaths = getMavenResourcePaths( currentProject, true );
        final String includeResource = analyzer.getProperty( Analyzer.INCLUDE_RESOURCE );
        if ( includeResource != null )
        {
            if ( includeResource.contains( MAVEN_RESOURCES ) || includeResource.contains( MAVEN_TEST_RESOURCES ) )
            {
                String combinedResource = StringUtils.replace( includeResource, MAVEN_RESOURCES, mavenResourcePaths );
                combinedResource = StringUtils.replace( combinedResource, MAVEN_TEST_RESOURCES, mavenTestResourcePaths );
                if ( combinedResource.length() > 0 )
                {
                    analyzer.setProperty( Analyzer.INCLUDE_RESOURCE, combinedResource );
                }
                else
                {
                    analyzer.unsetProperty( Analyzer.INCLUDE_RESOURCE );
                }
            }
            else if ( mavenResourcePaths.length() > 0 )
            {
                log.warn( Analyzer.INCLUDE_RESOURCE + ": overriding " + mavenResourcePaths + " with " + includeResource
                        + " (add " + MAVEN_RESOURCES + " if you want to include the maven resources)" );
            }
        }
        else if ( mavenResourcePaths.length() > 0 )
        {
            analyzer.setProperty( Analyzer.INCLUDE_RESOURCE, mavenResourcePaths );
        }
    }


    protected void mergeMavenManifest(MavenProject currentProject, Builder builder) throws Exception
    {
        Jar jar = builder.getJar();

        if ( getLog().isDebugEnabled() )
        {
            getLog().debug( "BND Manifest:" + NL + dumpManifest( jar.getManifest(), new StringBuilder() ) );
        }

        boolean addMavenDescriptor = currentProject.getBasedir() != null;

        try
        {
            /*
             * Grab customized manifest entries from the maven-jar-plugin configuration
             */
            MavenArchiveConfiguration archiveConfig = JarPluginConfiguration.getArchiveConfiguration( currentProject );
            String mavenManifestText = new MavenArchiver().getManifest( currentProject, archiveConfig.getManifest() ).toString();
            addMavenDescriptor = addMavenDescriptor && archiveConfig.isAddMavenDescriptor();

            Manifest mavenManifest = new Manifest();

            // First grab the external manifest file (if specified and different to target location)
            File externalManifestFile = archiveConfig.getManifestFile();
            if ( null != externalManifestFile )
            {
                if ( !externalManifestFile.isAbsolute() )
                {
                    externalManifestFile = new File( currentProject.getBasedir(), externalManifestFile.getPath() );
                }
                if ( externalManifestFile.exists() && !externalManifestFile.equals( new File( manifestLocation, "MANIFEST.MF" ) ) )
                {
                    InputStream mis = new FileInputStream( externalManifestFile );
                    mavenManifest.read( mis );
                    mis.close();
                }
            }

            // Then apply customized entries from the jar plugin; note: manifest encoding is UTF8
            mavenManifest.read( new ByteArrayInputStream( mavenManifestText.getBytes( "UTF8" ) ) );

            if ( !archiveConfig.isManifestSectionsEmpty() )
            {
                /*
                 * Add customized manifest sections (for some reason MavenArchiver doesn't do this for us)
                 */
                List<ManifestSection> sections = archiveConfig.getManifestSections();
                for ( Iterator<ManifestSection> i = sections.iterator(); i.hasNext(); )
                {
                    ManifestSection section = i.next();
                    Attributes attributes = new Attributes();

                    if ( !section.isManifestEntriesEmpty() )
                    {
                        Map<String, String> entries = section.getManifestEntries();
                        for ( Iterator<Map.Entry<String, String>> j = entries.entrySet().iterator(); j.hasNext(); )
                        {
                            Map.Entry<String, String> entry = j.next();
                            attributes.putValue( entry.getKey(), entry.getValue() );
                        }
                    }

                    mavenManifest.getEntries().put( section.getName(), attributes );
                }
            }

            Attributes mainMavenAttributes = mavenManifest.getMainAttributes();
            mainMavenAttributes.putValue( "Created-By", "Apache Maven Bundle Plugin" );

            String[] removeHeaders = builder.getProperty( Constants.REMOVEHEADERS, "" ).split( "," );

            // apply -removeheaders to the custom manifest
            for ( int i = 0; i < removeHeaders.length; i++ )
            {
                for ( Iterator<Object> j = mainMavenAttributes.keySet().iterator(); j.hasNext(); )
                {
                    if ( j.next().toString().matches( removeHeaders[i].trim() ) )
                    {
                        j.remove();
                    }
                }
            }

            /*
             * Overlay generated bundle manifest with customized entries
             */
            Properties properties = builder.getProperties();
            Manifest bundleManifest = jar.getManifest();
            if ( properties.containsKey( "Merge-Headers" ) )
            {
                Instructions instructions = new Instructions( ExtList.from(builder.getProperty("Merge-Headers")) );
                mergeManifest( instructions, bundleManifest, mavenManifest );
            }
            else
            {
                bundleManifest.getMainAttributes().putAll( mainMavenAttributes );
                bundleManifest.getEntries().putAll( mavenManifest.getEntries() );
            }

            // adjust the import package attributes so that optional dependencies use
            // optional resolution.
            String importPackages = bundleManifest.getMainAttributes().getValue( "Import-Package" );
            if ( importPackages != null )
            {
                Set optionalPackages = getOptionalPackages( currentProject);

                Map<String, ? extends Map<String, String>> values;
                try (Analyzer analyzer = new Analyzer()) {
                    values = analyzer.parseHeader( importPackages );
                }
                for ( Map.Entry<String, ? extends Map<String, String>> entry : values.entrySet() )
                {
                    String pkg = entry.getKey();
                    Map<String, String> options = entry.getValue();
                    if ( !options.containsKey( "resolution:" ) && optionalPackages.contains( pkg ) )
                    {
                        options.put( "resolution:", "optional" );
                    }
                }
                String result = Processor.printClauses( values );
                bundleManifest.getMainAttributes().putValue( "Import-Package", result );
            }

            jar.setManifest( bundleManifest );
        }
        catch ( Exception e )
        {
            getLog().warn( "Unable to merge Maven manifest: " + e.getLocalizedMessage() );
        }

        if ( addMavenDescriptor )
        {
            doMavenMetadata( currentProject, jar );
        }

        if ( getLog().isDebugEnabled() )
        {
            getLog().debug( "Final Manifest:" + NL + dumpManifest( jar.getManifest(), new StringBuilder() ) );
        }

        builder.setJar( jar );
    }


    protected static void mergeManifest( Instructions instructions, Manifest... manifests ) throws IOException
    {
        for ( int i = manifests.length - 2; i >= 0; i-- )
        {
            Manifest mergedManifest = manifests[i];
            Manifest manifest = manifests[i + 1];
            Attributes mergedMainAttributes = mergedManifest.getMainAttributes();
            Attributes mainAttributes = manifest.getMainAttributes();
            Attributes filteredMainAttributes = filterAttributes( instructions, mainAttributes, null );
            if ( !filteredMainAttributes.isEmpty() )
            {
                mergeAttributes( mergedMainAttributes, filteredMainAttributes );
            }
            Map<String, Attributes> mergedEntries = mergedManifest.getEntries();
            Map<String, Attributes> entries = manifest.getEntries();
            for ( Map.Entry<String, Attributes> entry : entries.entrySet() )
            {
                String name = entry.getKey();
                Attributes attributes = entry.getValue();
                Attributes filteredAttributes = filterAttributes( instructions, attributes, null );
                if ( !filteredAttributes.isEmpty() )
                {
                    Attributes mergedAttributes = mergedManifest.getAttributes( name );
                    if ( mergedAttributes != null)
                    {
                        mergeAttributes(mergedAttributes, filteredAttributes);
                    }
                    else
                    {
                        mergedEntries.put(name, filteredAttributes);
                    }
                }
            }
        }
    }


    /**
     * @see Analyzer#filter
     */
    private static Attributes filterAttributes(Instructions instructions, Attributes source, Set<Instruction> nomatch) {
        Attributes result = new Attributes();
        Map<String, Object> keys = new TreeMap<>();
        for ( Object key : source.keySet() )
        {
            keys.put( key.toString(), key );
        }

        List<Instruction> filters = new ArrayList<>( instructions.keySet() );
        if (nomatch == null)
        {
            nomatch = Create.set();
        }
        for ( Instruction instruction : filters ) {
            boolean match = false;
            for (Iterator<Map.Entry<String, Object>> i = keys.entrySet().iterator(); i.hasNext();)
            {
                Map.Entry<String, Object> entry = i.next();
                String key = entry.getKey();
                if ( instruction.matches( key ) )
                {
                    match = true;
                    if (!instruction.isNegated()) {
                        Object name = entry.getValue();
                        Object value = source.get( name );
                        result.put( name, value );
                    }
                    i.remove(); // Can never match again for another pattern
                }
            }
            if (!match && !instruction.isAny())
                nomatch.add(instruction);
        }

        /*
         * Tricky. If we have umatched instructions they might indicate that we
         * want to have multiple decorators for the same package. So we check
         * the unmatched against the result list. If then then match and have
         * actually interesting properties then we merge them
         */

        for (Iterator<Instruction> i = nomatch.iterator(); i.hasNext();) {
            Instruction instruction = i.next();

            // We assume the user knows what he is
            // doing and inserted a literal. So
            // we ignore any not matched literals
            // #252, we should not be negated to make it a constant
            if (instruction.isLiteral() && !instruction.isNegated()) {
                Object key = keys.get( instruction.getLiteral() );
                if ( key != null )
                {
                    Object value = source.get( key );
                    result.put( key, value );
                }
                i.remove();
                continue;
            }

            // Not matching a negated instruction looks
            // like an error ... Though so, but
            // in the second phase of Export-Package
            // the !package will never match anymore.
            if (instruction.isNegated()) {
                i.remove();
                continue;
            }

            // An optional instruction should not generate
            // an error
            if (instruction.isOptional()) {
                i.remove();
                continue;
            }
        }
        return result;
    }


    private static void mergeAttributes( Attributes... attributesArray ) throws IOException
    {
        for ( int i = attributesArray.length - 2; i >= 0; i-- )
        {
            Attributes mergedAttributes = attributesArray[i];
            Attributes attributes = attributesArray[i + 1];
            for ( Map.Entry<Object, Object> entry : attributes.entrySet() )
            {
                Object name = entry.getKey();
                String value = (String) entry.getValue();
                String oldValue = (String) mergedAttributes.put( name, value );
                if ( oldValue != null )
                {
                    Parameters mergedClauses = OSGiHeader.parseHeader(oldValue);
                    Parameters clauses = OSGiHeader.parseHeader( value );
                    if ( !mergedClauses.isEqual( clauses) )
                    {
                        for ( Map.Entry<String, Attrs> clauseEntry : clauses.entrySet() )
                        {
                            String clause = clauseEntry.getKey();
                            Attrs attrs = clauseEntry.getValue();
                            Attrs mergedAttrs = mergedClauses.get( clause );
                            if ( mergedAttrs == null)
                            {
                                mergedClauses.put( clause, attrs );
                            }
                            else if ( !mergedAttrs.isEqual(attrs) )
                            {
                                for ( Map.Entry<String,String> adentry : attrs.entrySet() )
                                {
                                    String adname = adentry.getKey();
                                    String ad = adentry.getValue();
                                    if ( mergedAttrs.containsKey( adname ) )
                                    {
                                        Attrs.Type type = attrs.getType( adname );
                                        switch (type)
                                        {
                                            case VERSIONS:
                                            case STRINGS:
                                            case LONGS:
                                            case DOUBLES:
                                                ExtList<String> mergedAd = ExtList.from( mergedAttrs.get( adname ) );
                                                ExtList.from( ad ).addAll( ExtList.from( ad ) );
                                                mergedAttrs.put(adname, mergedAd.join() );
                                                break;
                                        }
                                    }
                                    else
                                    {
                                        mergedAttrs.put( adname, ad );
                                    }
                                }
                            }
                        }
                        mergedAttributes.put( name, Processor.printClauses( mergedClauses ) );
                    }
                }
            }
        }
    }


    protected Set<String> getOptionalPackages(MavenProject currentProject) throws IOException, MojoExecutionException
    {
        ArrayList<Artifact> inscope = new ArrayList<>();
        final Collection<Artifact> artifacts = getSelectedDependencies(currentProject.getArtifacts() );
        for ( Iterator<Artifact> it = artifacts.iterator(); it.hasNext(); )
        {
            Artifact artifact = it.next();
            if ( artifact.getArtifactHandler().isAddedToClasspath() )
            {
                inscope.add( artifact );
            }
        }

        HashSet<String> optionalArtifactIds = new HashSet<>();
        for ( Iterator<Artifact> it = inscope.iterator(); it.hasNext(); )
        {
            Artifact artifact = it.next();
            if ( artifact.isOptional() )
            {
                String id = artifact.toString();
                if ( artifact.getScope() != null )
                {
                    // strip the scope...
                    id = id.replaceFirst( ":[^:]*$", "" );
                }
                optionalArtifactIds.add( id );
            }

        }

        HashSet<String> required = new HashSet<>();
        HashSet<String> optional = new HashSet<>();
        for ( Iterator<Artifact> it = inscope.iterator(); it.hasNext(); )
        {
            Artifact artifact = it.next();
            File file = getFile( artifact );
            if ( file == null )
            {
                continue;
            }

            Jar jar = new Jar( artifact.getArtifactId(), file );
            if ( isTransitivelyOptional( optionalArtifactIds, artifact ) )
            {
                optional.addAll( jar.getPackages() );
            }
            else
            {
                required.addAll( jar.getPackages() );
            }
            jar.close();
        }

        optional.removeAll( required );
        return optional;
    }


    /**
     * Check to see if any dependency along the dependency trail of
     * the artifact is optional.
     *
     * @param artifact
     */
    protected boolean isTransitivelyOptional( HashSet<String> optionalArtifactIds, Artifact artifact )
    {
        List<String> trail = artifact.getDependencyTrail();
        for ( Iterator<String> iterator = trail.iterator(); iterator.hasNext(); )
        {
            String next = iterator.next();
            if ( optionalArtifactIds.contains( next ) )
            {
                return true;
            }
        }
        return false;
    }


    private void unpackBundle( File jarFile )
    {
        File outputDir = getOutputDirectory();
        if ( null == outputDir )
        {
            outputDir = new File( getBuildDirectory(), "classes" );
        }

        try
        {
            /*
             * this directory must exist before unpacking, otherwise the plexus
             * unarchiver decides to use the current working directory instead!
             */
            if ( !outputDir.exists() )
            {
                outputDir.mkdirs();
            }

            UnArchiver unArchiver = m_archiverManager.getUnArchiver( "jar" );
            unArchiver.setDestDirectory( outputDir );
            unArchiver.setSourceFile( jarFile );
            unArchiver.extract();
        }
        catch ( Exception e )
        {
            getLog().error( "Problem unpacking " + jarFile + " to " + outputDir, e );
        }
    }


    protected static String removeTagFromInstruction( String instruction, String tag )
    {
        StringBuffer buf = new StringBuffer();

        String[] clauses = instruction.split( "," );
        for ( int i = 0; i < clauses.length; i++ )
        {
            String clause = clauses[i].trim();
            if ( !tag.equals( clause ) )
            {
                if ( buf.length() > 0 )
                {
                    buf.append( ',' );
                }
                buf.append( clause );
            }
        }

        return buf.toString();
    }


    private static Map<String, String> getProperties( Model projectModel, String prefix )
    {
        Map<String, String> properties = new LinkedHashMap<>();
        Method methods[] = Model.class.getDeclaredMethods();
        for ( int i = 0; i < methods.length; i++ )
        {
            String name = methods[i].getName();
            if ( name.startsWith( "get" ) )
            {
                try
                {
                    Object v = methods[i].invoke( projectModel, null );
                    if ( v != null )
                    {
                        name = prefix + Character.toLowerCase( name.charAt( 3 ) ) + name.substring( 4 );
                        if ( v.getClass().isArray() )
                            properties.put( name, Arrays.asList( ( Object[] ) v ).toString() );
                        else
                            properties.put( name, v.toString() );

                    }
                }
                catch ( Exception e )
                {
                    // too bad
                }
            }
        }
        return properties;
    }


    private static StringBuffer printLicenses( List<License> licenses )
    {
        if ( licenses == null || licenses.size() == 0 )
            return null;
        StringBuffer sb = new StringBuffer();
        String del = "";
        for ( Iterator<License> i = licenses.iterator(); i.hasNext(); )
        {
            License l = i.next();
            String url = l.getUrl();
            if ( url == null )
                continue;
            sb.append( del );
            sb.append( url );
            del = ", ";
        }
        if ( sb.length() == 0 )
            return null;
        return sb;
    }


    /**
     * @param jar
     * @throws IOException
     */
    private void doMavenMetadata( MavenProject currentProject, Jar jar ) throws IOException
    {
        String path = "META-INF/maven/" + currentProject.getGroupId() + "/" + currentProject.getArtifactId();

        File pomFile = currentProject.getFile();
        if ( pomFile == null || !pomFile.exists() )
        {
            pomFile = new File( currentProject.getBasedir(), "pom.xml" );
        }
        if ( pomFile.exists() )
        {
            jar.putResource( path + "/pom.xml", new FileResource( pomFile ) );
        }

        Properties p = new Properties();
        p.put( "version", currentProject.getVersion() );
        p.put( "groupId", currentProject.getGroupId() );
        p.put( "artifactId", currentProject.getArtifactId() );
        jar.putResource( path + "/pom.properties", new EmbeddedResource( toFileContentAsBytes( p ), System.currentTimeMillis() ) );
    }


    private byte[] toFileContentAsBytes( Properties properties )
    {
        byte[] bytes;
        try
        {
            StringWriter sw = new StringWriter();
            properties.store( sw, null );
    
            BufferedReader r = new BufferedReader( new StringReader( sw.toString() ) );
            StringWriter stringWriter = new StringWriter();
    
            String line;
            while ( ( line = r.readLine() ) != null )
            {
                if ( !line.startsWith( "#" ) )
                {
                    stringWriter.append( line ).append( NL );
                }
            }
            bytes = stringWriter.getBuffer().toString().getBytes( StandardCharsets.ISO_8859_1 );
           
            r.close();
            sw.close();
            stringWriter.close();
        }
        catch ( IOException e )
        {
            getLog().error( "Error while converting properties to file content. Returning empty array.", e );
            bytes = new byte[] {};
        }
        return bytes;
    }


    protected ClassPathItem[] getClasspath(MavenProject currentProject) throws IOException, MojoExecutionException
    {
        List<ClassPathItem> list = new ArrayList<>( currentProject.getArtifacts().size() + 1 );

        String d = currentProject.getBuild() != null ? currentProject.getBuild().getOutputDirectory() : null;
        if ( d != null )
        {
            list.add( new ClassPathItem( ".", new File( d ) ) );
        }

        final Collection<Artifact> artifacts = getSelectedDependencies(currentProject.getArtifacts() );
        for ( Artifact artifact : artifacts  )
        {
            if ( artifact.getArtifactHandler().isAddedToClasspath() && !Artifact.SCOPE_TEST.equals( artifact.getScope() ) )
            {
                File file = getFile( artifact );
                if ( file == null )
                {
                    getLog().warn(
                            "File is not available for artifact " + artifact + " in project "
                                    + currentProject.getArtifact() );
                    continue;
                }
                ClassPathItem jar = new ClassPathItem( artifact.getArtifactId(), file );
                list.add( jar );
            }
        }
        ClassPathItem[] cp = new ClassPathItem[list.size()];
        list.toArray( cp );

        return cp;
    }


    private Collection<Artifact> getSelectedDependencies(Collection<Artifact> artifacts) throws MojoExecutionException
    {
        if ( null == excludeDependencies || excludeDependencies.isEmpty() )
        {
            return artifacts;
        }
        else if ( "true".equalsIgnoreCase( excludeDependencies ) )
        {
            return Collections.emptyList();
        }

        Collection<Artifact> selectedDependencies = new LinkedHashSet<>( artifacts );
        DependencyExcluder excluder = new DependencyExcluder(artifacts );
        excluder.processHeaders( excludeDependencies );
        selectedDependencies.removeAll( excluder.getExcludedArtifacts() );

        return selectedDependencies;
    }


    /**
     * Get the file for an Artifact
     *
     * @param artifact
     */
    protected File getFile( Artifact artifact )
    {
        return artifact.getFile();
    }


    private static void header( Properties properties, String key, Object value )
    {
        if ( value == null )
            return;

        if ( value instanceof Collection && ( ( Collection ) value ).isEmpty() )
            return;

        properties.put( key, value.toString().replaceAll( "[\r\n]", "" ) );
    }


    /**
     * Convert a Maven version into an OSGi compliant version
     *
     * @param version Maven version
     * @return the OSGi version
     */
    protected String convertVersionToOsgi( String version )
    {
        return getMaven2OsgiConverter().getVersion( version );
    }


    /**
     * TODO this should return getMaven2Osgi().getBundleFileName( project.getArtifact() )
     */
    protected String getBundleName( MavenProject currentProject )
    {
        String extension;
        try
        {
            extension = currentProject.getArtifact().getArtifactHandler().getExtension();
        }
        catch ( Throwable e )
        {
            extension = currentProject.getArtifact().getType();
        }
        if ( StringUtils.isEmpty( extension ) || "bundle".equals( extension ) || "pom".equals( extension ) )
        {
            extension = "jar"; // just in case maven gets confused
        }
        if ( null != classifier && classifier.trim().length() > 0 )
        {
            return finalName + '-' + classifier + '.' + extension;
        }
        return finalName + '.' + extension;
    }


    protected String getBuildDirectory()
    {
        return buildDirectory;
    }


    protected void setBuildDirectory( String _buildirectory )
    {
        buildDirectory = _buildirectory;
    }


    protected Properties getDefaultProperties( MavenProject currentProject )
    {
        Properties properties = new Properties();

        String bsn;
        try
        {
            bsn = getMaven2OsgiConverter().getBundleSymbolicName( currentProject.getArtifact() );
        }
        catch ( Exception e )
        {
            bsn = currentProject.getGroupId() + "." + currentProject.getArtifactId();
        }

        // Setup defaults
        properties.put( MAVEN_SYMBOLICNAME, bsn );
        properties.put( Analyzer.BUNDLE_SYMBOLICNAME, bsn );
        properties.put( Analyzer.IMPORT_PACKAGE, "*" );
        properties.put( Analyzer.BUNDLE_VERSION, getMaven2OsgiConverter().getVersion( currentProject.getVersion() ) );

        // remove the extraneous Include-Resource and Private-Package entries from generated manifest
        properties.put( Constants.REMOVEHEADERS, Analyzer.INCLUDE_RESOURCE + ',' + Analyzer.PRIVATE_PACKAGE );

        header( properties, Analyzer.BUNDLE_DESCRIPTION, currentProject.getDescription() );
        StringBuffer licenseText = printLicenses( currentProject.getLicenses() );
        if ( licenseText != null )
        {
            header( properties, Analyzer.BUNDLE_LICENSE, licenseText );
        }
        header( properties, Analyzer.BUNDLE_NAME, currentProject.getName() );

        if ( currentProject.getOrganization() != null )
        {
            if ( currentProject.getOrganization().getName() != null )
            {
                String organizationName = currentProject.getOrganization().getName();
                header( properties, Analyzer.BUNDLE_VENDOR, organizationName );
                properties.put( "project.organization.name", organizationName );
                properties.put( "pom.organization.name", organizationName );
            }
            if ( currentProject.getOrganization().getUrl() != null )
            {
                String organizationUrl = currentProject.getOrganization().getUrl();
                header( properties, Analyzer.BUNDLE_DOCURL, organizationUrl );
                properties.put( "project.organization.url", organizationUrl );
                properties.put( "pom.organization.url", organizationUrl );
            }
        }

        properties.putAll( currentProject.getProperties() );
        properties.putAll( currentProject.getModel().getProperties() );

        for ( Iterator<String> i = currentProject.getFilters().iterator(); i.hasNext(); )
        {
            File filterFile = new File( i.next() );
            if ( filterFile.isFile() )
            {
                try
                {
                    properties.putAll( PropertyUtils.loadProperties( filterFile ) );
                }
                catch ( IOException e )
                {
                    // Ignore
                }
            }
        }

        if ( m_mavenSession != null )
        {
            try
            {
                // don't pass upper-case session settings to bnd as they end up in the manifest
                Properties sessionProperties = m_mavenSession.getExecutionProperties();
                for ( Enumeration<String> e = (Enumeration<String>) sessionProperties.propertyNames(); e.hasMoreElements(); )
                {
                    String key = e.nextElement();
                    if ( key.length() > 0 && !Character.isUpperCase( key.charAt( 0 ) ) )
                    {
                        properties.put( key, sessionProperties.getProperty( key ) );
                    }
                }
            }
            catch ( Exception e )
            {
                getLog().warn( "Problem with Maven session properties: " + e.getLocalizedMessage() );
            }
        }

        properties.putAll( getProperties( currentProject.getModel(), "project.build." ) );
        properties.putAll( getProperties( currentProject.getModel(), "pom." ) );
        properties.putAll( getProperties( currentProject.getModel(), "project." ) );

        properties.put( "project.baseDir", getBase( currentProject ) );
        properties.put( "project.build.directory", getBuildDirectory() );
        properties.put( "project.build.outputdirectory", getOutputDirectory() );

        properties.put( "classifier", classifier == null ? "" : classifier );

        // Add default plugins
        header( properties, Analyzer.PLUGIN, BlueprintPlugin.class.getName() + ","
                                           + SpringXMLType.class.getName() + ","
                                           + JpaPlugin.class.getName() );

        return properties;
    }


    protected static File getBase( MavenProject currentProject )
    {
        return currentProject.getBasedir() != null ? currentProject.getBasedir() : new File( "" );
    }


    protected File getOutputDirectory()
    {
        return outputDirectory;
    }


    protected void setOutputDirectory( File _outputDirectory )
    {
        outputDirectory = _outputDirectory;
    }


    private static void addLocalPackages( File outputDirectory, Analyzer analyzer ) throws IOException
    {
        Packages packages = new Packages();

        if ( outputDirectory != null && outputDirectory.isDirectory() )
        {
            // scan classes directory for potential packages
            DirectoryScanner scanner = new DirectoryScanner();
            scanner.setBasedir( outputDirectory );
            scanner.setIncludes( new String[]
                { "**/*.class" } );

            scanner.addDefaultExcludes();
            scanner.scan();

            String[] paths = scanner.getIncludedFiles();
            for ( int i = 0; i < paths.length; i++ )
            {
                packages.put( analyzer.getPackageRef( getPackageName( paths[i] ) ) );
            }
        }

        Packages exportedPkgs = new Packages();
        Packages privatePkgs = new Packages();

        boolean noprivatePackages = "!*".equals( analyzer.getProperty( Analyzer.PRIVATE_PACKAGE ) );

        for ( PackageRef pkg : packages.keySet() )
        {
            // mark all source packages as private by default (can be overridden by export list)
            privatePkgs.put( pkg );

            // we can't export the default package (".") and we shouldn't export internal packages
            String fqn = pkg.getFQN();
            if ( noprivatePackages || !( ".".equals( fqn ) || fqn.contains( ".internal" ) || fqn.contains( ".impl" ) ) )
            {
                exportedPkgs.put( pkg );
            }
        }

        Properties properties = analyzer.getProperties();
        String exported = properties.getProperty( Analyzer.EXPORT_PACKAGE );
        if ( exported == null )
        {
            if ( !properties.containsKey( Analyzer.EXPORT_CONTENTS ) )
            {
                // no -exportcontents overriding the exports, so use our computed list
                for ( Attrs attrs : exportedPkgs.values() )
                {
                    attrs.put( Constants.SPLIT_PACKAGE_DIRECTIVE, "merge-first" );
                }
                properties.setProperty( Analyzer.EXPORT_PACKAGE, Processor.printClauses( exportedPkgs ) );
            }
            else
            {
                // leave Export-Package empty (but non-null) as we have -exportcontents
                properties.setProperty( Analyzer.EXPORT_PACKAGE, "" );
            }
        }
        else if ( exported.indexOf( LOCAL_PACKAGES ) >= 0 )
        {
            String newExported = StringUtils.replace( exported, LOCAL_PACKAGES, Processor.printClauses( exportedPkgs ) );
            properties.setProperty( Analyzer.EXPORT_PACKAGE, newExported );
        }

        String internal = properties.getProperty( Analyzer.PRIVATE_PACKAGE );
        if ( internal == null )
        {
            if ( !privatePkgs.isEmpty() )
            {
                for ( Attrs attrs : privatePkgs.values() )
                {
                    attrs.put( Constants.SPLIT_PACKAGE_DIRECTIVE, "merge-first" );
                }
                properties.setProperty( Analyzer.PRIVATE_PACKAGE, Processor.printClauses( privatePkgs ) );
            }
            else
            {
                // if there are really no private packages then use "!*" as this will keep the Bnd Tool happy
                properties.setProperty( Analyzer.PRIVATE_PACKAGE, "!*" );
            }
        }
        else if ( internal.indexOf( LOCAL_PACKAGES ) >= 0 )
        {
            String newInternal = StringUtils.replace( internal, LOCAL_PACKAGES, Processor.printClauses( privatePkgs ) );
            properties.setProperty( Analyzer.PRIVATE_PACKAGE, newInternal );
        }
    }


    private static String getPackageName( String filename )
    {
        int n = filename.lastIndexOf( File.separatorChar );
        return n < 0 ? "." : filename.substring( 0, n ).replace( File.separatorChar, '.' );
    }


    private static List<Resource> getMavenResources( MavenProject currentProject, boolean test )
    {
        List<Resource> resources = new ArrayList<>( test ? currentProject.getTestResources() : currentProject.getResources() );

        if ( currentProject.getCompileSourceRoots() != null )
        {
            // also scan for any "packageinfo" files lurking in the source folders
            final List<String> packageInfoIncludes = Collections.singletonList( "**/packageinfo" );
            for ( Iterator<String> i = currentProject.getCompileSourceRoots().iterator(); i.hasNext(); )
            {
                String sourceRoot = i.next();
                Resource packageInfoResource = new Resource();
                packageInfoResource.setDirectory( sourceRoot );
                packageInfoResource.setIncludes( packageInfoIncludes );
                resources.add( packageInfoResource );
            }
        }

        return resources;
    }


    protected static String getMavenResourcePaths( MavenProject currentProject, boolean test )
    {
        final String basePath = currentProject.getBasedir().getAbsolutePath();

        Set<String> pathSet = new LinkedHashSet<>();
        for ( Iterator<Resource> i = getMavenResources( currentProject, test ).iterator(); i.hasNext(); )
        {
            Resource resource = i.next();

            final String sourcePath = resource.getDirectory();
            final String targetPath = resource.getTargetPath();

            // ignore empty or non-local resources
            if ( new File( sourcePath ).exists() && ( ( targetPath == null ) || ( targetPath.indexOf( ".." ) < 0 ) ) )
            {
                DirectoryScanner scanner = new DirectoryScanner();

                scanner.setBasedir( sourcePath );
                if ( resource.getIncludes() != null && !resource.getIncludes().isEmpty() )
                {
                    scanner.setIncludes( resource.getIncludes().toArray( EMPTY_STRING_ARRAY ) );
                }
                else
                {
                    scanner.setIncludes( DEFAULT_INCLUDES );
                }

                if ( resource.getExcludes() != null && !resource.getExcludes().isEmpty() )
                {
                    scanner.setExcludes( resource.getExcludes().toArray( EMPTY_STRING_ARRAY ) );
                }

                scanner.addDefaultExcludes();
                scanner.scan();

                List<String> includedFiles = Arrays.asList( scanner.getIncludedFiles() );

                for ( Iterator<String> j = includedFiles.iterator(); j.hasNext(); )
                {
                    String name = j.next();
                    String path = sourcePath + '/' + name;

                    // make relative to project
                    if ( path.startsWith( basePath ) )
                    {
                        if ( path.length() == basePath.length() )
                        {
                            path = ".";
                        }
                        else
                        {
                            path = path.substring( basePath.length() + 1 );
                        }
                    }

                    // replace windows backslash with a slash
                    // this is a workaround for a problem with bnd 0.0.189
                    if ( File.separatorChar != '/' )
                    {
                        name = name.replace( File.separatorChar, '/' );
                        path = path.replace( File.separatorChar, '/' );
                    }

                    // copy to correct place
                    path = name + '=' + path;
                    if ( targetPath != null )
                    {
                        path = targetPath + '/' + path;
                    }

                    // use Bnd filtering?
                    if ( resource.isFiltering() )
                    {
                        path = '{' + path + '}';
                    }

                    pathSet.add( path );
                }
            }
        }

        StringBuffer resourcePaths = new StringBuffer();
        for ( Iterator<String> i = pathSet.iterator(); i.hasNext(); )
        {
            resourcePaths.append( i.next() );
            if ( i.hasNext() )
            {
                resourcePaths.append( ',' );
            }
        }

        return resourcePaths.toString();
    }


    protected Collection<Artifact> getEmbeddableArtifacts(MavenProject currentProject, Analyzer analyzer)
        throws MojoExecutionException
    {
        final Collection<Artifact> artifacts;

        String embedTransitive = analyzer.getProperty( DependencyEmbedder.EMBED_TRANSITIVE );
        if (Boolean.valueOf(embedTransitive))
        {
            // includes transitive dependencies
            artifacts = currentProject.getArtifacts();
        }
        else
        {
            // only includes direct dependencies
            artifacts = currentProject.getDependencyArtifacts();
        }

        return getSelectedDependencies(artifacts );
    }


    protected static void addMavenSourcePath( MavenProject currentProject, Analyzer analyzer, Log log )
    {
        // pass maven source paths onto BND analyzer
        StringBuilder mavenSourcePaths = new StringBuilder();
        StringBuilder mavenTestSourcePaths = new StringBuilder();
        Map<StringBuilder, List<String>> map = new HashMap<>(2);
        map.put(mavenSourcePaths, currentProject.getCompileSourceRoots() );
        map.put(mavenTestSourcePaths, currentProject.getTestCompileSourceRoots() );
        for ( Map.Entry<StringBuilder, List<String>> entry : map.entrySet() )
        {
            List<String> compileSourceRoots = entry.getValue();
            if ( compileSourceRoots != null )
            {
                StringBuilder sourcePaths = entry.getKey();
                for ( Iterator<String> i = compileSourceRoots.iterator(); i.hasNext(); )
                {
                    if ( sourcePaths.length() > 0 )
                    {
                        sourcePaths.append( ',' );
                    }
                    sourcePaths.append( i.next() );
                }
            }
        }
        final String sourcePath = analyzer.getProperty( Analyzer.SOURCEPATH );
        if ( sourcePath != null )
        {
            if ( sourcePath.contains(MAVEN_SOURCES) || sourcePath.contains(MAVEN_TEST_RESOURCES) )
            {
                String combinedSource = StringUtils.replace( sourcePath, MAVEN_SOURCES, mavenSourcePaths.toString() );
                combinedSource = StringUtils.replace( combinedSource, MAVEN_TEST_SOURCES, mavenTestSourcePaths.toString() );
                if ( combinedSource.length() > 0 )
                {
                    analyzer.setProperty( Analyzer.SOURCEPATH, combinedSource );
                }
                else
                {
                    analyzer.unsetProperty( Analyzer.SOURCEPATH );
                }
            }
            else if ( mavenSourcePaths.length() > 0 )
            {
                log.warn( Analyzer.SOURCEPATH + ": overriding " + mavenSourcePaths + " with " + sourcePath + " (add "
                    + MAVEN_SOURCES + " if you want to include the maven sources)" );
            }
            else if ( mavenTestSourcePaths.length() > 0 )
            {
                log.warn( Analyzer.SOURCEPATH + ": overriding " + mavenTestSourcePaths + " with " + sourcePath + " (add "
                        + MAVEN_TEST_SOURCES + " if you want to include the maven test sources)" );
            }
        }
        else if ( mavenSourcePaths.length() > 0 )
        {
            analyzer.setProperty( Analyzer.SOURCEPATH, mavenSourcePaths.toString() );
        }
    }

    /**
     * Downgrade the message "Classes found in the wrong directory" to a warning. This allows the plugin
     * to process a multi-release JAR (see JEP 238, http://openjdk.java.net/jeps/238).
     * 
     * Note that the version-specific paths will NOT be visible at runtime nor processed by bnd for
     * imported packages etc. This will not be possible until a runtime solution for multi-release
     * JARs exists in OSGi. This fix only allows these JARs to be processed at all and to be usable on
     * Java 8 (and below), and also on Java 9 where the version-specific customizations are optional.
     */
    protected static void includeJava9Fixups(MavenProject currentProject, Analyzer analyzer)
    {
        final String classesInWrongDirError = "Classes found in the wrong directory";
        final String newFixup = "Classes found in the wrong directory;"
            + Analyzer.FIXUPMESSAGES_IS_DIRECTIVE + "="
            + Analyzer.FIXUPMESSAGES_IS_WARNING;

        String fixups = analyzer.getProperty(Analyzer.FIXUPMESSAGES);
        if (fixups != null && !fixups.isEmpty()) {
            if (!fixups.contains(classesInWrongDirError)) {
                fixups += "," + newFixup;
            }
        } else {
            fixups = newFixup;
        }
        analyzer.setProperty(Analyzer.FIXUPMESSAGES, fixups);
    }

    static class ClassPathItem {
        final String id;
        final File file;

        public ClassPathItem(String id, File file) {
            this.id = id;
            this.file = file;
        }
    }
}
