Package net.sourceforge.retroweaver.ant

Source Code of net.sourceforge.retroweaver.ant.RetroWeaverTask$Namespace

package net.sourceforge.retroweaver.ant;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.sourceforge.retroweaver.RefVerifier;
import net.sourceforge.retroweaver.RetroWeaver;
import net.sourceforge.retroweaver.event.VerifierListener;
import net.sourceforge.retroweaver.event.WeaveListener;
import net.sourceforge.retroweaver.translator.NameSpace;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.ExitStatusException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.DirSet;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
import org.objectweb.asm.commons.EmptyVisitor;

/**
* An Ant task for running RetroWeaver on a set of class files.
*/
public class RetroWeaverTask extends Task {

  ////////////////////////////////////////////////////////////////////////////////
  //  Constants and variables.

  /**
   * The destination directory for processd classes, or <code>null</code> for in place
   * processing.
   */
  private File itsDestDir;

  /**
   * Indicates if an error should cause the script to fail. Default to <code>true</code>.
   */
  private boolean itsFailOnError = true;

  /**
   * The set of files to be weaved.
   */
  private final List<FileSet> itsFileSets = new ArrayList<FileSet>();

  private final List<DirSet> itsDirSets = new ArrayList<DirSet>();

  private String inputJar;

  private String outputJar;

  /**
   * Indicates if classes should only be processed if their current version differ from the target version. Initially <code>true</code>.
   */
  private boolean itsLazy = true;

  /**
   * Indicates whether the generic signatures should be stripped. Default to <code>false</code>.
   */
  private boolean stripSignatures;

  /**
   * Indicates whether the custom retroweaver attributes should be stripped. Default to <code>false</code>.
   */
  private boolean stripAttributes;

  /**
   * Indicates if each processed class should be logged. Initially set to <code>false</code>.
   */
  private boolean itsVerbose = false;

  /**
   * The classpath to use to verify the weaved result
   */
  private Path verifyClasspath;

  private boolean verify = true;

  /**
   * The class file version number.
   */
  private int itsVersion = 48;

  /**
   * The class file version number.
   */
  private static final Map<String, Integer> itsVersionMap = new HashMap<String, Integer>();

  /**
   * Initialize the version map.
   */
  static {
    itsVersionMap.put("1.2", 46);
    itsVersionMap.put("1.3", 47);
    itsVersionMap.put("1.4", 48);
    itsVersionMap.put("1.5", 49);
  }

  ////////////////////////////////////////////////////////////////////////////////
  //  Property accessors and mutators.

  /**
   * Set the destination directory for processed classes. Unless specified the classes
   * are processed in place.
   * @param pDir The destination directory.
   */
  public void setDestDir(File pDir) {
    if (!pDir.isDirectory()) {
      throw new BuildException(
          "The destination directory doesn't exist: " + pDir,
          getLocation());
    }

    itsDestDir = pDir;
  }

  /**
   * Specify if an error should cause the script to fail. Default to <code>true</code>.
   *
   * @param pFailOnError <code>true</code> to fail, <code>false</code> to keep going.
   */
  public void setFailOnError(boolean pFailOnError) {
    itsFailOnError = pFailOnError;
  }

  /**
   * Add a set of files to be weaved.
   * @param pSet The fileset.
   */
  public void addFileSet(FileSet pFileSet) {
    itsFileSets.add(pFileSet);
  }

  public void addDirSet(DirSet pFileSet) {
    itsDirSets.add(pFileSet);
  }

  /**
   * Specify if classes should only be processed if their current version differ from the target version. Initially <code>true</code>.
   * @param pLazy <code>true</code> for lazy processing.
   */
  public void setLazy(boolean pLazy) {
    itsLazy = pLazy;
  }

  /**
   * Set the source directory containing classes to process. This is a shortcut to
   * using an embedded fileset with the specified base directory and which includes
   * all class files.
   * @param pDir The directory.
   */
  public void setSrcDir(File pDir) {
    FileSet fileSet = new FileSet();
    fileSet.setDir(pDir);
    fileSet.setIncludes("**/*.class");

    addFileSet(fileSet);
  }

