Package org.appfuse.tool

Source Code of org.appfuse.tool.ArtifactInstaller

package org.appfuse.tool;

import org.apache.commons.io.FileUtils;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.plugin.logging.SystemStreamLog;
import org.apache.maven.project.MavenProject;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Copy;
import org.apache.tools.ant.taskdefs.Echo;
import org.apache.tools.ant.taskdefs.LoadFile;
import org.apache.tools.ant.taskdefs.Replace;
import org.apache.tools.ant.taskdefs.optional.ReplaceRegExp;
import org.apache.tools.ant.types.FileSet;
import org.appfuse.mojo.installer.AntUtils;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

/**
* This class is responsible for installing generated CRUD artifacts into an AppFuse application.
*
* @author mraible
*/
public class ArtifactInstaller {
    private Log log;
    static final String FILE_SEP = System.getProperty("file.separator");
    Project antProject;
    String pojoName;
    String pojoNameLower;
    String destinationDirectory;
    String sourceDirectory;
    MavenProject project;
    boolean genericCore;
    StringUtils util;

    public ArtifactInstaller(MavenProject project, String pojoName, String sourceDirectory, String destinationDirectory, boolean genericCore) {
        this.project = project;
        this.pojoName = pojoName;
        this.pojoNameLower = pojoLowerCase(pojoName);
        this.sourceDirectory = sourceDirectory;
        this.destinationDirectory = destinationDirectory;
        this.genericCore = genericCore;
        this.util = new StringUtils();
    }

    public void execute() {
        antProject = AntUtils.createProject();

        boolean hasDbUnit = projectContainsPluginArtifact("dbunit");

        if (hasDbUnit) {
            log("Installing sample data for DbUnit...");
            installSampleData();
        }

        // install dao and manager if jar (modular/core) or war w/o parent (basic)
        if (project.getPackaging().equals("jar") || (project.getPackaging().equals("war") && project.getParent() == null)) {
            copyGeneratedObjects(this.sourceDirectory, this.destinationDirectory, "**/model/**/*.java");
            copyGeneratedObjects(this.sourceDirectory, this.destinationDirectory, "**/dao/**/*.java");
            copyGeneratedObjects(this.sourceDirectory, this.destinationDirectory, "**/service/**/*.java");
            if (genericCore) {
                log("Installing Spring bean definitions (genericCore == true)...");
                installGenericBeanDefinitions();
            } else {
                // APF-1105: Changed to use Spring annotations (@Repository, @Service and @Autowired)
                //installDaoAndManagerBeanDefinitions();
            }
            // only installs if iBATIS is configured as dao.framework
            installiBATISFiles();
        }

        if (project.getPackaging().equalsIgnoreCase("war")) {
            copyGeneratedObjects(this.sourceDirectory, this.destinationDirectory, "**/webapp/**/*.java");

            String webFramework = project.getProperties().getProperty("web.framework");

            if ("jsf".equalsIgnoreCase(webFramework)) {
                log("Installing JSF views and configuring...");
                installJSFNavigationAndBeans();
                installJSFViews();
            } else if ("struts".equalsIgnoreCase(webFramework)) {
                log("Installing Struts views and configuring...");
                // A bean definition for an Action is not used anymore (APF-798)
                // installStrutsBeanDefinition();
                installStrutsActionDefinitions();
                copyGeneratedObjects(sourceDirectory + "/src/main/resources",
                        destinationDirectory + "/src/main/resources", "**/model/*.xml");
                copyGeneratedObjects(sourceDirectory + "/src/main/resources",
                        destinationDirectory + "/src/main/resources", "**/webapp/action/*.xml");
                installStrutsViews();
            } else if ("spring".equalsIgnoreCase(webFramework)) {
                log("Installing Spring views and configuring...");
                //Controllers configured by Spring annotations in 2.1+
                //installSpringControllerBeanDefinitions();
                installSpringValidation();
                installSpringViews();
            } else if ("tapestry".equalsIgnoreCase(webFramework)) {
                log("Installing Tapestry views and configuring...");
                installTapestryViews();
            }

            log("Installing i18n messages...");
            installInternationalizationKeys(webFramework);

            if (!"tapestry".equalsIgnoreCase(webFramework)) {
                log("Installing menu...");
                installMenu();
            }

            log("Installing UI tests...");
            installUITests();
        }
    }

    private boolean projectContainsPluginArtifact(String artifactId) {
        for (Object artifact : project.getPluginArtifacts()) {
            if (((Artifact) artifact).getArtifactId().contains(artifactId)) {
                return true;
            }
        }
        return false;
    }

