Package org.appfuse.mojo.exporter

Source Code of org.appfuse.mojo.exporter.AppFuseGeneratorMojo$POJOSearcher

package org.appfuse.mojo.exporter;


import org.apache.commons.io.FileUtils;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.appfuse.mojo.HibernateExporterMojo;
import org.appfuse.tool.AppFuseExporter;
import org.appfuse.tool.ArtifactInstaller;
import org.codehaus.plexus.components.interactivity.Prompter;
import org.codehaus.plexus.components.interactivity.PrompterException;
import org.hibernate.tool.hbm2x.Exporter;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.*;
import java.util.Collection;

/**
* Generates Java classes from set of annotated POJOs. Use -DdisableInstallation to prevent installation.
* If using this goal in a "core" module or project, only DAOs and Managers will be created. For "web"
* modules, the same principle applies.
*
* @author <a href="mailto:matt@raibledesigns.com">Matt Raible</a>
* @goal gen
* @phase generate-sources
* @execute phase="compile"
*/
public class AppFuseGeneratorMojo extends HibernateExporterMojo {
    boolean generateCoreOnly;
    boolean generateWebOnly;
    String pojoName;

    /**
     * This is a prompter that can be user within the maven framework.
     *
     * @component
     */
    Prompter prompter;

    /**
     * The path where the generated artifacts will be placed. This is intentionally not set to the
     * default location for maven generated sources. This is to keep these files out of the
     * eclipse/idea generated sources directory as the intention is that these files will be copied
     * to a source directory to be edited and modified and not re generated each time the plugin is
     * run. If you want to regenerate the files each time you build the project just set this value
     * to ${basedir}/target/generated-sources or set the flag on eclipse/idea plugin to include this
     * file in your project file as a source directory.
     *
     * @parameter expression="${appfuse.destinationDirectory}" default-value="${basedir}"
     * @noinspection UnusedDeclaration
     */
    private String destinationDirectory;

    /**
     * The directory containing the source code.
     *
     * @parameter expression="${appfuse.sourceDirectory}" default-value="${basedir}/target/appfuse/generated-sources"
     * @noinspection UnusedDeclaration
     */
    private String sourceDirectory;

    /**
     * Allows disabling installation - for tests and end users that don't want to do a full installation
     *
     * @parameter expression="${appfuse.disableInstallation}" default-value="false"
     */
    private boolean disableInstallation;

    /**
     * @parameter expression="${appfuse.genericCore}" default-value="true"
     * @noinspection UnusedDeclaration
     */
    private boolean genericCore;

    /**
     * @parameter expression="${appfuse.templateDirectory}" default-value="${basedir}/src/test/resources"
     * @noinspection UnusedDeclaration
     */
    private String templateDirectory;

    /**
     * Path for where to generate files at.
     */

    private String fullPath = null;

    /**
     * Default constructor.
     */
    public AppFuseGeneratorMojo() {
        addDefaultComponent("target/appfuse/generated-sources", "configuration", false);
        addDefaultComponent("target/appfuse/generated-sources", "annotationconfiguration", true);
    }

// --------------------- Interface ExporterMojo ---------------------

    /**
     * Returns <b>gen</b>.
     *
     * @return String goal's name
     */
    public String getName() {
        return "gen";
    }