  /**
   * Specify if each processed class should be logged. Initially set to <code>false</code>.
   * @param pVerbose <code>true</code> for verbose processing.
   */
  public void setVerbose(boolean pVerbose) {
    itsVerbose = pVerbose;
  }

  /**
   * Set the target class file version. Initially set to "1.4".
   * @param target The JDK target version, e&nbsp;g "1.3".
   */
  public void setTarget(String target) {
    Integer v = itsVersionMap.get(target);
    if (v == null) {
      throw new BuildException("Unknown target: " + target, getLocation());
    }
    itsVersion = v;
  }

  /**
   * Set the classpath to be used for verification.
   * Retroweaver will report any references to fields/methods/classes which don't appear
   * on refClassPath.
   * @param classpath an Ant Path object containing the compilation classpath.
   */
  public void setClasspath(Path classpath) {
    if (verifyClasspath == null) {
      verifyClasspath = classpath;
    } else {
      verifyClasspath.append(classpath);
    }
  }

  /**
   * Gets the classpath to be used for verification.
   * @return the class path
   public Path getClasspath() {
   return verifyClasspath;
   }

   /**
   * Adds a path to the classpath.
   * @return a class path to be configured
   */
  public Path createClasspath() {
    if (verifyClasspath == null) {
      verifyClasspath = new Path(getProject());
    }
    return verifyClasspath.createPath();
  }

  /**
   * Adds a reference to a classpath defined elsewhere.
   * @param r a reference to a classpath
   */
  public void setClasspathRef(Reference r) {
    createClasspath().setRefid(r);
  }

  /**
   * Turn off verification if desired
   * @return is verification enabled?
   */
  public void setVerify(boolean newVerify) {
    verify = newVerify;
  }

  /**
   * Turn off verification if desired
   * @return is verification enabled?
   */
  public boolean doVerify() {
    return verify;
  }

  /** NameSpace in translator package is immutable. Temporary values are
   * stored using this Namespace class.
   */
  public static final class Namespace {
    private String from;
    private String to;
    public String getFrom() { return from; }
    public void setFrom(String from) { this.from = from; }
    public String getTo() { return to; }
    public void setTo(String to) { this.to = to; }   
  }

  private List<Namespace> namespaces = new ArrayList<Namespace>();

  public Namespace createNameSpace() {
    Namespace n = new Namespace();
    namespaces.add(n);
    return n;
  }

  ////////////////////////////////////////////////////////////////////////////////
  //  Operations.

