Package org.jnode.build

Source Code of org.jnode.build.PluginTask

/*
* $Id$
*
* Copyright (C) 2003-2014 JNode.org
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; If not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

package org.jnode.build;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.taskdefs.Jar;
import org.apache.tools.ant.taskdefs.Manifest;
import org.apache.tools.ant.taskdefs.ManifestException;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.ZipFileSet;
import org.apache.tools.ant.util.FileUtils;
import org.jnode.build.packager.PluginBuilder;
import org.jnode.plugin.Library;
import org.jnode.plugin.PluginDescriptor;
import org.jnode.plugin.Runtime;

/**
* @author Ewout Prangsma (epr@users.sourceforge.net)
*/
public class PluginTask extends AbstractPluginTask {

    private LinkedList<ZipFileSet> descriptorSets = new LinkedList<ZipFileSet>();
    private File todir;
    private File tmpDir = new File(System.getProperty("java.io.tmpdir"));

    private PluginBuilder packager;

    public ZipFileSet createDescriptors() {
        final ZipFileSet fs = new ZipFileSet();
        descriptorSets.add(fs);
        return fs;
    }

    /**
     * @throws BuildException
     * @see org.apache.tools.ant.Task#execute()
     */
    public void execute() throws BuildException {

        if (descriptorSets.isEmpty()) {
            throw new BuildException("At at least 1 descriptorset element");
        }
        if (todir == null) {
            throw new BuildException("The todir attribute must be set");
        }
        if (getPluginDir() == null) {
            throw new BuildException("The pluginDir attribute must be set");
        }
        if (!todir.exists()) {
            todir.mkdirs();
        } else if (!todir.isDirectory()) {
            throw new BuildException("todir must be a directory");
        }

        int max_thread_count = 10;
        int max_plugin_count = 500;

        final AtomicBoolean failure = new AtomicBoolean(false);
        ThreadPoolExecutor executor = new ThreadPoolExecutor(max_thread_count, max_thread_count, 60, TimeUnit.SECONDS,
            new ArrayBlockingQueue<Runnable>(max_plugin_count)) {
            @Override
            protected void afterExecute(Runnable r, Throwable t) {
                if (t != null) {
                    failure.set(true);
                }
            }
        };

        final Map<String, File> descriptors = new HashMap<String, File>();
        for (FileSet fs : descriptorSets) {
            final DirectoryScanner ds = fs.getDirectoryScanner(getProject());
            final String[] files = ds.getIncludedFiles();
            for (final String file : files) {
                executor.execute(new Runnable() {
                    public void run() {
                        buildPlugin(descriptors, new File(ds.getBasedir(), file));
                    }
                });
            }
        }

        if (packager != null) {
            packager.execute(executor, descriptors);
        }

        executor.shutdown();
        try {
            executor.awaitTermination(10, TimeUnit.MINUTES);
        } catch (InterruptedException ie) {
            throw new RuntimeException("Building plugins interrupted");
        }

        if (failure.get()) {
            throw new RuntimeException("At least one plugin task failed : see above errors");
        }

        if (packager != null) {
            // that must be called after completion of all plugin tasks
            packager.finish();
        }
    }

    /**
     * @param descriptors map of fullPluginId to File descriptor
     * @param descriptor  the plugin descriptor XML
     * @throws BuildException on failure
     */
    public void buildPlugin(Map<String, File> descriptors, File descriptor) throws BuildException {
        final PluginDescriptor descr = readDescriptor(descriptor);

        final String fullId = descr.getId() + "_" + descr.getVersion();
        if (descriptors.containsKey(fullId)) {
            File otherDesc = descriptors.get(fullId);
            throw new BuildException("Same id(" + fullId + ") for 2 plugins: " + otherDesc + ", " + descriptor);
        }
        descriptors.put(fullId, descriptor);

        File destFile = new File(todir, fullId + ".jar");

        // Check if we have to do something
        if (isUpToDate(descriptor, descr, destFile))
            return;

        final Jar jarTask = new Jar();
        jarTask.setProject(getProject());
        jarTask.setTaskName(getTaskName());
        jarTask.setDestFile(destFile);
        jarTask.setCompress(false);

        // Add plugin.xml
        final File tmpPluginDir;
        final File tmpPluginXmlFile;
        try {
            tmpPluginDir = new File(tmpDir, "jnode-plugins" + File.separator + fullId);
            tmpPluginDir.mkdirs();
            tmpPluginXmlFile = new File(tmpPluginDir, "plugin.xml");
            FileUtils.newFileUtils().copyFile(descriptor, tmpPluginXmlFile);
            FileSet fs = new FileSet();
            fs.setDir(tmpPluginDir);
            fs.createInclude().setName("plugin.xml");
            jarTask.addFileset(fs);
        } catch (IOException ex) {
            throw new BuildException(ex);
        }

        // Create manifest
        try {
            jarTask.addConfiguredManifest(createManifest(descr));
        } catch (ManifestException ex) {
            throw new BuildException(ex);
        }

        // Add runtime resources
        final Runtime rt = descr.getRuntime();
        if (rt != null) {
            final HashMap<File, ZipFileSet> fileSets = new HashMap<File, ZipFileSet>();
            final Library[] libs = rt.getLibraries();
            for (int l = 0; l < libs.length; l++) {
                processLibrary(jarTask, libs[l], fileSets, getPluginDir());
            }
        }

        jarTask.execute();
    }

    /**
     * Is the given destination file up to date with respect to it's sources?
     *
     * @param descriptor
     * @param descr
     * @param destFile
     * @return
     */
    private boolean isUpToDate(File descriptor, PluginDescriptor descr, File destFile) {
        if (!destFile.exists())
            return false;
        long destLastModified = destFile.lastModified();

        if (descriptor.lastModified() > destLastModified)
            return false;

        // Check runtime resources
        final Runtime rt = descr.getRuntime();
        if (rt != null) {
            for (Library lib : rt.getLibraries()) {
                File libFile = getLibraryFile(lib, getPluginDir());
                if (libFile.lastModified() > destLastModified)
                    return false;
            }
        }

        return true;
    }

    /**
     * Create a manifest for the given descriptor.
     *
     * @param descr plugin descriptor object
     * @return the manifest
     * @throws ManifestException
     */
    protected Manifest createManifest(PluginDescriptor descr) throws ManifestException {
        Manifest mf = new Manifest();

        mf.addConfiguredAttribute(new Manifest.Attribute("Bundle-SymbolicName", descr.getId()));
        mf.addConfiguredAttribute(new Manifest.Attribute("Bundle-ManifestVersion", "2"));
        mf.addConfiguredAttribute(new Manifest.Attribute("Bundle-Version", descr.getVersion().toString()));

        return mf;
    }

    /**
     * @return The destination directory
     */
    public final File getTodir() {
        return this.todir;
    }

    /**
     * @param todir
     */
    public final void setTodir(File todir) {
        this.todir = todir;
    }

    /**
     * @return The temp directory
     */
    public final File getTmpDir() {
        return this.tmpDir;
    }

    /**
     * @param tmpDir
     */
    public final void setTmpDir(File tmpDir) {
        this.tmpDir = tmpDir;
    }

    public PluginBuilder createPackager() {
        packager = new PluginBuilder(this);
        return packager;
    }
}
TOP

Related Classes of org.jnode.build.PluginTask

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.