    @Override
    public void execute() throws MojoExecutionException, MojoFailureException {
        // if project is of type "pom", throw an error
        if (getProject().getPackaging().equalsIgnoreCase("pom")) {
            String errorMsg = "[ERROR] This plugin cannot be run from a pom project, please run it from a jar or war project (i.e. core or web).";
            //getLog().error(errorMsg);
            throw new MojoFailureException(errorMsg);
        }

        pojoName = System.getProperty("entity");

        if (pojoName == null) {
            try {
                pojoName = prompter.prompt("What is the name of your pojo (i.e. Person)?");
            } catch (PrompterException pe) {
                pe.printStackTrace();
            }
        }

        if (pojoName == null || "".equals(pojoName.trim())) {
            throw new MojoExecutionException("You must specify an entity name to continue.");
        }

        // A dot in the entity name means the person is specifying the package.
        if (pojoName.contains(".")) {
            if (!pojoName.contains("model")) {
                throw new MojoExecutionException("You must specify 'model' as the last package in your entity name.");
            }
            fullPath = pojoName.substring(0, pojoName.indexOf(".model"));
            // allow ~ to be used for groupId
            fullPath = fullPath.replace("~", getProject().getGroupId());

            pojoName = pojoName.substring(pojoName.lastIndexOf(".") + 1);
            log("Package name set to: " + fullPath);
        }

        String daoFramework = getProject().getProperties().getProperty("dao.framework");

        // If dao.framework is jpa, change to jpaconfiguration and persistence.xml should be found in classpath.
        // No other configuration is needed.
        if (daoFramework.contains("jpa")) {
            getComponentProperties().put("implementation", "jpaconfiguration");
            checkEntityExists();
        }

        // for war projects that have a parent pom, don't reset classpath
        // this is to allow using hibernate.cfg.xml from core module
        if (getProject().getPackaging().equals("war") && getProject().hasParent()) {
            // assume first module in parent project has hibernate.cfg.xml
            String moduleName = (String) getProject().getParent().getModules().get(0);
            String pathToParent = getProject().getOriginalModel().getParent().getRelativePath();
            pathToParent = pathToParent.substring(0, pathToParent.lastIndexOf('/') + 1);
            log("Assuming '" + moduleName + "' has hibernate.cfg.xml in its src/main/resources directory");
            getComponentProperties().put("configurationfile",
                    getProject().getBasedir() + "/" + pathToParent + moduleName + "/src/main/resources/hibernate.cfg.xml");
        }

        if (getComponentProperty("configurationfile") == null) {
            getComponentProperties().put("configurationfile", "src/main/resources/hibernate.cfg.xml");
        }

        // if entity is not in hibernate.cfg.xml, add it
        String hibernateConfig = getComponentProperty("configurationfile");

        if (daoFramework.equals("hibernate")) {
            try {
                String hibernateCfgXml = FileUtils.readFileToString(new File(hibernateConfig));
                addEntityToHibernateCfgXml(hibernateCfgXml);
            } catch (IOException io) {
                throw new MojoFailureException(io.getMessage());
            }
        }

        // If dao.framework is ibatis, programmatically create a hibernate.cfg.xml and put it in the classpath
        if (daoFramework.equalsIgnoreCase("ibatis")) {
            try {
                String pomAsString = FileUtils.readFileToString(new File("pom.xml"));
                if (pomAsString.contains("<implementation>annotationconfiguration</implementation>")) {
                    // if no hibernate.cfg.xml exists, create one from template in plugin
                    log("Creating hibernate.cfg.xml from template...");
                    String hibernateCfgXml;
                    File existingConfig = new File(hibernateConfig);
                    if (!existingConfig.exists()) {
                        InputStream in = this.getClass().getResourceAsStream("/appfuse/dao/ibatis/hibernate.cfg.ftl");
                        StringBuffer configFile = new StringBuffer();
                        try {
                            InputStreamReader isr = new InputStreamReader(in);
                            BufferedReader reader = new BufferedReader(isr);
                            String line;
                            while ((line = reader.readLine()) != null) {
                                configFile.append(line).append("\n");
                            }
                            reader.close();
                        } catch (IOException io) {
                            throw new MojoFailureException(io.getMessage());
                        }

                        hibernateCfgXml = configFile.toString();
                    } else {
                        hibernateCfgXml = FileUtils.readFileToString(existingConfig);
                    }

                    addEntityToHibernateCfgXml(hibernateCfgXml);
                } else {
                    log("[WARN] Detected JPA configuration");
                }
            } catch (IOException io) {
                io.printStackTrace();
                getLog().error(io.getMessage());
            }
        }

        super.execute();
    }