  /**
   * Run the RetroWeaver task.
   * @throws BuildException If a build exception occurs.
   */
  public void execute() throws BuildException {

    for (DirSet set : itsDirSets) {
      File baseDir = set.getDir(getProject());
      DirectoryScanner scanner = set.getDirectoryScanner(getProject());

      // create a non recursive file set for each included directory
      for (String fileName : scanner.getIncludedDirectories()) {
        FileSet fileSet = new FileSet();
        fileSet.setDir(new File(baseDir, fileName));
        fileSet.setIncludes("*.class");
        addFileSet(fileSet);
      }
    }

    //  Check arguments.

    boolean hasFileSet = !itsFileSets.isEmpty() || !itsDirSets.isEmpty();

    if (inputJar != null) {
      if (outputJar == null) {
        throw new BuildException("'outputjar' must be set.");
      }
      if (hasFileSet) {
        throw new BuildException(
            "'inputjar' is incompatible with filesets and dirsets");
      }
    } else if (!hasFileSet) {
      throw new BuildException(
          "Either attribute 'srcdir' or 'inputjar' must be used or atleast one fileset or dirset must be embedded.",
          getLocation());
    }
    //  Create and configure the weaver.

    RetroWeaver weaver = new RetroWeaver(itsVersion);
    weaver.setLazy(itsLazy);
    weaver.setStripSignatures(stripSignatures);
    weaver.setStripAttributes(stripAttributes);
   
    // Name space conversion
    List<NameSpace> l = new ArrayList<NameSpace>();
    for(Namespace n: namespaces) {
      l.add(new NameSpace(n.getFrom(), n.getTo()));
    }
    weaver.addNameSpaces(l);

    //  Set up a listener.
    weaver.setListener(new WeaveListener() {
      public void weavingStarted(String msg) {
        getProject().log(RetroWeaverTask.this, msg, Project.MSG_INFO);
      }

      public void weavingCompleted(String msg) {
        getProject().log(RetroWeaverTask.this, msg, Project.MSG_INFO);
      }

      public void weavingError(String msg) {
        getProject().log(RetroWeaverTask.this, msg, Project.MSG_ERR);
        throw new ExitStatusException("weaving error", 1);
      }

      public void weavingPath(String pPath) {
        if (itsVerbose) {
          getProject().log(RetroWeaverTask.this, "Weaving " + pPath,
              Project.MSG_INFO);
        }
      }
    });

    if (verifyClasspath != null && doVerify()) {

      List<String> refPath = new ArrayList<String>();

      for (String pathItem : verifyClasspath.list()) {
        refPath.add(pathItem);
      }
      if (itsDestDir != null) {
        refPath.add(itsDestDir.getPath());
      }

      RefVerifier rv = new RefVerifier(itsVersion, new EmptyVisitor(), refPath, new VerifierListener() {
        public void verifyPathStarted(String msg) {
          getProject().log(RetroWeaverTask.this, msg,
              Project.MSG_INFO);
        }

        public void verifyClassStarted(String msg) {
          if (itsVerbose) {
            getProject().log(RetroWeaverTask.this, msg, Project.MSG_INFO);
          }
        }

        public void acceptWarning(String msg) {
          getProject().log(RetroWeaverTask.this, msg, Project.MSG_WARN);
        }

        public void displaySummary(int warningCount) {
          String msg = "Verification complete, " + warningCount
              + " warning(s).";
          getProject().log(RetroWeaverTask.this, msg,
              Project.MSG_WARN);

          if (itsFailOnError) {
            throw new ExitStatusException(Integer
                .toString(warningCount)
                + " warning(s)", 1);
          }
        }
      });
      weaver.setVerifier(rv);
    }

    try {
      if (inputJar != null) {
        weaver.weaveJarFile(inputJar, outputJar);
      } else {
        //  Weave the files in the filesets.

        //  Process each fileset.
        String[][] fileSets = new String[itsFileSets.size()][];
        File[] baseDirs = new File[itsFileSets.size()];
        int i = 0;
        for (FileSet fileSet : itsFileSets) {
          //  Create a directory scanner for the fileset.
          File baseDir = fileSet.getDir(getProject());
          DirectoryScanner scanner = fileSet
              .getDirectoryScanner(getProject());
          fileSets[i] = scanner.getIncludedFiles();
          baseDirs[i++] = baseDir;
        }

        weaver.weave(baseDirs, fileSets, itsDestDir);
      }
    } catch (BuildException ex) {
      throw ex;
    } catch (Exception ex) {
      // unexpected exception
      throw new BuildException(ex, getLocation());
    }
  }

  /**
   * @return Returns the inputJar.
   */
  public String getInputJar() {
    return inputJar;
  }

  /**
   * @param inputJar The inputJar to set.
   */
  public void setInputJar(String inputJar) {
    this.inputJar = inputJar;
  }

  /**
   * @return Returns the outputJar.
   */
  public String getOutputJar() {
    return outputJar;
  }

  /**
   * @param outputJar The outputJar to set.
   */
  public void setOutputJar(String outputJar) {
    this.outputJar = outputJar;
  }

  /**
   * @param stripSignatures The stripSignatures to set.
   */
  public void setStripSignatures(boolean stripSignatures) {
    this.stripSignatures = stripSignatures;
  }

  /**
   * @param stripAttributes The stripAttributes to set
   */
  public void setStripAttributes(boolean stripAttributes) {
    this.stripAttributes = stripAttributes;
  }
}
TOP

Related Classes of net.sourceforge.retroweaver.ant.RetroWeaverTask$Namespace

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.