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