    /**
     * @see org.appfuse.mojo.HibernateExporterMojo#configureExporter(org.hibernate.tool.hbm2x.Exporter)
     */
    protected Exporter configureExporter(Exporter exp) throws MojoExecutionException {
        // Read in AppFuseExporter#configureExporter to decide if a class should be generated or not
        System.setProperty("appfuse.entity", pojoName);

        // add output directory to compile roots
        getProject().addCompileSourceRoot(new File(getComponent().getOutputDirectory()).getPath());

        // now set the extra properties for the AppFuseExporter
        AppFuseExporter exporter = (AppFuseExporter) super.configureExporter(exp);
        exporter.getProperties().setProperty("ejb3", getComponentProperty("ejb3", "true"));
        exporter.getProperties().setProperty("jdk5", getComponentProperty("jdk5", "true"));

        if (generateCoreOnly) {
            exporter.getProperties().setProperty("generate-core", "true");
        } else if (generateWebOnly) {
            exporter.getProperties().setProperty("generate-web", "true");
        }

        String rootPackage = (fullPath != null) ? fullPath : getProject().getGroupId();

        // AppFuse-specific values
        exporter.getProperties().setProperty("basepackage", rootPackage);
        exporter.getProperties().setProperty("daoframework", getProject().getProperties().getProperty("dao.framework"));

        String webFramework = (getProject().getProperties().containsKey("web.framework")) ?
                getProject().getProperties().getProperty("web.framework") : "";

        exporter.getProperties().setProperty("webframework", webFramework);

        exporter.getProperties().setProperty("packaging", getProject().getPackaging());
        exporter.getProperties().setProperty("genericcore", String.valueOf(genericCore));

        if (templateDirectory != null) {
            exporter.getProperties().setProperty("templatedirectory", templateDirectory);
        }

        if (isFullSource())
            exporter.getProperties().setProperty("appfusepackage", rootPackage);
        else {
            exporter.getProperties().setProperty("appfusepackage", "org.appfuse");
        }

        // See if the project has security enabled
        boolean hasSecurity = false;
        if (getProject().getPackaging().equals("war")) {
            Collection<File> sourceFiles = FileUtils.listFiles(getProject().getBasedir(),new String[]{"xml"}, true);
            for (File file : sourceFiles) {
                if (file.getPath().contains("security.xml")) {
                    hasSecurity = true;
                    break;
                }
            }
        }

        exporter.getProperties().setProperty("hasSecurity", String.valueOf(hasSecurity));

        // determine if using Home or Home for Tapestry
        if (webFramework.equals("tapestry")) {
            boolean useHome = true;
            Collection<File> sourceFiles = FileUtils.listFiles(getProject().getBasedir(),new String[]{"java"}, true);
            for (File file : sourceFiles) {
                if (file.getPath().contains("Home.java")) {
                    useHome = false;
                    break;
                }
            }
            exporter.getProperties().setProperty("useHome", String.valueOf(useHome));
        }

        return exporter;
    }

    /**
     * Executes the plugin in an isolated classloader.
     *
     * @throws MojoExecutionException When there is an erro executing the plugin
     */
    @Override
    protected void doExecute() throws MojoExecutionException {
        super.doExecute();

        if (System.getProperty("disableInstallation") != null) {
            disableInstallation = Boolean.valueOf(System.getProperty("disableInstallation"));
        }

        // allow installation to be suppressed when testing
        if (!disableInstallation) {
            ArtifactInstaller installer = new ArtifactInstaller(getProject(), pojoName, sourceDirectory, destinationDirectory, genericCore);
            installer.execute();
        }
    }

    /**
     * Instantiates a org.appfuse.tool.AppFuseExporter object.
     *
     * @return POJOExporter
     */
    protected Exporter createExporter() {
        return new AppFuseExporter();
    }

    protected void setGenerateCoreOnly(boolean generateCoreOnly) {
        this.generateCoreOnly = generateCoreOnly;
    }

    protected void setGenerateWebOnly(boolean generateWebOnly) {
        this.generateWebOnly = generateWebOnly;
    }

    private void log(String msg) {
        getLog().info("[AppFuse] " + msg);
    }

    private void addEntityToHibernateCfgXml(String hibernateCfgXml) throws MojoFailureException {
        String className = (fullPath != null) ? fullPath : getProject().getGroupId();

        className += ".model." + pojoName;
        log("Constructed class name : " + className);

        POJOSearcher pojoSearcher = new POJOSearcher(hibernateCfgXml);
        if (!pojoSearcher.searchForPojo(pojoName)) {
            // check that class exists and has an @Entity annotation
            checkEntityExists();

            hibernateCfgXml = hibernateCfgXml.replace("</session-factory>",
                    "    <mapping class=\"" + className + "\"/>"
                            + "\n    </session-factory>");
            log("Adding '" + pojoName + "' to hibernate.cfg.xml...");
        }

        hibernateCfgXml = hibernateCfgXml.replaceAll("\\$\\{appfusepackage}",
                (isFullSource()) ? getProject().getGroupId() : "org.appfuse");

        try {
            FileUtils.writeStringToFile(new File(
                    getComponentProperty("configurationfile", "src/main/resources/hibernate.cfg.xml")), hibernateCfgXml);
        } catch (IOException io) {
            throw new MojoFailureException(io.getMessage());
        }
    }

