All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gephi.maven.Migrate Maven / Gradle / Ivy

There is a newer version: 1.3.4
Show newest version
/*
 * Copyright 2015 Gephi Consortium
 *
 * Licensed 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.gephi.maven;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.tools.ant.taskdefs.Manifest;
import org.apache.tools.ant.taskdefs.Manifest.Section;
import org.apache.tools.ant.taskdefs.ManifestException;
import org.codehaus.plexus.util.DirectoryScanner;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.IOUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 * Migrate ant-based plugin.
 */
@Mojo(name = "migrate", aggregator = true)
public class Migrate extends AbstractMojo {

    /**
     * The Maven project.
     */
    @Parameter(required = true, readonly = true, property = "project")
    private MavenProject project;

    //Set of Gephi + Netbeans dependencies
    private Set gephiDependencies;

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        File baseDir = project.getBasedir();

        //Info
        getLog().info("Start migrating ant-based plugin folder.");

        //Root pom file
        File pomFile = new File(baseDir, "pom.xml");
        if (!pomFile.exists()) {
            throw new MojoExecutionException("The 'pom.xml' file doesn' exist at '" + pomFile.getAbsolutePath() + "'");
        }

        //Get gephi.version
        String gephiVersion = project.getProperties().getProperty("gephi.version");
        if (gephiVersion == null) {
            throw new MojoExecutionException("Can't obtain gephi version number");
        }
        getLog().info("Gephi version is defined as '" + gephiVersion + "'");

        //Get modules folder
        List folders = collectFolders();
        if (folders.isEmpty()) {
            throw new MojoExecutionException("No plugin modules have been found this folder");
        }
        getLog().info("Found " + folders.size() + " modules to migrate:");
        for (String moduleStr : folders) {
            getLog().info("  '" + moduleStr + "' will be migrated to 'modules/" + moduleStr + "'");
        }

        //Collect modules data
        Map foldersMetadata = new HashMap();
        for (String moduleFolder : folders) {
            ProjectMetadata projectMetadata = new ProjectMetadata();
            File folder = new File(baseDir, moduleFolder);

            //Check nbproject
            File nbProjectFolder = checkNbproject(folder);

            //Process project.xml
            File projectXMLFile = new File(nbProjectFolder, "project.xml");
            if (!projectXMLFile.exists()) {
                throw new MojoExecutionException("The 'project.xml' file can't be found at " + projectXMLFile.getAbsolutePath());
            }
            projectMetadata.codeNameBase = collectCodeName(projectXMLFile);
            getLog().debug("Module: '" + moduleFolder + "' has code name '" + projectMetadata.codeNameBase + "'");

            //Process dependencies
            projectMetadata.dependencies = collectDependencies(projectXMLFile, moduleFolder);

            //Collect public packages
            projectMetadata.publicPackages = collectPublicPackages(projectXMLFile);

            //Collect metadata
            collectManifest(folder, projectMetadata);

            //Collect project props
            collectProjectProperties(nbProjectFolder, projectMetadata);

            foldersMetadata.put(moduleFolder, projectMetadata);
        }

