de.thischwa.pmcms.tool.InternalAntTool.java Source code

Java tutorial

Introduction

Here is the source code for de.thischwa.pmcms.tool.InternalAntTool.java

Source

/*******************************************************************************
 * Poor Man's CMS (pmcms) - A very basic CMS generating static html pages.
 * http://poormans.sourceforge.net
 * Copyright (C) 2004-2013 by Thilo Schwarz
 * 
 * == BEGIN LICENSE ==
 * 
 * Licensed under the terms of any of the following licenses at your
 * choice:
 * 
 *  - GNU Lesser General Public License Version 2.1 or later (the "LGPL")
 *    http://www.gnu.org/licenses/lgpl.html
 * 
 *  - Mozilla Public License Version 1.1 or later (the "MPL")
 *    http://www.mozilla.org/MPL/MPL-1.1.html
 * 
 * == END LICENSE ==
 ******************************************************************************/
package de.thischwa.pmcms.tool;

import java.io.File;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Properties;

import org.apache.commons.lang.StringUtils;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.DemuxOutputStream;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Delete;
import org.apache.tools.ant.taskdefs.Java;
import org.apache.tools.ant.taskdefs.Mkdir;
import org.apache.tools.ant.types.Commandline.Argument;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;

import de.thischwa.pmcms.Constants;
import de.thischwa.pmcms.tool.OS.OSDetector;

/**
 * Internal ant tool. Functions:
 * <ul>
 * <li>Start of pmcms. OS specific JVM-arguments are respected.
 * <li>Cleanup: Deletes all settings and data.
 * </ul>
 *
 * @author Thilo Schwarz
 */
public class InternalAntTool {

    /**
     * Starts poormans with respect of the current OS. Dependent on that, special JVM settings and environment variables
     * are set.
     * 
     * @param dataDir Data directory to use for.
     * @param props Properties to use for.
     * @param starterClass
     * @param printDebug if true additional logging informations will be print out at stdio.
     * @param additionalArgs Additional poormans commandline arguments. Can be <tt>null</tt> or empty.
     */
    public static void start(final File dataDir, final Properties props, final String starterClass,
            boolean printDebug, final String[] additionalArgs) {
        OSDetector.Type os = OSDetector.getType(); // Throws a RuntimeException, if os isn't supported!
        Project project = buildProject();
        List<String> jvmArgs = new ArrayList<String>();
        if (props.getProperty("jvm.arguments") != null) {
            String args = props.getProperty("jvm.arguments");
            if (printDebug)
                project.log("Raw JVM argements: " + args);
            jvmArgs = new ArrayList<String>(Arrays.asList(StringUtils.split(args)));
        }
        Throwable caught = null;
        String propLib = props.getProperty("pmcms.dir.lib");
        String propLibSwt = props.getProperty("pmcms.dir.lib.swt");
        if (printDebug) {
            project.log("Java: " + System.getProperty("java.version"));
            project.log("OS: " + os);
            project.log("Starter class: " + starterClass);
            project.log("Lib-folder: " + propLib);
            project.log("Lib-swt-folder: " + propLibSwt);
        }
        int retVal = -1;
        try {
            /** initialize an java task **/
            Java javaTask = new Java();
            javaTask.setNewenvironment(true);
            javaTask.setTaskName("runjava");
            javaTask.setProject(project);
            javaTask.setFork(true);
            javaTask.setFailonerror(true);
            javaTask.setClassname(starterClass);

            /** build the class path */
            Path classPath = new Path(project);
            javaTask.setClasspath(classPath);
            FileSet libFileSet = new FileSet();
            libFileSet.setDir(new File(Constants.APPLICATION_DIR, propLib));
            libFileSet.setIncludes("**/*jar,**/*properties");

            /** build the requested swt-jar */
            boolean enable64bit = Boolean.parseBoolean(props.getProperty("pmcms.64bit"));
            String swt64bitAddOn = (enable64bit) ? "_64" : "";
            if (printDebug)
                project.log(String.format("Requested swt-arch: %sbit", (enable64bit) ? "64" : "32"));

            String swtFolderRaw;
            switch (os) {
            case MAC:
                swtFolderRaw = "cocoa-macosx%s";
                break;
            case LINUX:
                swtFolderRaw = "gtk-linux-x86%s";
                break;
            default:
                swtFolderRaw = "win32-win32-x86%s";
            }
            swtFolderRaw = String.format("%s/%s", propLibSwt, swtFolderRaw);
            String swtFolder = String.format(swtFolderRaw, swt64bitAddOn);
            File swtDir = new File(Constants.APPLICATION_DIR, swtFolder);
            if (printDebug)
                project.log(String.format("Swt-directory: %s", swtDir.getPath()));
            FileSet swtFileSet = new FileSet();
            swtFileSet.setDir(swtDir);
            swtFileSet.setIncludes("*jar");
            classPath.addFileset(swtFileSet);
            classPath.addFileset(libFileSet);
            if (printDebug)
                project.log("Classpath: " + classPath);

            // add some vm args dependent on the os 
            switch (os) {
            case MAC:
                if (!jvmArgs.contains("-XstartOnFirstThread"))
                    jvmArgs.add("-XstartOnFirstThread");
                break;
            case WIN:
                String arg = String.format("-Djava.library.path=%s", swtFolder);
                jvmArgs.add(arg);
                break;
            case LINUX:
                // no special properties required, setting be done by jvm args 
                break;
            default:
                project.log("Error: Unknown OS: " + OSDetector.getOSString());
                System.exit(3);
                break;
            }

            // add jvm args if exists
            if (!jvmArgs.isEmpty()) {
                // clean-up the jvm-args and ensure that each one starts with '-D' or '-X'
                List<String> tmpArgs = new ArrayList<String>();
                for (String arg : jvmArgs) {
                    if (arg.startsWith("-D") || arg.startsWith("-d") || arg.startsWith("-X")
                            || arg.startsWith("-x"))
                        tmpArgs.add(arg);
                }
                jvmArgs.clear();
                jvmArgs.addAll(tmpArgs);
                // build the args line and replace inline-variables
                String jvmArgsLine = StringUtils.join(jvmArgs, ' ');
                Argument argument = javaTask.createJvmarg();
                argument.setLine(jvmArgsLine);
                if (printDebug)
                    project.log("JVM args: " + jvmArgsLine);
            }

            // add some program args if exists
            String strArgs = String.format("-datadir \"%s\"", dataDir);
            if (additionalArgs != null && additionalArgs.length > 0)
                strArgs += " " + StringUtils.join(additionalArgs, ' ');
            Argument taskArgs = javaTask.createArg();
            taskArgs.setLine(strArgs);
            if (printDebug)
                project.log("Program-args: " + strArgs);

            // call the java task
            javaTask.init();
            retVal = javaTask.executeJava();
        } catch (Exception e) {
            caught = e;
        }
        if (caught != null)
            project.log("Error while starting poormans: " + caught.getMessage(), caught, Project.MSG_ERR);
        else if (retVal != 0 && caught == null)
            project.log("finished with code: " + retVal);
        else
            project.log("successful finished");
        project.fireBuildFinished(caught);
    }