    private boolean projectContainsArtifact(String artifactId) {
        for (Object artifact : project.getArtifacts()) {
            if (((Artifact) artifact).getArtifactId().contains(artifactId)) {
                return true;
            }
        }
        return false;
    }

    /**
     * This method will copy files from the source directory to the destination directory based on
     * the pattern.
     *
     * @param inSourceDirectory      The source directory to copy from.
     * @param inDestinationDirectory The destination directory to copy to.
     * @param inPattern              The file pattern to match to locate files to copy.
     */
    protected void copyGeneratedObjects(final String inSourceDirectory, final String inDestinationDirectory,
                                        final String inPattern) {
        Copy copyTask = (Copy) antProject.createTask("copy");

        FileSet fileSet = AntUtils.createFileset(inSourceDirectory, inPattern, new ArrayList());
        log("Installing generated files (pattern: " + inPattern + ")...");
        copyTask.setTodir(new File(inDestinationDirectory));
        copyTask.addFileset(fileSet);
        copyTask.execute();
    }

    private String pojoLowerCase(String name) {
        return name.substring(0, 1).toLowerCase() + name.substring(1);
    }

    private String getPathToApplicationContext() {
        if (project.getPackaging().equalsIgnoreCase("war")) {
            return "/src/main/webapp/WEB-INF/applicationContext.xml";
        } else { // if (project.getPackaging().equalsIgnoreCase("jar")) {
            return "/src/main/resources/applicationContext.xml";
        }
    }

    /**
     * Add sample-data.xml to project's sample-data.xml
     */
    private void installSampleData() {
        createLoadFileTask("src/test/resources/" + pojoName + "-sample-data.xml", "sample.data").execute();
        File existingFile = new File(destinationDirectory + "/src/test/resources/sample-data.xml");

        parseXMLFile(existingFile, null, "</dataset>", "sample.data");
    }

    /* APF-1105: Changed to use Spring annotations (@Repository, @Service and @Autowired)
    private void installDaoAndManagerBeanDefinitions() {
        createLoadFileTask("src/main/resources/" + pojoName + "Dao-bean.xml", "dao.context.file").execute();
        File generatedFile = new File(destinationDirectory + getPathToApplicationContext());

        parseXMLFile(generatedFile, pojoName + "Dao", "<!-- Add new DAOs here -->", "dao.context.file");

        createLoadFileTask("src/main/resources/" + pojoName + "Manager-bean.xml", "mgr.context.file").execute();
        generatedFile = new File(destinationDirectory + getPathToApplicationContext());

        parseXMLFile(generatedFile, pojoName + "Manager", "<!-- Add new Managers here -->", "mgr.context.file");
    }*/

    private void installiBATISFiles() {
        if (project.getProperties().getProperty("dao.framework").equals("ibatis")) {
            log("Installing iBATIS SQL Maps...");
            createLoadFileTask("src/main/resources/" + pojoName + "-sql-map-config.xml", "sql.map.config").execute();
            File sqlMapConfig = new File(destinationDirectory + "/src/main/resources/sql-map-config.xml");
            parseXMLFile(sqlMapConfig, null, "</sqlMapConfig>", "sql.map.config");

            File sqlMapsDir = new File(destinationDirectory + "/src/main/resources/sqlmaps");
            if (sqlMapsDir.exists()) {
                sqlMapsDir.mkdir();
            }

            Copy copy = (Copy) antProject.createTask("copy");
            copy.setFile(new File(sourceDirectory + "/src/main/resources/sqlmaps/" + pojoName + "SQL.xml"));
            copy.setTodir(new File(destinationDirectory + "/src/main/resources/sqlmaps"));
            copy.execute();

            // Add compass gps bean if it doesn't exist
            File ctx = new File(destinationDirectory + "/src/main/webapp/WEB-INF/applicationContext.xml");
            try {
                File appCtx = new File(destinationDirectory + "/src/main/webapp/WEB-INF/applicationContext.xml");
                String appCtxAsString = FileUtils.readFileToString(ctx);
                if (!appCtxAsString.contains("SqlMapClientGpsDevice")) {
                    log("Adding compassGps bean to applicationContext.xml");
                    createLoadFileTask("src/main/resources/compass-gps.xml", "compass.gps").execute();
                    parseXMLFile(appCtx, null, "<!-- Add new DAOs here -->", "compass.gps");
                }

                if (!appCtxAsString.contains("<value>get" + pojoName)) {
                    // add value to list of select statement Ids
                    createLoadFileTask("src/main/resources/" + pojoName + "-select-ids.xml", "select.ids").execute();
                    parseXMLFile(appCtx, null, "<value>getUsers</value>", "select.ids");
                }
            } catch (IOException e) {
                log("Failed to read project's applicationContext.xml!");
                e.printStackTrace();
            }
        }
    }