        //Generate
        for (Map.Entry entry : foldersMetadata.entrySet()) {
            String folder = entry.getKey();
            ProjectMetadata metadata = entry.getValue();

            //Create folder (if needed)
            File pluginFolder = new File(baseDir, "modules" + File.separator + folder);
            if (pluginFolder.exists()) {
                try {
                    getLog().warn("The plugin folder 'modules" + File.separator + folder + "' already exists, the configuration will be overriden");
                    FileUtils.deleteDirectory(pluginFolder);
                    getLog().debug("Deleted folder '" + pluginFolder.getAbsolutePath() + "'");
                } catch (IOException ex) {
                    throw new MojoExecutionException("Error while deleting previous '" + folder + "' directory", ex);
                }
            }
            GenerateUtils.createFolder(new File(baseDir, "modules" + File.separator + folder), getLog());

            //Get sourcode
            String sourceCodeUrl = MetadataUtils.getSourceCodeUrlFromGit(project, getLog());
            getLog().debug("Obtained source code url from Git: " + sourceCodeUrl);

            // Compute org and artifact
            String org = metadata.codeNameBase;
            String artifact = metadata.codeNameBase;
            if (org.contains(".")) {
                artifact = org.substring(org.lastIndexOf(".") + 1);
                org = org.substring(0, org.lastIndexOf("."));
            }

            //License
            String licenseFile = null;
            String license = null;
            if (metadata.licenseFile != null) {
                File file = new File(baseDir, folder + File.separator + metadata.licenseFile.replace('/', File.separatorChar));
                if (file.exists()) {
                    try {
                        File dest = new File(pluginFolder, file.getName());
                        FileUtils.copyFile(file, dest);
                        licenseFile = dest.getName();
                        license = licenseFile.contains(".") ? licenseFile.substring(0, licenseFile.lastIndexOf('.')) : licenseFile;
                    } catch (IOException ex) {
                        getLog().error("Error while copying license file for module'" + folder + "'", ex);
                    }
                }
            }

            //Author
            if (metadata.author == null) {
                metadata.author = "Unknown";
            }

            //Create pom.xml
            File modulePomFile = new File(pluginFolder, "pom.xml");
            GenerateUtils.createTopPomFile(modulePomFile, gephiVersion, org, artifact, "1.0.0", folder, metadata.author, null, null, license, licenseFile, sourceCodeUrl, metadata.homepageUrl);
            getLog().debug("Created 'pom.xml' file at '" + pluginFolder.getAbsolutePath() + "'");

            //Insert deps
            insertDependencies(modulePomFile, metadata.dependencies);
            getLog().debug("Inserted " + metadata.dependencies.size() + " dependencies into 'pom.xml'");

            //Insert public packages
            if (!metadata.publicPackages.isEmpty()) {
                insertPublicPackages(modulePomFile, metadata.publicPackages);
                getLog().debug("Inserted " + metadata.publicPackages.size() + " public packages into 'pom.xml'");
            }

            //Create nbm, java and resources in src/main folder
            File srcMain = GenerateUtils.createFolder(new File(pluginFolder, "src" + File.separator + "main"), getLog());
            File nbmFolder = GenerateUtils.createFolder(new File(srcMain, "nbm"), getLog());
            File javaFolder = new File(srcMain, "java");
            File resourcesFolder = new File(srcMain, "resources");
            GenerateUtils.createFolder(javaFolder, getLog());
            GenerateUtils.createFolder(resourcesFolder, getLog());

            //Copy source code
            File srcFolder = new File(folder, "src");
            if (srcFolder.exists()) {
                try {
                    String[] pattern = new String[]{"**\\*.java", "**\\*.form"};
                    copyFiles(srcFolder, javaFolder, pattern, null);
                    getLog().debug("Copied source folders to '" + javaFolder.getAbsolutePath() + "'");
                    copyFiles(srcFolder, resourcesFolder, null, pattern);
                    getLog().debug("Copied resources folders to '" + resourcesFolder.getAbsolutePath() + "'");
                } catch (IOException e) {
                    throw new MojoExecutionException("Error while copying source files", e);
                }
            } else {
                getLog().warn("The 'src' folder at '" + srcFolder.getAbsolutePath() + "' doesn't exists");
            }

            //Manifest
            if (metadata.category == null) {
                metadata.category = "Other Category";
            }

            //Create manifest
            if (metadata.localizingBundle != null) {
                GenerateUtils.createManifest(new File(nbmFolder, "manifest.mf"), metadata.localizingBundle);
            } else {
                GenerateUtils.createManifest(new File(nbmFolder, "manifest.mf"), metadata.brandingName, metadata.shortDescription, metadata.longDescription, metadata.category);
            }
            getLog().debug("Created 'manifest.mf' file at '" + nbmFolder.getAbsolutePath() + "'");

            //Create img folder
            GenerateUtils.createFolder(new File(pluginFolder, "src" + File.separator + "img"), getLog());

            //Add module to pom
            GenerateUtils.addModuleToPom(pomFile, folder, getLog());
            getLog().debug("Inserted '" + folder + "' into the list of modules in 'pom.xml'");
        }
    }

    /**
     * Collect project properties in project.properties file.
     *
     * @param nbProjectFolder nbproject folder
     * @param projectMetadata project metadata
     * @throws MojoExecutionException if an error occurs
     */
    private void collectProjectProperties(File nbProjectFolder, ProjectMetadata projectMetadata) throws MojoExecutionException {
        File projectPropertiesFile = new File(nbProjectFolder, "project.properties");
        if (!projectPropertiesFile.exists()) {
            throw new MojoExecutionException("The 'project.properties' can't be found in '" + nbProjectFolder.getAbsolutePath() + "'");
        }
        Properties prop = new Properties();
        FileReader bundleReader = null;
        try {
            bundleReader = new FileReader(projectPropertiesFile);
            prop.load(bundleReader);
            projectMetadata.homepageUrl = prop.getProperty("nbm.homepage", null);
            projectMetadata.author = prop.getProperty("nbm.module.author", null);
            projectMetadata.licenseFile = prop.getProperty("license.file", null);
        } catch (IOException e) {
            throw new MojoExecutionException("Error while reading '" + projectPropertiesFile.getAbsolutePath() + "'", e);
        } finally {
            if (bundleReader != null) {
                try {
                    bundleReader.close();
                } catch (IOException ex) {
                }
            }
        }
    }

    /**
     * Collect branding name, short description, long description and category
     * from manifest file.
     *
     * @param folder module folder
     * @param projectMetadata project metadata
     * @throws MojoExecutionException if an error occurs
     */
    private void collectManifest(File folder, ProjectMetadata projectMetadata) throws MojoExecutionException {
        File manifestFile = new File(folder, "manifest.mf");
        if (!manifestFile.exists()) {
            throw new MojoExecutionException("The 'manifest.mf' can't be found in '" + folder.getAbsolutePath() + "'");
        }
        // Read manifest
        Manifest manifest = null;
        Reader reader = null;
        try {
            reader = new InputStreamReader(new FileInputStream(manifestFile));
            manifest = new Manifest(reader);
        } catch (IOException exc) {
            throw new MojoExecutionException("Error reading manifest at " + manifestFile, exc);
        } catch (ManifestException ex) {
            throw new MojoExecutionException("Error reading manifest at " + manifestFile, ex);
        } finally {
            IOUtil.close(reader);
        }

        // Get section
        Section section = null;
        if (manifest == null) {
            throw new MojoExecutionException("The manifest is malformed at '" + manifestFile.getAbsolutePath() + "'");
        } else {
            section = manifest.getMainSection();
        }

        //Metadata
        if (section.getAttributeValue("OpenIDE-Module-Localizing-Bundle") != null) {
            projectMetadata.localizingBundle = section.getAttributeValue("OpenIDE-Module-Localizing-Bundle");
        } else {
            projectMetadata.brandingName = section.getAttributeValue("OpenIDE-Module-Name");
            projectMetadata.shortDescription = section.getAttributeValue("OpenIDE-Module-Short-Description");
            projectMetadata.longDescription = section.getAttributeValue("OpenIDE-Module-Long-Description");
            projectMetadata.category = section.getAttributeValue("OpenIDE-Module-Display-Category");
        }
    }

    /**
     * Checks the given folder has a nbproject folder.
     *
     * @param folder folder to check
     * @return the found nbproject folder
     * @throws MojoExecutionException if an error occurs
     */
    private File checkNbproject(File folder) throws MojoExecutionException {
        File result = new File(folder, "nbproject");
        if (!result.exists()) {
            throw new MojoExecutionException("The 'nbproject' can't be found in '" + folder.getAbsolutePath() + "'");
        }
        return result;
    }

    /**
     * Collect list of module folders. A module folder is recognized based on
     * whether it has a nbproject folder.
     *
     * @return list of folders
     * @throws MojoExecutionException if an error occurs
     */
    private List collectFolders() throws MojoExecutionException {
        List result = new ArrayList();
        for (File child : project.getBasedir().listFiles()) {
            if (child.isDirectory() && new File(child, "nbproject").exists()) {
                result.add(child.getName());
                getLog().debug("Found module folder '" + child.getAbsolutePath() + "'");
            }
        }
        return result;
    }

    /**
     * Collect list of public packages from project.xml.
     *
     * @param projectXMLFile project xml file
     * @return list of public packages
     * @throws MojoExecutionException if an error occurs
     */
    private List collectPublicPackages(File projectXMLFile) throws MojoExecutionException {
        return getStringsFromXML(projectXMLFile, "/project/configuration/data/public-packages/package/text()");
    }

    /**
     * Collect dependencies from the project.xml file.
     * 

* Only gephi dependencies defined in modules/pom.xml are kept. * * @param projectXMLFile project.xml dependencies * @param moduleName name of module * @return set of dependencies * @throws MojoExecutionException if an error occurs */ private Set collectDependencies(File projectXMLFile, String moduleName) throws MojoExecutionException { if (gephiDependencies == null) { //Collect Gephi dependencies gephiDependencies = collectGephiDependencies(); getLog().debug(gephiDependencies.size() + " dependencies collected from 'modules/pom.xml'"); } Set result = new HashSet(); List deps = getStringsFromXML(projectXMLFile, "/project/configuration/data/module-dependencies/dependency/code-name-base/text()"); getLog().debug(deps.size() + " dependencies found in '" + projectXMLFile.getAbsolutePath() + "'"); for (String dep : deps) { Dependency dependency = null; if (dep.startsWith("org.gephi")) { String artifactId = dep.substring("org.gephi.".length()).replace('.', '-'); dependency = new Dependency("org.gephi", artifactId); } else if (dep.startsWith("org.openide")) { dependency = new Dependency("org.netbeans.api", dep.replace('.', '-')); } else if (dep.startsWith("org.netbeans")) { dependency = new Dependency("org.netbeans.api", dep.replace('.', '-')); } if (dependency != null && gephiDependencies.contains(dependency)) { getLog().debug("Found dependency '" + dependency + "' in '" + moduleName + "'"); result.add(dependency); } else { getLog().warn("The '" + dep + "' dependency in '" + moduleName + "' couldn't be migrated, please add it manually in 'modules/" + moduleName + "'"); } } return result; } /** * Collect the code-name in the project.xml file. * * @param projectXMLFile project.xml file * @return code name * @throws MojoExecutionException if an error occurs */ private String collectCodeName(File projectXMLFile) throws MojoExecutionException { return getStringFromXML(projectXMLFile, "/project/configuration/data/code-name-base/text()"); } /** * Execute XPath query on the given XML file and retrieve the * singular text value. * * @param file xml file * @param path xpath query * @return text value * @throws MojoExecutionException if an error occurs */ private String getStringFromXML(File file, String path) throws MojoExecutionException { NodeList nl = getNodeListFromXml(file, path); if (nl.getLength() != 1) { throw new MojoExecutionException("The expected number of items is 1, but " + nl.getLength() + " was found"); } Node node = nl.item(0); return node.getTextContent(); } /** * Execute XPath query on the given XML file and return the list of * text values. * * @param file xml file * @param path xpath query * @return list of text values * @throws MojoExecutionException if an error occurs */ private List getStringsFromXML(File file, String path) throws MojoExecutionException { NodeList nl = getNodeListFromXml(file, path); List result = new ArrayList(); for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); result.add(node.getTextContent()); } return result; } /** * Execute XPath query on the given XML file and return the list of * nodes. * * @param file xml file * @param path xpath query * @return list of nodes * @throws MojoExecutionException if an error occurs */ private NodeList getNodeListFromXml(File file, String path) throws MojoExecutionException { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); Document doc = builder.parse(file); XPathFactory xPathfactory = XPathFactory.newInstance(); XPath xpath = xPathfactory.newXPath(); XPathExpression expr = xpath.compile(path); NodeList nl = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); return nl; } catch (Exception ex) { throw new MojoExecutionException("Error while reading XML file '" + file.getAbsolutePath() + "' with XPath='" + path + "'", ex); } } /** * Inspect the modules/pom.xml to collect all the gephi and * netbeans dependencies in the parent pom. *

* These dependencies are the set plugins can use. * * @return set of dependencies * @throws MojoExecutionException if an error occurs */ private Set collectGephiDependencies() throws MojoExecutionException { Set result = new HashSet(); File modulesDir = new File(project.getBasedir(), "modules"); if (!modulesDir.exists()) { throw new MojoExecutionException("The 'modules' folder doesn't exists at '" + modulesDir + "'"); } File pomFile = new File(modulesDir, "pom.xml"); if (!pomFile.exists()) { throw new MojoExecutionException("The 'pom.xml' file doesn't exists at '" + pomFile + "'"); } NodeList nl = getNodeListFromXml(pomFile, "/project/dependencyManagement/dependencies/dependency"); for (int i = 0; i < nl.getLength(); i++) { String groupId = null, artifactId = null; Node n = nl.item(i); NodeList children = n.getChildNodes(); for (int j = 0; j < children.getLength(); j++) { Node m = children.item(j); if (m.getNodeName().equals("groupId")) { groupId = m.getTextContent(); } else if (m.getNodeName().equals("artifactId")) { artifactId = m.getTextContent(); } } if (groupId != null && artifactId != null) { if ("${project.groupId}".equals(groupId)) { groupId = "org.gephi"; } result.add(new Dependency(groupId, artifactId)); getLog().debug("Found dependency groupId=" + groupId + " artifactId=" + artifactId); } } return result; } private void insertDependencies(File xmlFile, Set dependencies) throws MojoExecutionException { try { Document doc = parseXMLDocument(xmlFile); XPathFactory xPathfactory = XPathFactory.newInstance(); XPath xpath = xPathfactory.newXPath(); XPathExpression expr = xpath.compile("/project/dependencies"); NodeList nodes = (NodeList) expr.evaluate(doc, XPathConstants.NODESET); for (Dependency d : dependencies) { Element dep = doc.createElement("dependency"); Element group = doc.createElement("groupId"); Element artifact = doc.createElement("artifactId"); group.appendChild(doc.createTextNode(d.groupId)); artifact.appendChild(doc.createTextNode(d.artifactId)); dep.appendChild(group); dep.appendChild(artifact); nodes.item(0).appendChild(dep); } FileWriter writer = new FileWriter(xmlFile); StreamResult result = new StreamResult(writer); Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); transformer.transform(new DOMSource(doc), result); writer.close(); } catch (Exception e) { throw new MojoExecutionException("Error while inserting dependencies in XML document '" + xmlFile + "'", e); } } private void insertPublicPackages(File xmlFile, List packages) throws MojoExecutionException { try { Document doc = parseXMLDocument(xmlFile); XPathFactory xPathfactory = XPathFactory.newInstance(); XPath xpath = xPathfactory.newXPath(); XPathExpression expr = xpath.compile("/project/build/plugins/plugin[artifactId = 'nbm-maven-plugin']/configuration/publicPackages"); Node node = (Node) expr.evaluate(doc, XPathConstants.NODE); for (String p : packages) { Element pp = doc.createElement("publicPackage"); pp.appendChild(doc.createTextNode(p)); node.appendChild(pp); } FileWriter writer = new FileWriter(xmlFile); StreamResult result = new StreamResult(writer); Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); transformer.transform(new DOMSource(doc), result); writer.close(); } catch (Exception e) { throw new MojoExecutionException("Error while inserting public packages in XML document '" + xmlFile + "'", e); } } private Document parseXMLDocument(File xmlFile) throws ParserConfigurationException, IOException, SAXException { DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance(); domFactory.setIgnoringComments(true); DocumentBuilder builder = domFactory.newDocumentBuilder(); Document doc = builder.parse(xmlFile); return doc; } /** * Simple groupId + artifactId internal class. */ private static class Dependency { private final String groupId; private final String artifactId; public Dependency(String groupId, String artifactId) { this.groupId = groupId; this.artifactId = artifactId; } @Override public int hashCode() { int hash = 7; hash = 37 * hash + (this.groupId != null ? this.groupId.hashCode() : 0); hash = 37 * hash + (this.artifactId != null ? this.artifactId.hashCode() : 0); return hash; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } final Dependency other = (Dependency) obj; if ((this.groupId == null) ? (other.groupId != null) : !this.groupId.equals(other.groupId)) { return false; } if ((this.artifactId == null) ? (other.artifactId != null) : !this.artifactId.equals(other.artifactId)) { return false; } return true; } @Override public String toString() { return "[groupId=" + groupId + " artifactId=" + artifactId + "]"; } } private static class ProjectMetadata { private String brandingName; private String category; private String shortDescription; private String longDescription; private String author; private String homepageUrl; private String codeNameBase; private String localizingBundle; private List publicPackages; private Set dependencies; private String licenseFile; } private void copyFiles(File srcFolder, File destFolder, String[] includes, String[] excludes) throws IOException { DirectoryScanner scanner = new DirectoryScanner(); scanner.setBasedir(srcFolder); if (includes != null && includes.length >= 1) { scanner.setIncludes(includes); } else { scanner.setIncludes(new String[]{"**"}); } if (excludes != null && excludes.length >= 1) { scanner.setExcludes(excludes); } scanner.addDefaultExcludes(); scanner.scan(); List files = Arrays.asList(scanner.getIncludedFiles()); for (Iterator i = files.iterator(); i.hasNext();) { String name = (String) i.next(); File source = new File(srcFolder, name); if (source.equals(srcFolder)) { continue; } File target = new File(destFolder, name); getLog().debug("Copying file '" + source.getAbsolutePath() + "' to '" + target.getAbsolutePath() + "'"); FileUtils.copyFile(source, target); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy