Package org.apache.sling.maven.projectsupport

Source Code of org.apache.sling.maven.projectsupport.AbstractUsingBundleListMojo

/*
* 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.sling.maven.projectsupport;

import static org.apache.sling.maven.projectsupport.BundleListUtils.interpolateProperties;
import static org.apache.sling.maven.projectsupport.BundleListUtils.readBundleList;

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Set;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.shared.filtering.MavenFileFilter;
import org.apache.maven.shared.filtering.MavenFilteringException;
import org.apache.maven.shared.filtering.PropertyUtils;
import org.apache.sling.maven.projectsupport.BundleListUtils.ArtifactDefinitionsCallback;
import org.apache.sling.maven.projectsupport.bundlelist.v1_0_0.BundleList;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.archiver.zip.ZipUnArchiver;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
import org.drools.KnowledgeBase;
import org.drools.KnowledgeBaseFactory;
import org.drools.builder.KnowledgeBuilder;
import org.drools.builder.KnowledgeBuilderError;
import org.drools.builder.KnowledgeBuilderFactory;
import org.drools.builder.ResourceType;
import org.drools.io.ResourceFactory;
import org.drools.runtime.StatefulKnowledgeSession;

public abstract class AbstractUsingBundleListMojo extends AbstractBundleListMojo {

    /**
     * JAR Packaging type.
     */
    protected static final String JAR = "jar";

    /**
     * WAR Packaging type.
     */
    protected static final String WAR = "war";

    protected static final String CONFIG_PATH_PREFIX = "resources/config";

    protected static final String BUNDLE_PATH_PREFIX = "resources/bundles";

    protected static boolean shouldCopy(File source, File dest) {
        if (!dest.exists()) {
            return true;
        }
        return source.lastModified() > dest.lastModified();
    }

    /**
     * The definition of the defaultBundleList artifact.
     *
     * @parameter
     */
    protected ArtifactDefinition defaultBundleList;

    /**
     * Any additional bundles to include in the project's bundles directory.
     *
     * @parameter
     */
    private ArtifactDefinition[] additionalBundles;

    private BundleList initializedBundleList;

    /**
     * Bundles which should be removed from the project's bundles directory.
     *
     * @parameter
     */
    private ArtifactDefinition[] bundleExclusions;

    /**
     * If true, include the default bundles.
     *
     * @parameter expression="${includeDefaultBundles}" default-value="true"
     */
    private boolean includeDefaultBundles;

    /**
     * @parameter
     */
    private File[] rewriteRuleFiles;

    /**
     * The list of tokens to include when copying configs
     * from partial bundle lists.
     *
     * @parameter default-value="**"
     */
    private String[] configIncludes;

    /**
     * The list of tokens to exclude when copying the configs
     * from partial bundle lists.
     *
     * @parameter
     */
    private String[] configExcludes;

    /**
     * The list of names to exclude when copying properties
     * from partial bundle lists.
     *
     * @parameter
     */
    private String[] propertiesExcludes;

    /**
     * @component
     */
    protected MavenFileFilter mavenFileFilter;

    /**
     * The zip unarchiver.
     *
     * @component role="org.codehaus.plexus.archiver.UnArchiver" roleHint="zip"
     */
    private ZipUnArchiver zipUnarchiver;

    private Properties slingProperties;

    private Properties slingWebappProperties;

    private Properties slingStandaloneProperties;

    private String slingBootstrapCommand;

    private String slingWebappBootstrapCommand;

    private String slingStandaloneBootstrapCommand;

    /**
     * @parameter default-value="${project.build.directory}/tmpBundleListconfig"
     */
    private File tmpOutputDir;

    /**
     * @parameter default-value="${project.build.directory}/tmpConfigDir"
     */
    private File tempConfigDir;

    private File overlayConfigDir;

    public final void execute() throws MojoFailureException, MojoExecutionException {
        try {
            initBundleList();
            extractConfigurations();
        } catch (MojoExecutionException e) {
            throw e;
        } catch (Exception e) {
            throw new MojoExecutionException("Unable to load dependency information from properties file.", e);
        }
        executeWithArtifacts();

    }

    @Override
    protected File getConfigDirectory() {
        if ( this.overlayConfigDir != null ) {
            return this.overlayConfigDir;
        }
        return super.getConfigDirectory();
    }

    /**
     * Execute the logic of the plugin after the default artifacts have been
     * initialized.
     */
    protected abstract void executeWithArtifacts() throws MojoExecutionException, MojoFailureException;

    protected BundleList getInitializedBundleList() {
        return initializedBundleList;
    }

    /**
     * Hook methods for subclasses to initialize any additional artifact
     * definitions.
     *
     * @param dependencies the dependency properties loaded from the JAR file
     */
    protected void initArtifactDefinitions(Properties dependencies) {
    }

    /**
     * Hook methods for subclasses to initialize the bundle list.
     */
    protected void initBundleList(BundleList bundleList) {
    }

    /**
     * Initialize the artifact definitions using defaults inside the plugin JAR.
     *
     * @throws IOException if the default properties can't be read
     * @throws XmlPullParserException
     * @throws MojoExecutionException
     */
    private final void initArtifactDefinitions() throws IOException {
        BundleListUtils.initArtifactDefinitions(getClass().getClassLoader(), new ArtifactDefinitionsCallback() {

            public void initArtifactDefinitions(Properties dependencies) {
                if (defaultBundleList == null) {
                    defaultBundleList = new ArtifactDefinition();
                }
                defaultBundleList.initDefaults(dependencies.getProperty("defaultBundleList"));

                AbstractUsingBundleListMojo.this.initArtifactDefinitions(dependencies);
            }
        });
    }

    private final void initBundleList() throws IOException, XmlPullParserException, MojoExecutionException {
        initArtifactDefinitions();
        if (BundleListUtils.isCurrentArtifact(project, defaultBundleList)) {
            initializedBundleList = readBundleList(bundleListFile);
        } else {
            initializedBundleList = new BundleList();
            if (includeDefaultBundles) {
                Artifact defBndListArtifact = getArtifact(defaultBundleList.getGroupId(),
                        defaultBundleList.getArtifactId(), defaultBundleList.getVersion(), defaultBundleList.getType(),
                        defaultBundleList.getClassifier());
                getLog().info("Using bundle list file from " + defBndListArtifact.getFile().getAbsolutePath());
                initializedBundleList = readBundleList(defBndListArtifact.getFile());
            }

            if (bundleListFile.exists()) {
                initializedBundleList.merge(readBundleList(bundleListFile));
            }
        }
        // add additional bundles
        if (additionalBundles != null) {
            for (ArtifactDefinition def : additionalBundles) {
                initializedBundleList.add(def.toBundleList());
            }
        }

        interpolateProperties(initializedBundleList, project, mavenSession);

        // check for partial bundle lists
        final Set<Artifact> dependencies = project.getDependencyArtifacts();
        for (Artifact artifact : dependencies) {
            if (PARTIAL.equals(artifact.getType())) {
                getLog().info(
                        String.format("Merging partial bundle list %s:%s:%s", artifact.getGroupId(),
                                artifact.getArtifactId(), artifact.getVersion()));
                initializedBundleList.merge(readBundleList(artifact.getFile()));
            }
        }

        // handle exclusions
        if (bundleExclusions != null) {
            for (ArtifactDefinition def : bundleExclusions) {
                initializedBundleList.remove(def.toBundleList(), false);
            }
        }

        initBundleList(initializedBundleList);

        interpolateProperties(initializedBundleList, project, mavenSession);

        rewriteBundleList(initializedBundleList);
    }

    private final void extractConfigurations() throws MojoExecutionException, IOException {
        final Set<Artifact> dependencies = project.getDependencyArtifacts();
        for (Artifact artifact : dependencies) {
            if (PARTIAL.equals(artifact.getType())) {
                extractConfiguration(artifact);
            }
        }
        // copy own config files
        if ( this.overlayConfigDir != null && super.getConfigDirectory().exists() ) {
            copyDirectory(super.getConfigDirectory(), this.overlayConfigDir, null, FileUtils.getDefaultExcludes());
        }
    }

    private void extractConfiguration(final Artifact artifact) throws MojoExecutionException, IOException {
        // check for configuration artifact
        Artifact cfgArtifact = null;
        try {
            cfgArtifact = getArtifact(artifact.getGroupId(),
                    artifact.getArtifactId(),
                    artifact.getVersion(),
                    AttachPartialBundleListMojo.CONFIG_TYPE,
                    AttachPartialBundleListMojo.CONFIG_CLASSIFIER);
        } catch (final MojoExecutionException ignore) {
            // we just ignore this
        }
        if ( cfgArtifact != null ) {
            getLog().info(
                    String.format("Merging settings from partial bundle list %s:%s:%s", cfgArtifact.getGroupId(),
                            cfgArtifact.getArtifactId(), cfgArtifact.getVersion()));

            // extract
            zipUnarchiver.setSourceFile(cfgArtifact.getFile());
            try {
                this.tmpOutputDir.mkdirs();
                zipUnarchiver.setDestDirectory(this.tmpOutputDir);
                zipUnarchiver.extract();

                final File slingDir = new File(this.tmpOutputDir, "sling");
                this.readSlingProperties(new File(slingDir, AttachPartialBundleListMojo.SLING_COMMON_PROPS), 0);
                this.readSlingProperties(new File(slingDir, AttachPartialBundleListMojo.SLING_WEBAPP_PROPS), 1);
                this.readSlingProperties(new File(slingDir, AttachPartialBundleListMojo.SLING_STANDALONE_PROPS), 2);
                this.readSlingBootstrap(new File(slingDir, AttachPartialBundleListMojo.SLING_COMMON_BOOTSTRAP), 0);
                this.readSlingBootstrap(new File(slingDir, AttachPartialBundleListMojo.SLING_WEBAPP_BOOTSTRAP), 1);
                this.readSlingBootstrap(new File(slingDir, AttachPartialBundleListMojo.SLING_STANDALONE_BOOTSTRAP), 2);

                // and now configurations
                final File configDir = new File(this.tmpOutputDir, "config");
                if ( configDir.exists() ) {
                    if ( this.overlayConfigDir == null ) {
                        this.tempConfigDir.mkdirs();
                        this.overlayConfigDir = this.tempConfigDir;
                    }
                    final String[] defaultExcludes = FileUtils.getDefaultExcludes();
                    String[] excludes;
                    if ( this.configExcludes != null ) {
                        excludes = new String[defaultExcludes.length + this.configExcludes.length];
                        System.arraycopy(defaultExcludes, 0, excludes, 0, defaultExcludes.length);
                        System.arraycopy(this.configExcludes, 0, excludes, defaultExcludes.length, this.configExcludes.length);
                    } else {
                        excludes = defaultExcludes;
                    }
                    String[] includes = null;
                    if ( this.configIncludes != null ) {
                        includes = this.configIncludes;
                    }
                    copyDirectory(configDir, this.overlayConfigDir,
                                    includes, excludes);
                }
            } catch (final ArchiverException ae) {
                throw new MojoExecutionException("Unable to extract configuration archive.",ae);
            } finally {
                // and delete at the end
                FileUtils.deleteDirectory(this.tmpOutputDir);
            }
        }
    }

    private void rewriteBundleList(BundleList bundleList) throws MojoExecutionException {
        if (rewriteRuleFiles != null) {
            KnowledgeBase knowledgeBase = createKnowledgeBase(rewriteRuleFiles);
            StatefulKnowledgeSession session = knowledgeBase.newStatefulKnowledgeSession();
            try {
                session.setGlobal("mavenSession", mavenSession);
                session.setGlobal("mavenProject", project);
                session.insert(bundleList);
                session.fireAllRules();
            } finally {
                session.dispose();
            }
        }
    }

    private KnowledgeBase createKnowledgeBase(File[] files) throws MojoExecutionException {
        KnowledgeBuilder builder = KnowledgeBuilderFactory.newKnowledgeBuilder();
        builder.add(ResourceFactory.newClassPathResource("drools-globals.drl", getClass()), ResourceType.DRL);
        for (File file : files) {
            getLog().info("Parsing rule file " + file.getAbsolutePath());
            builder.add(ResourceFactory.newFileResource(file), ResourceType.DRL);
        }
        if (builder.hasErrors()) {
            getLog().error("Rule errors:");
            for (KnowledgeBuilderError error : builder.getErrors()) {
                getLog().error(error.toString());
            }
            throw new MojoExecutionException("Unable to create rules. See log for details.");
        }

        KnowledgeBase base = KnowledgeBaseFactory.newKnowledgeBase();
        base.addKnowledgePackages(builder.getKnowledgePackages());
        return base;
    }

    private void copyProperties(final Properties source, final Properties dest) {
        final Enumeration<Object> keys = source.keys();
        while ( keys.hasMoreElements() ) {
            final Object key = keys.nextElement();
            dest.put(key, source.get(key));
        }
    }

    private void readSlingProperties(final File propsFile, final int mode) throws MojoExecutionException {
        if (propsFile.exists()) {
            File tmp = null;
            try {
                tmp = File.createTempFile("sling", "props");
                mavenFileFilter.copyFile(propsFile, tmp, true, project, Collections.EMPTY_LIST, true,
                        System.getProperty("file.encoding"), mavenSession);
                final Properties loadedProps = PropertyUtils.loadPropertyFile(tmp, null);
                if ( mode == 0 ) {
                    if ( this.slingProperties == null ) {
                        this.slingProperties = loadedProps;
                    } else {
                        this.copyProperties(loadedProps, this.slingProperties);
                    }
                    filterProperties(this.slingProperties);
                } else if ( mode == 1 ) {
                    if ( this.slingWebappProperties == null ) {
                        this.slingWebappProperties = loadedProps;
                    } else {
                        this.copyProperties(loadedProps, this.slingWebappProperties);
                    }
                    filterProperties(this.slingWebappProperties);
                } else {
                    if ( this.slingStandaloneProperties == null ) {
                        this.slingStandaloneProperties = loadedProps;
                    } else {
                        this.copyProperties(loadedProps, this.slingStandaloneProperties);
                    }
                    filterProperties(this.slingStandaloneProperties);
                }
            } catch (IOException e) {
                throw new MojoExecutionException("Unable to create filtered properties file", e);
            } catch (MavenFilteringException e) {
                throw new MojoExecutionException("Unable to create filtered properties file", e);
            } finally {
                if (tmp != null) {
                    tmp.delete();
                }
            }
        }
    }

    /**
     * Filter properties by removing excluded properties
     */
    private void filterProperties(final Properties props) {
        if ( this.propertiesExcludes != null ) {
            for(final String name : this.propertiesExcludes) {
                props.remove(name.trim());
            }
        }
    }

    protected Properties getSlingProperties(final boolean standalone) throws MojoExecutionException {
        readSlingProperties(this.commonSlingProps, 0);
        final Properties additionalProps = (standalone ? this.slingStandaloneProperties : this.slingWebappProperties);
        if ( this.slingProperties == null) {
            return additionalProps;
        }
        if ( additionalProps != null ) {
            final Properties combinedProps = new Properties();
            this.copyProperties(this.slingProperties, combinedProps);
            this.copyProperties(additionalProps, combinedProps);
            return combinedProps;
        }
        return this.slingProperties;
    }

    /**
     * Try to read the bootstrap command file
     * The filter is copied to a tmp location to apply filtering.
     * @throws MojoExecutionException
     */
    private void readSlingBootstrap(final File bootstrapFile, final int mode) throws MojoExecutionException {
        if (bootstrapFile.exists()) {
            File tmp = null;
            Reader reader = null;
            try {
                tmp = File.createTempFile("sling", "bootstrap");
                mavenFileFilter.copyFile(bootstrapFile, tmp, true, project, Collections.EMPTY_LIST, true,
                        System.getProperty("file.encoding"), mavenSession);
                reader = new FileReader(tmp);
                final StringBuilder sb = new StringBuilder();
                if ( mode == 0 ) {
                    if ( this.slingBootstrapCommand != null ) {
                        sb.append(this.slingBootstrapCommand);
                    }
                } else if ( mode == 1 ) {
                    if ( this.slingWebappBootstrapCommand != null ) {
                        sb.append(this.slingWebappBootstrapCommand);
                    }
                } else {
                    if ( this.slingStandaloneBootstrapCommand != null ) {
                        sb.append(this.slingStandaloneBootstrapCommand);
                    }
                }
                final char[] buffer = new char[2048];
                int l;
                while ( (l = reader.read(buffer, 0, buffer.length) ) != -1 ) {
                    sb.append(buffer, 0, l);
                }
                sb.append('\n');
                if ( mode == 0 ) {
                    this.slingBootstrapCommand = sb.toString();
                } else if ( mode == 1 ) {
                    this.slingWebappBootstrapCommand = sb.toString();
                } else {
                    this.slingStandaloneBootstrapCommand = sb.toString();
                }
            } catch (final IOException e) {
                throw new MojoExecutionException("Unable to create filtered bootstrap file", e);
            } catch (final MavenFilteringException e) {
                throw new MojoExecutionException("Unable to create filtered bootstrap file", e);
            } finally {
                if (tmp != null) {
                    tmp.delete();
                }
                if ( reader != null ) {
                    try {
                        reader.close();
                    } catch (final IOException ignore) {}
                }
            }
        }
    }

    /**
     * Try to read the bootstrap command file and return its content
     * The filter is copied to a tmp location to apply filtering.
     * @return The contents are <code>null</code>
     * @throws MojoExecutionException
     */
    protected String getSlingBootstrap(final boolean standalone) throws MojoExecutionException {
        this.readSlingBootstrap(this.commonSlingBootstrap, 0);
        final String addCmds = (standalone ? this.slingStandaloneBootstrapCommand : this.slingWebappBootstrapCommand);
        if ( this.slingBootstrapCommand == null ) {
            return addCmds;
        }
        if ( addCmds != null ) {
            final StringBuilder builder = new StringBuilder(this.slingBootstrapCommand);
            builder.append('\n');
            builder.append(addCmds);
            return builder.toString();
        }
        return this.slingBootstrapCommand;
    }
}
TOP

Related Classes of org.apache.sling.maven.projectsupport.AbstractUsingBundleListMojo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.