    private void installGenericBeanDefinitions() {
        createLoadFileTask("src/main/resources/" + pojoName + "-generic-beans.xml", "context.file").execute();
        File generatedFile = new File(destinationDirectory + getPathToApplicationContext());

        parseXMLFile(generatedFile, pojoName + "Manager", "<!-- Add new Managers here -->", "context.file");
    }

    private void installJSFNavigationAndBeans() {
        createLoadFileTask("src/main/webapp/WEB-INF/" + pojoName + "-navigation.xml", "navigation.rules").execute();
        File generatedFile = new File(destinationDirectory + "/src/main/webapp/WEB-INF/faces-config.xml");
        parseXMLFile(generatedFile, pojoName + "-nav", "<!-- Add additional rules here -->", "navigation.rules");

        // JSF managed beans configured by Spring annotations in 2.1+
        //createLoadFileTask("src/main/webapp/WEB-INF/" + pojoName + "-managed-beans.xml", "managed.beans").execute();
        //generatedFile = new File(destinationDirectory + "/src/main/webapp/WEB-INF/faces-config.xml");
        //parseXMLFile(generatedFile, pojoName + "-beans", "<!-- Add additional beans here -->", "managed.beans");
    }

    private void installSpringControllerBeanDefinitions() {
        // Controllers configured by Spring annotations in 2.1+
        //createLoadFileTask("src/main/webapp/WEB-INF/" + pojoName + "-beans.xml", "dispatcher.servlet").execute();
        //File generatedFile = new File(destinationDirectory + "/src/main/webapp/WEB-INF/dispatcher-servlet.xml");

        //parseXMLFile(generatedFile, pojoName, "<!-- Add additional controller beans here -->", "dispatcher.servlet");
    }

    private void installSpringValidation() {
        createLoadFileTask("src/main/webapp/WEB-INF/" + pojoName + "-validation.xml", "spring.validation").execute();
        File generatedFile = new File(destinationDirectory + "/src/main/webapp/WEB-INF/validation.xml");

        parseXMLFile(generatedFile, pojoName, "    </formset>", "spring.validation");
    }

    private void installStrutsActionDefinitions() {
        createLoadFileTask("src/main/resources/" + pojoName + "-struts.xml", "struts.file").execute();
        File existingFile = new File(destinationDirectory + "/src/main/resources/struts.xml");

        parseXMLFile(existingFile, pojoName + "Action", "<!-- Add additional actions here -->", "struts.file");
    }

    // =================== Views ===================

    private void installJSFViews() {
        Copy copy = (Copy) antProject.createTask("copy");
        copy.setFile(new File(sourceDirectory + "/src/main/webapp/" + pojoName + "Form.xhtml"));
        copy.setTofile(new File(destinationDirectory + "/src/main/webapp/" + pojoNameLower + "Form.xhtml"));
        copy.execute();

        copy.setFile(new File(sourceDirectory + "/src/main/webapp/" + pojoName + "s.xhtml"));
        copy.setTofile(new File(destinationDirectory + "/src/main/webapp/" + util.getPluralForWord(pojoNameLower) + ".xhtml"));
        copy.execute();
    }

    private void installSpringViews() {
        Copy copy = (Copy) antProject.createTask("copy");
        copy.setFile(new File(sourceDirectory + "/src/main/webapp/WEB-INF/pages/" + pojoName + "form.jsp"));
        copy.setTofile(new File(destinationDirectory + "/src/main/webapp/WEB-INF/pages/" + pojoNameLower + "form.jsp"));
        copy.execute();

        copy.setFile(new File(sourceDirectory + "/src/main/webapp/WEB-INF/pages/" + pojoName + "s.jsp"));
        copy.setTofile(new File(destinationDirectory + "/src/main/webapp/WEB-INF/pages/" + util.getPluralForWord(pojoNameLower) + ".jsp"));
        copy.execute();
    }