    /**
     * Task to clean up all the generated data and setting. The database will be rebuild. 
     * 
     * @param dataDir Data directory to use for.
     * @param props Properties to use for.
     */
    public static void cleanup(final File dataDir, final Properties props) {
        Project project = buildProject();
        Throwable caught = null;
        try {
            File sitesDir = new File(dataDir, props.getProperty("pmcms.dir.sites"));

            // delete the files
            deleteFile(project, new File(dataDir, ".settings.properties"));
            deleteDir(project, sitesDir);

            // make the required directories
            mkdir(project, new File(dataDir, "sites"));
        } catch (Exception e) {
            caught = e;
        }
        if (caught != null)
            project.log("Error while cleanung up: " + caught.getMessage(), caught, Project.MSG_ERR);
        else
            project.log("successful finished");
        project.fireBuildFinished(caught);
    }

    /**
     * Initializes an ant project. The base directory is the current working directory.
     * 
     * @return Ant project.
     */
    private static Project buildProject() {
        Project project = new Project();
        project.setBasedir(System.getProperty("user.dir"));
        project.init();
        DefaultLogger logger = new DefaultLogger();
        project.addBuildListener(logger);
        logger.setOutputPrintStream(System.out);
        logger.setErrorPrintStream(System.err);
        logger.setMessageOutputLevel(Project.MSG_VERBOSE);
        System.setOut(new PrintStream(new DemuxOutputStream(project, false)));
        System.setErr(new PrintStream(new DemuxOutputStream(project, true)));
        project.fireBuildStarted();
        return project;
    }

    /*
    private static Environment.Variable buildVar(final String key, final String val) {
       Environment.Variable var = new Environment.Variable();
       var.setKey(key);
       var.setValue(val);
       return var;
    }
    */

    private static void deleteDir(Project project, File dir) {
        Delete deleteTask = new Delete();
        deleteTask.setProject(project);
        deleteTask.setTaskName("delete dir");
        deleteTask.setDir(dir);
        deleteTask.execute();
    }

    private static void deleteFile(Project project, File file) {
        Delete deleteTask = new Delete();
        deleteTask.setProject(project);
        deleteTask.setTaskName("delete file");
        deleteTask.setFile(file);
        deleteTask.execute();
    }

    private static void mkdir(Project project, File dir) {
        Mkdir mkdir = new Mkdir();
        mkdir.setProject(project);
        mkdir.setTaskName("mkdir");
        mkdir.setDir(dir);
        mkdir.execute();
    }
}