Package org.moxie.ant

Source Code of org.moxie.ant.Main$NewProject

/*
* Copyright 2012 James Moger
*
* 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.moxie.ant;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.tools.ant.BuildEvent;
import org.apache.tools.ant.BuildListener;
import org.apache.tools.ant.Project;
import org.eclipse.jgit.api.AddCommand;
import org.eclipse.jgit.api.CommitCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.InitCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.StoredConfig;
import org.moxie.MoxieException;
import org.moxie.Scope;
import org.moxie.Toolkit;
import org.moxie.Toolkit.Key;
import org.moxie.maxml.Maxml;
import org.moxie.maxml.MaxmlException;
import org.moxie.maxml.MaxmlMap;
import org.moxie.utils.FileUtils;
import org.moxie.utils.StringUtils;

public class Main extends org.apache.tools.ant.Main implements BuildListener {
 
  NewProject newProject = null;

    /**
     * Command line entry point. This method kicks off the building
     * of a project object and executes a build using either a given
     * target or the default target.
     *
     * @param args Command line arguments. Must not be <code>null</code>.
     */
    public static void main(String[] args) {
        start(args, null, null);
    }
   
    /**
     * Creates a new instance of this class using the
     * arguments specified, gives it any extra user properties which have been
     * specified, and then runs the build using the classloader provided.
     *
     * @param args Command line arguments. Must not be <code>null</code>.
     * @param additionalUserProperties Any extra properties to use in this
     *        build. May be <code>null</code>, which is the equivalent to
     *        passing in an empty set of properties.
     * @param coreLoader Classloader used for core classes. May be
     *        <code>null</code> in which case the system classloader is used.
     */
    public static void start(String[] args, Properties additionalUserProperties,
                             ClassLoader coreLoader) {
        Main m = new Main();
        m.startAnt(args, additionalUserProperties, coreLoader);
    }


  /*
   * (non-Javadoc)
   *
   * @see org.apache.tools.ant.Main#startAnt(java.lang.String[],
   * java.util.Properties, java.lang.ClassLoader)
   */
  @Override
  public void startAnt(String[] args, Properties additionalUserProperties, ClassLoader coreLoader) {
    boolean startAnt = true;
    boolean specifiedBuildFile = false;
    List<String> antArgs = new ArrayList<String>(Arrays.asList(args));
    if (antArgs.contains("-color")) {
      antArgs.remove("-color");
      System.setProperty(Toolkit.MX_COLOR, "true");
    }
    if (antArgs.contains("-c")) {
      antArgs.remove("-c");
      System.setProperty(Toolkit.MX_COLOR, "true");
    }
    if (antArgs.contains("-debug") || antArgs.contains("-d")) {
      System.setProperty(Toolkit.MX_DEBUG, "true");
    }
    if (antArgs.contains("-verbose") || antArgs.contains("-v")) {
      System.setProperty(Toolkit.MX_VERBOSE, "true");
    }
    if (antArgs.contains("-updateMetadata")) {
      antArgs.remove("-updateMetadata");
      System.setProperty(Toolkit.MX_UPDATEMETADATA, "true");
    }
    if (antArgs.contains("-ignoreChecksums")) {
      antArgs.remove("-ignoreChecksums");
      System.setProperty(Toolkit.MX_ENFORCECHECKSUMS, "false");
    }
    if (antArgs.contains("-offline")) {
      antArgs.remove("-offline");
      System.setProperty(Toolkit.MX_ONLINE, "false");
    }

    for (int i = 0; i < args.length; i++) {
      String arg = args[i];

      if (arg.equals("-help") || arg.equals("-h")) {
        printUsage();
        startAnt = false;
      } else if (arg.equals("-version")) {
        printVersion();
        startAnt = false;
      } else if (arg.equals("-new")) {
        // create new project
        antArgs.remove(arg);
        newProject = newProject(antArgs);
       
        // run the init phase on the new project
        antArgs = Arrays.asList(
            "phase:init",
            "-Dbasedir=" + newProject.dir.getAbsolutePath().replace('\\', '/'),
            "-f",
            new File(newProject.dir, "build.xml").getAbsolutePath().replace('\\', '/'));
        break;
      } else if (arg.equals("-f") || arg.equals("-buildfile") || arg.equals("-file")) {
        specifiedBuildFile = true;
      }
    }

    if (startAnt) {
      List<String> moxieArgs = new ArrayList<String>();     
          moxieArgs.add("-logger");
          moxieArgs.add(MainLogger.class.getName());
          if (!specifiedBuildFile) {
            File file = new File(System.getProperty("user.dir"), "build.xml");
            if (file.exists()) {
              // standard local build.xml
              moxieArgs.add("-f");
              moxieArgs.add("build.xml");
            } else {
              // missing build file, use minimal file
              try {
                  InputStream is = getClass().getResourceAsStream("/archetypes/build.xml");
                 
                  ByteArrayOutputStream os = new ByteArrayOutputStream();
                  byte [] buffer = new byte[4096];
                  int len = 0;
                  while((len = is.read(buffer)) > -1) {
                    os.write(buffer, 0, len);
                  }
                  String content = os.toString("UTF-8");
                  os.close();
                  is.close();
                 
                  file = File.createTempFile("build-", ".xml", new File(System.getProperty("user.dir")));
                  file.deleteOnExit();
                  FileUtils.writeContent(file, content);
                 
                moxieArgs.add("-f");
                moxieArgs.add(file.getAbsolutePath());               
                } catch (Throwable t) {
                  t.printStackTrace();
                  System.exit(1);
                }
            }
          }
          moxieArgs.addAll(antArgs);
          String [] newArgs = moxieArgs.toArray(new String[moxieArgs.size()]);
      super.startAnt(newArgs, additionalUserProperties, coreLoader);
    }
  }
 
  @Override
  protected void addBuildListeners(Project project) {
    project.addBuildListener(this);
    super.addBuildListeners(project);
  }
 
  private void printVersion() {
    System.out.println();
    System.out.println("Moxie+Ant v" + Toolkit.getVersion());
    System.out.println("executing on " + getAntVersion());
    System.out.println();
  }
 
     /**
     * Prints the usage information for this class to <code>System.out</code>.
     */
    private void printUsage() {
        String lSep = System.getProperty("line.separator");
        StringBuilder msg = new StringBuilder();
        msg.append("moxie [options] [target [target2 [target3] ...]]" + lSep);
        msg.append("Options: " + lSep);
        msg.append("  -help, -h              print this message" + lSep);
        msg.append("  -projecthelp, -p       print project help information" + lSep);
        msg.append("  -version               print the version information and exit" + lSep);
        msg.append("  -diagnostics           print information that might be helpful to" + lSep);
        msg.append("                         diagnose or report problems." + lSep);
        msg.append(lSep);
        msg.append("  -new -<archetype> <groupId>:<artifactId>:<version> -dir:<dirname> -git<:originId> -eclipse<:+var> -intellij" + lSep);
        msg.append(lSep);
        msg.append("  -offline               do not contact any remote repositories" + lSep);
        msg.append("  -ignoreChecksums       disable SHA1 checksum verification" + lSep);
        msg.append("  -updateMetadata        force metadata updates" + lSep);
        msg.append("  -color, -c             use ANSI color sequences" + lSep);
        msg.append("  -quiet, -q             be extra quiet" + lSep);
        msg.append("  -verbose, -v           be extra verbose" + lSep);
        msg.append("  -debug, -d             print debugging information" + lSep);
        msg.append("  -emacs, -e             produce logging information without adornments"
                   + lSep);
        msg.append("  -lib <path>            specifies a path to search for jars and classes"
                   + lSep);
        msg.append("  -logfile <file>        use given file for log" + lSep);
        msg.append("    -l     <file>                ''" + lSep);
        msg.append("  -logger <classname>    the class which is to perform logging" + lSep);
        msg.append("  -listener <classname>  add an instance of class as a project listener"
                   + lSep);
        msg.append("  -noinput               do not allow interactive input" + lSep);
        msg.append("  -buildfile <file>      use given buildfile" + lSep);
        msg.append("    -file    <file>              ''" + lSep);
        msg.append("    -f       <file>              ''" + lSep);
        msg.append("  -D<property>=<value>   use value for given property" + lSep);
        msg.append("  -keep-going, -k        execute all targets that do not depend" + lSep);
        msg.append("                         on failed target(s)" + lSep);
        msg.append("  -propertyfile <name>   load all properties from file with -D" + lSep);
        msg.append("                         properties taking precedence" + lSep);
        msg.append("  -inputhandler <class>  the class which will handle input requests" + lSep);
        msg.append("  -find <file>           (s)earch for buildfile towards the root of" + lSep);
        msg.append("    -s  <file>           the filesystem and use it" + lSep);
        msg.append("  -nice  number          A niceness value for the main thread:" + lSep
                   + "                         1 (lowest) to 10 (highest); 5 is the default"
                   + lSep);
        msg.append("  -nouserlib             Run Moxie without using the jar files from" + lSep
                   + "                         ${user.home}/.ant/lib" + lSep);
        msg.append("  -noclasspath           Run Moxie without using CLASSPATH" + lSep);
        msg.append("  -autoproxy             Java1.5+: use the OS proxy settings"
                + lSep);
        msg.append("  -main <class>          override Moxie's normal entry point");
        System.out.println(msg.toString());
    }
   
   
    /**
     * Creates a new Moxie project in the current folder.
     *
     * @param args
     */
    private NewProject newProject(List<String> args) {
      File basedir = new File(System.getProperty("user.dir"));
      File moxieFile = new File(basedir, "build.moxie");
      if (moxieFile.exists()) {
        log("build.moxie exists!  Can not create new project!");
        System.exit(1);
      }
     
      NewProject project = new NewProject();
      project.dir = basedir;
     
      List<String> apply = new ArrayList<String>();
     
      // parse args
      if (args.size() > 0) {
        List<String> projectArgs = new ArrayList<String>();
        for (String arg : args) {
          if (arg.startsWith("-git")) {
            project.initGit = true;
            if (arg.startsWith("-git:"))  {
              project.gitOrigin = arg.substring(5);
            }
          } else if (arg.startsWith("-eclipse")) {
            if (args.contains("+var")) {
                // Eclipse uses variable-relative paths
              project.eclipse = Eclipse.var;
          } else if (args.contains("+ext")) {
                // Eclipse uses project-relative paths
              project.eclipse = Eclipse.ext;
            } else {
                // Eclipse uses hard-coded paths to MOXIE_HOME in USER_HOME
              project.eclipse = Eclipse.user;
            }
            apply.add(arg.substring(1));
          } else if (arg.startsWith("-intellij")) {
             project.idea = IntelliJ.var;
            apply.add(arg.substring(1));
          } else if (arg.startsWith("-apply:")) {
            // -apply:a,b,c,d
            // -apply:a -apply:b
            List<String> vals = new ArrayList<String>();
            for (String val : arg.substring(arg.indexOf(':') + 1).split(",")) {
              vals.add(val.trim());
            }
            apply.addAll(vals);
           
            // special apply cases
            for (String val : vals) {
              if (val.startsWith(Toolkit.APPLY_ECLIPSE)) {
                if (args.contains("+var")) {
                      // Eclipse uses variable-relative paths
                    project.eclipse = Eclipse.var;
                } else if (args.contains("+ext")) {
                         // Eclipse uses project-relative paths
                       project.eclipse = Eclipse.ext;
                } else {
                    // Eclipse uses hard-coded paths to MOXIE_HOME in USER_HOME
                    project.eclipse = Eclipse.user;
                }
                        } else if (val.equals(Toolkit.APPLY_INTELLIJ)) {
                   project.idea = IntelliJ.var;
                        }
            }
          } else if (arg.startsWith("-dir:")) {
            String dir = arg.substring("-dir:".length()).trim();
            project.dir = new File(basedir, dir);
          } else {
            projectArgs.add(arg);
          }
        }
       
        // parse
        project.type = projectArgs.get(0);
        if (project.type.charAt(0) == '-') {
          project.type = project.type.substring(1);
        }
        if (projectArgs.size() > 1) {
          String [] fields = projectArgs.get(1).split(":");
          switch (fields.length) {
          case 2:
            project.groupId = fields[0];
            project.artifactId = fields[1];
            break;
          case 3:
            project.groupId = fields[0];
            project.artifactId = fields[1];
            project.version = fields[2];
            break;
          default:
            throw new MoxieException("Illegal parameter " + args);
          }
        }
      }
     
      InputStream is = getClass().getResourceAsStream(MessageFormat.format("/archetypes/{0}.moxie", project.type));
      if (is == null) {
        log("Unknown archetype " + project.type);
        System.exit(1);
      }
      MaxmlMap map = null;
      try {
      map = Maxml.parse(is);
    } catch (MaxmlException e) {
      e.printStackTrace();
    } finally {
      try {
        is.close();
      } catch (Exception e) {
      }
    }
     
      // property substitution
      Map<String, String> properties = new HashMap<String, String>();
      properties.put(Key.groupId.name(), project.groupId);
      properties.put(Key.artifactId.name(), project.artifactId);
      properties.put(Key.version.name(), project.version);
      properties.put(Key.apply.name(), StringUtils.flattenStrings(apply, ", "));
      for (String key : map.keySet()) {
        Object o = map.get(key);
        if (o instanceof String) {
          String value = resolveProperties(o.toString(), properties);
          map.put(key, value);
        }
      }
     
      createDirectories(project, map, Key.sourceDirectories);
      createDirectories(project, map, Key.resourceDirectories);
     
      // Eclipse-ext dependency directory
      if (Eclipse.ext.equals(project.eclipse)) {
        map.put(Toolkit.Key.dependencyDirectory.name(), "ext");
      }

      // write build.moxie
      String maxml = map.toMaxml();
    moxieFile = new File(project.dir, "build.moxie");
      FileUtils.writeContent(moxieFile, maxml);
     
      // write build.xml
      try {
        is = getClass().getResourceAsStream(MessageFormat.format("/archetypes/{0}.build.xml", project.type));
       
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        byte [] buffer = new byte[4096];
        int len = 0;
        while((len = is.read(buffer)) > -1) {
          os.write(buffer, 0, len);
        }
        String prototype = os.toString("UTF-8");
        os.close();
        is.close();
       
        String content = prototype;
        content = content.replace("%MOXIE_VERSION%", Toolkit.getVersion());
        content = content.replace("%MOXIE_URL%", Toolkit.getMavenUrl());
        FileUtils.writeContent(new File(project.dir, "build.xml"), content);
      } catch (Throwable t) {
        t.printStackTrace();
        System.exit(1);
      }
     
      return project;
    }
   
    private void createDirectories(NewProject project, MaxmlMap map, Key key) {
      List<String> dirs = map.getStrings(key.name(), Arrays.asList(new String [0]));
      for (String scopedDir : dirs) {
        String s = scopedDir.substring(0, scopedDir.indexOf(' ')).trim();
        Scope scope = Scope.fromString(s);
        if (scope.isValidSourceScope()) {
          String folder = StringUtils.stripQuotes(scopedDir.substring(s.length() + 1).trim());
            File file = new File(project.dir, folder);
            file.mkdirs();
        } else {
          log("Illegal " + key.name() + " scope: " + s);
        }
      }
    }
   
    private void initGit() throws GitAPIException {
      // create the repository
      InitCommand init = Git.init();
      init.setBare(false);
      init.setDirectory(newProject.dir);
      Git git = init.call();
     
      if (!StringUtils.isEmpty(newProject.gitOrigin)) {
        // set the origin and configure the master branch for merging
        StoredConfig config = git.getRepository().getConfig();
        config.setString("remote", "origin", "url", getGitUrl());
        config.setString("remote""origin", "fetch", "+refs/heads/*:refs/remotes/origin/*");
        config.setString("branch""master", "remote", "origin");
        config.setString("branch""master", "merge", "refs/heads/master");
        try {
        config.save();
      } catch (IOException e) {
        throw new MoxieException(e);
      }
      }

      // prepare a common gitignore file
      StringBuilder sb = new StringBuilder();
      sb.append("/.directory\n");
      sb.append("/.DS_STORE\n");
      sb.append("/.DS_Store\n");
      sb.append("/.settings\n");
      sb.append("/bin\n");
      sb.append("/build\n");
      sb.append("/ext\n");
      sb.append("/target\n");
      sb.append("/tmp\n");
      sb.append("/temp\n");
      if (!newProject.eclipse.includeClasspath()) {
        // ignore hard-coded .classpath
        sb.append("/.classpath\n")
      }
      FileUtils.writeContent(new File(newProject.dir, ".gitignore"), sb.toString());
     
      AddCommand add = git.add();
      add.addFilepattern("build.xml");
      add.addFilepattern("build.moxie");
      add.addFilepattern(".gitignore");
      if (newProject.eclipse.includeProject()) {
        add.addFilepattern(".project")
      }
      if (newProject.eclipse.includeClasspath()) {
        // MOXIE_HOME relative dependencies in .classpath
        add.addFilepattern(".classpath")
      }
        if (newProject.idea.includeProject()) {
            add.addFilepattern(".project");
        }
        if (newProject.idea.includeClasspath()) {
            // MOXIE_HOME relative dependencies in .iml
            add.addFilepattern("*.iml");
        }
      try {
        add.call();
        CommitCommand commit = git.commit();
        PersonIdent moxie = new PersonIdent("Moxie", "moxie@localhost");
        commit.setAuthor(moxie);
        commit.setCommitter(moxie);
        commit.setMessage("Project structure created");
        commit.call();
      } catch (Exception e) {
        throw new MoxieException(e);
      }
    }
   
    String resolveProperties(String string, Map<String, String> properties) {
    if (string == null) {
      return null;
    }
    Pattern p = Pattern.compile("\\$\\{[a-zA-Z0-9-_\\.]+\\}");     
    StringBuilder sb = new StringBuilder(string);
    while (true) {
      Matcher m = p.matcher(sb.toString());
      if (m.find()) {
        String prop = m.group();
        prop = prop.substring(2, prop.length() - 1);
        String value = prop;
        if (properties.containsKey(prop)) {
          value = properties.get(prop);
        }
        sb.replace(m.start(), m.end(), value);
      } else {
        return sb.toString();
      }
    }   
  }
   
    /**
     * Returns a git url from the specified url which may use aliases.
     *
     * @return a url
     */
    private String getGitUrl() {
      String url = newProject.gitOrigin;
      String repo = newProject.gitOrigin.substring(url.indexOf("://") + 3);
     
    File root = Toolkit.getMxRoot();
      File gitAliases = new File(root, "git.moxie");
      if (gitAliases.exists()) {
        try {
          MaxmlMap map = Maxml.parse(gitAliases);
          // look for protocol alias matches
          for (String alias : map.keySet()) {
            // ensure alias is legal
            if ("ftp".equals(alias)
                || "http".equals(alias)
                || "https".equals(alias)
                || "git".equals(alias)
                || "ssh".equals(alias)) {
              error(MessageFormat.format("Illegal repository alias \"{0}\"!", alias));
              continue;
            }
           
            // look for alias match
            String proto = alias + "://";
            if (url.startsWith(proto)) {
              String baseUrl = map.getString(alias, "");
              if (baseUrl.charAt(baseUrl.length() - 1) != '/') {
                return baseUrl + '/' + repo;
              }
              return baseUrl + repo;
            }
          }
        } catch (Exception e) {
          throw new MoxieException(e);
        }
      }
      return url;
    }
   
    private void log(String msg) {
      System.out.println(msg);
    }

    private void error(String msg) {
      System.err.println(msg);
    }

    private enum Eclipse {
      none, user, var, ext;
     
      boolean includeProject() {
        return this.ordinal() > none.ordinal();
      }
     
      boolean includeClasspath() {
        return this.ordinal() > user.ordinal();
      }
    }

    private enum IntelliJ {
        none, var;

        boolean includeProject() {
            return this.ordinal() > none.ordinal();
        }

        boolean includeClasspath() {
            return true;
        }
    }
   
    private class NewProject {
      String type = "jar";
      String groupId = "mygroup";
      String artifactId = "artifact";
      String version = "0.0.0-SNAPSHOT";
      boolean initGit = false;
      String gitOrigin;
      Eclipse eclipse = Eclipse.none;
        IntelliJ idea = IntelliJ.none;
      File dir;
    }

  @Override
  public void buildStarted(BuildEvent event) {
  }

  @Override
  public void buildFinished(BuildEvent event) {
    if (newProject != null && newProject.initGit) {
      // init Git repository after running moxie.init
      try {
        initGit();
      } catch (GitAPIException e) {
        throw new RuntimeException(e);
      }
    }
  }

  @Override
  public void targetStarted(BuildEvent event) {
  }

  @Override
  public void targetFinished(BuildEvent event) {
  }

  @Override
  public void taskStarted(BuildEvent event) {
  }

  @Override
  public void taskFinished(BuildEvent event) {
  }

  @Override
  public void messageLogged(BuildEvent event) {
  }
}
TOP

Related Classes of org.moxie.ant.Main$NewProject

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.