    private void installStrutsViews() {
        Copy copy = (Copy) antProject.createTask("copy");
        copy.setFile(new File(sourceDirectory + "/src/main/webapp/WEB-INF/pages/" + pojoName + "Form.jsp"));
        copy.setTofile(new File(destinationDirectory + "/src/main/webapp/WEB-INF/pages/" + pojoNameLower + "Form.jsp"));
        copy.execute();

        copy.setFile(new File(sourceDirectory + "/src/main/webapp/WEB-INF/pages/" + pojoName + "List.jsp"));
        copy.setTofile(new File(destinationDirectory + "/src/main/webapp/WEB-INF/pages/" + pojoNameLower + "List.jsp"));
        copy.execute();
    }

    private void installTapestryViews() {
        Copy copy = (Copy) antProject.createTask("copy");
        copy.setFile(new File(sourceDirectory + "/src/main/webapp/" + pojoName + "Form.tml"));
        copy.setTodir(new File(destinationDirectory + "/src/main/webapp"));
        copy.execute();

        copy.setFile(new File(sourceDirectory + "/src/main/webapp/" + pojoName + "List.tml"));
        copy.execute();

        log("Installing menu...");
        createLoadFileTask("src/main/webapp/" + pojoName + "-menu.tml", "tapestry-menu").execute();
        File existingFile = new File(destinationDirectory + "/src/main/resources/" +
                project.getGroupId().replace(".", "/") + "/webapp/components/Layout.tml");
        parseXMLFile(existingFile, pojoName, "<!-- Add new menu items here -->", "tapestry-menu");
    }

    private boolean isAppFuse() {
        return (project.getProperties().getProperty("copyright.year") != null);
    }

    // =================== End of Views ===================

    private void installMenu() {
        boolean hasStrutsMenu;
        File menuConfig = new File(destinationDirectory + "/src/main/webapp/WEB-INF/menu-config.xml");
        hasStrutsMenu = menuConfig.exists();

        if (hasStrutsMenu) {
            createLoadFileTask("src/main/webapp/common/" + pojoName + "-menu.jsp", "menu.jsp").execute();
            File existingFile = new File(destinationDirectory + "/src/main/webapp/common/menu.jsp");

            parseXMLFile(existingFile, pojoName, "</ul>", "menu.jsp");

            createLoadFileTask("src/main/webapp/WEB-INF/" + pojoName + "-menu-config.xml", "menu.config").execute();
            existingFile = new File(destinationDirectory + "/src/main/webapp/WEB-INF/menu-config.xml");

            parseXMLFile(existingFile, pojoName, "    </Menus>", "menu.config");
        } else {
            createLoadFileTask("src/main/webapp/common/" + pojoName + "-menu-light.jsp", "menu-light.jsp").execute();

            File existingFile = new File(destinationDirectory + "/src/main/webapp/decorators/default.jsp");
            File jsfConfig = new File(destinationDirectory + "/src/main/webapp/WEB-INF/faces-config.xml");
            if (jsfConfig.exists()) {
                existingFile = new File(destinationDirectory + "/src/main/webapp/layouts/default.xhtml");
            }

            parseXMLFile(existingFile, pojoName, "<!-- Add new menu items here -->", "menu-light.jsp");
        }
    }

    private void installInternationalizationKeys(String webFramework) {
        createLoadFileTask("src/main/resources/" + pojoName + "-ApplicationResources.properties", "i18n.file").execute();
        File existingFile = new File(destinationDirectory + "/src/main/resources/ApplicationResources.properties");

        // if ApplicationResources doesn't exist, assume appfuse-light and use messages instead
        if (!existingFile.exists()) {
            existingFile = new File(destinationDirectory + "/src/main/resources/messages.properties");
        }

        parsePropertiesFile(existingFile, pojoName);

        Echo echoTask = (Echo) antProject.createTask("echo");
        echoTask.setFile(existingFile);
        echoTask.setAppend(true);
        echoTask.setMessage(antProject.getProperty("i18n.file"));
        echoTask.execute();
    }