    private void checkEntityExists() throws MojoFailureException {
        // allow check to be bypassed when -Dentity.check=false
        if (!"false".equals(System.getProperty("entity.check"))) {
            final String FILE_SEP = System.getProperty("file.separator");
            String pathToModelPackage = "src" + FILE_SEP + "main" + FILE_SEP + "java" + FILE_SEP;
            if (getProject().getPackaging().equals("war") && getProject().hasParent()) {
                String moduleName = (String) getProject().getParent().getModules().get(0);
                String pathToParent = getProject().getOriginalModel().getParent().getRelativePath();
                pathToParent = pathToParent.substring(0, pathToParent.lastIndexOf('/') + 1);
                pathToParent = pathToParent.replaceAll("/", FILE_SEP);
                pathToModelPackage = getProject().getBasedir() + FILE_SEP + pathToParent + moduleName + "/" + pathToModelPackage;
            }

            // refactor to check classpath instead of filesystem
            String groupIdAsPath = getProject().getGroupId().replace(".", FILE_SEP);

            String fullPathPackage = pathToModelPackage + groupIdAsPath;
            if (fullPath != null) {
                fullPathPackage += FILE_SEP + fullPath.replace(".", FILE_SEP);
            } else {
                fullPathPackage += FILE_SEP + "model";
            }
            log("Looking for entity in " + fullPathPackage);

            File modelPackage = new File(fullPathPackage);
            boolean entityExists = false;

            if (modelPackage.exists()) {
                String[] entities = modelPackage.list();
                for (String entity : entities) {
                    log("Found '" + entity + "' in model package...");
                    if (entity.contains(pojoName + ".java")) {
                        entityExists = true;
                        break;
                    }
                }
            } else {
                getLog().error("The path '" + fullPathPackage + groupIdAsPath + FILE_SEP + "model' does not exist!");
            }

            if (!entityExists) {
                throw new MojoFailureException("[ERROR] The '" + pojoName + "' entity does not exist in '" + modelPackage + "'.");
            } else {
                // Entity found, make sure it has @Entity annotation
                try {
                    File pojoFile = new File(modelPackage + FILE_SEP + pojoName + ".java");
                    String entityAsString = FileUtils.readFileToString(pojoFile);
                    if (!entityAsString.contains("@Entity")) {
                        String msg = "Entity '" + pojoName + "' found, but it doesn't contain an @Entity annotation. Please add one.";
                        throw new MojoFailureException(msg);
                    }
                } catch (IOException io) {
                    throw new MojoFailureException("[ERROR] Class '" + pojoName + ".java' not found in '" + modelPackage + "'");
                }
            }
        }
    }

    public class POJOSearcher extends DefaultHandler {
        private String pojoName;
        private boolean foundPojo;
        private String xmlString;

        public POJOSearcher(String xmlString) {
            this.xmlString = xmlString;
        }

        public boolean searchForPojo(String pojoName) {
            this.pojoName = pojoName;
            this.foundPojo = false;

            SAXParserFactory spf = SAXParserFactory.newInstance();
            try {
                spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);

                SAXParser sp = spf.newSAXParser();
                sp.parse(new InputSource(new StringReader(xmlString)), this);
            } catch (Exception ex) {
                System.out.println(ex.getMessage());
                ex.printStackTrace();
            }

            return foundPojo;
        }

        @Override
        public void startElement(String uri, String localName, String name, Attributes attributes) throws SAXException {
            super.startElement(uri, localName, name, attributes);
            if (name.equals("mapping")) {
                String classValue = attributes.getValue("class");
                if (classValue != null) {
                    if (classValue.endsWith(pojoName)) {
                        foundPojo = true;
                    }
                }
            }
        }
    }
}
TOP

Related Classes of org.appfuse.mojo.exporter.AppFuseGeneratorMojo$POJOSearcher

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.