Package org.jnode.build

Source Code of org.jnode.build.PluginList

/*
* $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.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;

import org.apache.tools.ant.taskdefs.Manifest;
import org.apache.tools.ant.taskdefs.ManifestException;
import org.jnode.nanoxml.XMLElement;
import org.jnode.plugin.PluginException;

/**
* @author epr
*/
public final class PluginList {

    private final List<URL> descrList;

    private final List<URL> pluginList;

    private final String name;
   
    private Manifest manifest;

    private List<PluginList> includes = new ArrayList<PluginList>();

    private final File defaultDir;

    public PluginList(File file, File defaultDir, String targetArch)
        throws PluginException, MalformedURLException {
        this.defaultDir = defaultDir;
        descrList = new ArrayList<URL>();
        pluginList = new ArrayList<URL>();
        final XMLElement root = new XMLElement(new Hashtable<Object, Object>(), true, false);
        try {
            final FileReader r = new FileReader(file);
            try {
                root.parseFromReader(r);
            } finally {
                r.close();
            }
        } catch (IOException ex) {
            throw new PluginException(ex);
        }
        if (!root.getName().equals("plugin-list")) {
            throw new PluginException("plugin-list element expected");
        }

        this.name = (String) root.getAttribute("name");
        if (name == null) {
            throw new PluginException("name attribute is missing in " + file);
        }

        for (Iterator<?> i = root.getChildren().iterator(); i.hasNext();) {

            final XMLElement e = (XMLElement) i.next();
            if (e.getName().equals("plugin")) {
                final String id = e.getStringAttribute("id");

                if (id == null) {
                    throw new PluginException("id attribute expected on "
                        + e.getName());
                }
               
                // version attribute is optional
                // if not specified, then the latest version found will be used.
                final String version = e.getStringAttribute("version");

                addPlugin(descrList, pluginList, id, version);
            } else if (e.getName().equals("manifest")) {
                manifest = parseManifest(e);
            } else if (e.getName().equals("include")) {
                parseInclude(e, file.getParentFile(), defaultDir, targetArch,
                    descrList, pluginList);
            } else {
                throw new PluginException("Unknown element " + e.getName());
            }
        }
    }
   
    /**
     *
     * @param id
     * @param version optional
     * @throws MalformedURLException
     * @throws PluginException
     */
    public void addPlugin(String id, String version) throws MalformedURLException, PluginException {
        addPlugin(descrList, pluginList, id, version);
    }
   
    /**
     *
     * @param descrList
     * @param pluginList
     * @param id
     * @param version optional parameter
     * @throws MalformedURLException
     * @throws PluginException
     */
    private void addPlugin(List<URL> descrList, List<URL> pluginList, String id, String version)
        throws MalformedURLException, PluginException {
        final File f = findPlugin(defaultDir, id, version);
        final URL pluginUrl = f.toURI().toURL()// ensure proper escaping ...
        final URL descrUrl = new URL("jar:" + pluginUrl + "!/plugin.xml");
       
        if (pluginList.contains(pluginUrl)) {
            String versionStr = (version == null) ? "unspecified" : version;
            throw new PluginException("can't use the same id(" + id +
                    ") and version(" + versionStr + ") for multiple plugins");
        }

        descrList.add(descrUrl);
        pluginList.add(pluginUrl);
    }

    private File findPlugin(File dir, final String id, String version) {
        // System.out.println("Find " + id + " in " + dir);
        final String begin = id + "_";
        final String end = ".jar";
       
        String[] names = dir.list(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.startsWith(begin) && name.endsWith(end);
            }
        });

        if (names.length == 0) {
            throw new IllegalArgumentException("Cannot find plugin " + id
                + " in " + dir + " for list " + this.name);
        }

        String filename = null;
        if (version != null) {
            // version specified, try to find it
            for (String name : names) {
                String v = name.substring(begin.length(), name.length() - end.length());
                if (version.equals(v)) {
                    filename = name; // found exact version
                    break;
                }
            }           
        }
       
        if (filename == null) {
            // by default, take the latest version
            filename = names[names.length - 1];
        }
       
        return new File(dir, filename);
    }

    private Manifest parseManifest(XMLElement me) throws PluginException {
        Manifest mf = this.manifest;
        if (mf == null) {
            mf = new Manifest();
        }
        for (Iterator<?> i = me.getChildren().iterator(); i.hasNext();) {
            final XMLElement e = (XMLElement) i.next();
            if (e.getName().equals("attribute")) {
                final String k = e.getStringAttribute("key");
                final String v = e.getStringAttribute("value");
                try {
                    mf.addConfiguredAttribute(new Manifest.Attribute(k, v));
                } catch (ManifestException ex) {
                    throw new PluginException("Error in manifest", ex);
                }
            } else {
                throw new PluginException("Unknown element " + e.getName());
            }
        }
        return mf;
    }

    private void parseInclude(XMLElement e, File curDir, File defaultDir,
                              String targetArch, List<URL> descrList, List<URL> pluginList)
        throws MalformedURLException, PluginException {
        File file = new File(e.getStringAttribute("file"));
        if (!file.isAbsolute()) {
            file = new File(curDir, file.getPath());
        }

        final PluginList inc = new PluginList(file, defaultDir, targetArch);
        includes.add(inc);

        if (this.manifest == null) {
            this.manifest = inc.manifest;
        } else if (inc.manifest != null) {
            try {
                final Manifest merged = new Manifest();
                merged.merge(inc.manifest);
                merged.merge(this.manifest);
                this.manifest = merged;
            } catch (ManifestException ex) {
                throw new PluginException(ex);
            }
        }

        descrList.addAll(inc.descrList);
        pluginList.addAll(inc.pluginList);
    }

    /**
     * Gets the maximum last modification date of all URL's.
     *
     * @return last modification date
     * @throws IOException
     */
    public long lastModified() throws IOException {
        long max = 0;
        for (URL url : descrList) {
            final URLConnection conn2 = url.openConnection();
            max = Math.max(max, conn2.getLastModified());
        }
        for (PluginList inc : includes) {
            max = Math.max(max, inc.lastModified());
        }
        return max;
    }

    /**
     * Gets all URL's to plugin descriptors.
     *
     * @return URL[]
     */
    public URL[] getDescriptorUrlList() {
        return descrList.toArray(new URL[descrList.size()]);
    }

    /**
     * Gets all URL's to the plugin files (jar format).
     *
     * @return URL[]
     */
    public URL[] getPluginList() {
        return pluginList.toArray(new URL[pluginList.size()]);
    }

    /**
     * @return Returns the manifest.
     */
    public final Manifest getManifest() {
        return this.manifest;
    }

    /**
     * @return Returns the name.
     */
    public final String getName() {
        return name;
    }

    /**
     * Create an URL to a plugin with a given id and version.
     */
    public final URL createPluginURL(String id, String version) {
        try {
            // The toURI().toURL() pattern is to ensure that funky characters
            // in the plugin pathname are properly escaped in the URL
            return findPlugin(defaultDir, id, version).toURI().toURL();
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }
}
TOP

Related Classes of org.jnode.build.PluginList

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.