    private void installUITests() {
        // Gracefully handle when ui tests don't exist
        boolean webTestsExist = new File("src/test/resources/" + "web-tests.xml").exists();
        File existingFile = new File(destinationDirectory + "/src/test/resources/web-tests.xml");
        if (webTestsExist && existingFile.exists()) {
            createLoadFileTask("src/test/resources/" + pojoName + "-web-tests.xml", "web.tests").execute();
            parseXMLFile(existingFile, pojoName, "</project>", "web.tests");

            // Add main target to run-all-tests target
            Replace replace = (Replace) antProject.createTask("replace");
            replace.setFile(existingFile);

            try {
                if (FileUtils.readFileToString(existingFile).contains("FileUpload")) {
                    // todo: figure out how to fix the 2 lines below so they don't include pojoNameTest
                    // multiple times on subsequent installs
                    replace.setToken(",FileUpload");
                    replace.setValue(",FileUpload," + pojoName + "Tests");
                } else {
                    // AppFuse Light
                    replace.setToken("depends=\"UserTests");
                    replace.setValue("depends=\"UserTests," + pojoName + "Tests");
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            replace.execute();
        } else {
            log("Project doesn't use Canoo WebTest, disabling UI test generation.");
            log("Support for jWebUnit will be added in a future release.");
            log("See http://issues.appfuse.org/browse/EQX-215 for more information.");
        }
    }

    /**
     * This method will create an ANT based LoadFile task based on an infile and a property name.
     * The property will be loaded with the infile for use later by the Replace task.
     *
     * @param inFile   The file to process
     * @param propName the name to assign it to
     * @return The ANT LoadFile task that loads a property with a file
     */
    protected LoadFile createLoadFileTask(String inFile, String propName) {
        inFile = sourceDirectory + FILE_SEP + inFile;
        LoadFile loadFileTask = (LoadFile) antProject.createTask("loadfile");
        loadFileTask.init();
        loadFileTask.setProperty(propName);
        loadFileTask.setSrcFile(new File(inFile));

        return loadFileTask;
    }

    private void parseXMLFile(File existingFile, String beanName, String tokenToReplace, String fileVariable) {
        String nameInComment = beanName;
        if (beanName == null) {
            nameInComment = pojoName;
        }
        Replace replace1 = (Replace) antProject.createTask("replace");
        replace1.setFile(existingFile);
        replace1.setToken("<!--" + nameInComment + "-START-->");
        replace1.setValue("REGULAR-START");
        replace1.execute();

        Replace replace2 = (Replace) antProject.createTask("replace");
        replace2.setFile(existingFile);
        replace2.setToken("<!--" + nameInComment + "-END-->");
        replace2.setValue("REGULAR-END");
        replace2.execute();

        ReplaceRegExp regExpTask = (ReplaceRegExp) antProject.createTask("replaceregexp");
        regExpTask.setFile(existingFile);
        regExpTask.setMatch("REGULAR-START(?s:.)*REGULAR-END");
        regExpTask.setReplace("");
        regExpTask.setFlags("g");
        regExpTask.execute();

        Replace replaceData = (Replace) antProject.createTask("replace");
        replaceData.setFile(existingFile);
        replaceData.setToken(tokenToReplace);
        String stringWithProperLineEndings = adjustLineEndingsForOS(antProject.getProperty(fileVariable));
        replaceData.setValue(stringWithProperLineEndings);
        replaceData.execute();
    }

    /**
     * This file is the same as the method above, except for different comment placeholder formats.
     * Yeah, I know, it's ugly.
     *
     * @param existingFile file to merge with in project
     * @param beanName     name of placeholder string that goes in comment
     */
    private void parsePropertiesFile(File existingFile, String beanName) {
        String nameInComment = beanName;
        if (beanName == null) {
            nameInComment = pojoName;
        }

        Replace replace1 = (Replace) antProject.createTask("replace");
        replace1.setFile(existingFile);
        replace1.setToken("# -- " + nameInComment + "-START");
        replace1.setValue("REGULAR-START");
        replace1.execute();

        Replace replace2 = (Replace) antProject.createTask("replace");
        replace2.setFile(existingFile);
        replace2.setToken("# -- " + nameInComment + "-END");
        replace2.setValue("REGULAR-END");
        replace2.execute();

        ReplaceRegExp regExpTask = (ReplaceRegExp) antProject.createTask("replaceregexp");
        regExpTask.setFile(existingFile);
        regExpTask.setMatch("REGULAR-START(?s:.)*REGULAR-END");
        regExpTask.setReplace("");
        regExpTask.setFlags("g");
        regExpTask.execute();
    }

    private static String adjustLineEndingsForOS(String property) {
        String os = System.getProperty("os.name");

        if (os.startsWith("Linux") || os.startsWith("Mac")) {
            // remove the \r returns
            property = property.replaceAll("\r", "");
        } else if (os.startsWith("Windows")) {
            // use windows line endings
            property = property.replaceAll(">\n", ">\r\n");
        }

        return property;
    }

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

    public Log getLog() {
        if (log == null) {
            log = new SystemStreamLog();
        }

        return log;
    }

    public void setProject(MavenProject project) {
        this.project = project;
    }

    public void setGenericCore(boolean genericCore) {
        this.genericCore = genericCore;
    }
}
TOP

Related Classes of org.appfuse.tool.ArtifactInstaller

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.