Re: [aspectwerkz-dev] AnnotationC task and anonymous inner class
the_mindstorm <[email protected]> Tue, 12 Oct 2004 13:06:04 +0300
| Newsgroups | gmane.comp.java.aspectwerkz.devel |
|---|---|
| Message-ID | <[email protected]> |
Attached is the new version of AnnotationCTask. 1. I have fixed a little problem in source fileset manipulation 2. I have added support for copying the annonymous inner classes if destdir is used. (currently I have used a matching pattern that will copy only 99 annonymous inner classes per source - I think it is enough). 3. I have added support for copying the resources from the clsdir-s to destdir in case this is used. (copyResources attribute for the task). I can see for the moment one drawback for this. Consider the following project structure - src1: sources dir (compiled to cls) - src2: sources dir (compiled to cls) - cls: classes dir - dest: destination for AnnotationCTask If i will use the AnnotationCTask only on sources from src1, i will have in the dest dir the annonymous inner classes resulted from the compilation of src2 sources too. I have tried to solve this problem, following to copy only the annonymous inner classes for the sources provided to AnnotationCTask. But as far a compilation unit (a source file) may contain more than 1 class there is no way to track this. So I concluded that it is better to have more then less necessary classes :-(. I am waiting for your opinions. ./the_mindstorm Quote [Alexandre Vasseur]: > fine > go for it, just copy the .class files > > plz start a new thread for the javadoc stuff. I had time to do some > brainstorming with my self :-) > Alex > > > On Sat, 09 Oct 2004 23:50:31 +0300, the_mindstorm > <[email protected]> wrote: >> Quote [Alexandre Vasseur]: >> > i d rather have the equivalent of the Ant snip posted here >> > (f.e. if you have .dtd / .xml / .properties stuff in your src dir then >> > everything is preserved.) >> > Alex >> >> While I see the need for copying anonymous inner classes into the target directory directly from the >> Ant task, I cannot see why such a task would manage resources. Usually this is done by another task >> allowing filtering (or more complex tasks: replacing ,etc). >> Afaik the only tool doing this automatically is the Eclipse builder (but I do not always agree this >> being a good solution. For example I have some properties file that go inside the final jar and they >> contain tokens to be replaced). >> >> Surely the task is an easy one to be done, but I would like to clarify the needs before doing it. A >> solution that will be more configurable would be to present in the task another property >> (copyResources) to trigger this additional step. (I think I remember this option in AJ). >> >> ./the_mindstorm >> >> PS: unfortunately I wasn't able to finish today the AspectWerkzCTask, but I hope tomorrow will be a >> more quiet day that will allow me to finish it. >> >> PPS: while thinking of this I have remember at some point we have started a discussion about >> generating AOP-ish javadoc. I would like to re-start this in order to allow me to start working on >> it. What do you think? >> >> >> >> >> > >> > >> > On Sat, 09 Oct 2004 17:20:08 +0300, the_mindstorm >> > <[email protected]> wrote: >> >> Quote [Alexandre Vasseur]: >> >> >> >> > exact ! >> >> > Thanks for remembering that Allan >> >> > The AnnotationCTask is indeed the right place for it. >> >> > Alex >> >> > >> >> >> >> yep i will fix this asap. But i guess i could copy only the <name>$<name>.class, ain't it? >> >> >> >> >> >> ./the_mindstorm >> >> >> >> >> >> >> >> > >> >> > On Sat, 9 Oct 2004 09:12:17 -0300, Allan Jones <[email protected]> wrote: >> >> >> one day, I wrote: >> >> >> >> >> >> "One minor bug. >> >> >> When we use "-dest" in AnnotationC, Anonymous Inner Classes are not >> >> >> copied to dest directory. When we run our classes, >> >> >> java.lang.NoClassDefFoundError occurs" >> >> >> >> >> >> and Alexandre Vasseur said: >> >> >> >> >> >> "Ok the AnnotationC issue cannot be solved in the framework. >> >> >> >> >> >> Anonymous inner classes are not parsed by Qdox that is used to parse >> >> >> the source code (note: cannot handle annotation on anonymous inner >> >> >> class neither by the way). Thus the anonymous inner class is not >> >> >> analyzed by AnnotationC. >> >> >> >> >> >> So when using -dest flag, add the following just after the call to >> >> >> AnnotationC in your Ant script: >> >> >> <copy todir="classes/annotated" overwrite="false"> >> >> >> <fileset dir="classes/regular"/> >> >> >> </copy>" >> >> >> >> >> >> Now that you´re doing an ant task, the task could resolve this problem >> >> >> by copying the missing classes to the dest dir. >> >> >> >> >> >> -- >> >> >> Allan Jones >> >> >> Summa Technologies do Brasil ltda. >> >> >> >> >> > >> >> >> >> >> > >> >> >
AnnotationCTask.java
(text/plain, 8.2 KB)
/************1************************************************************************** * Copyright (c) Jonas Bonér, Alexandre Vasseur. All rights reserved. * * http://aspectwerkz.codehaus.org * * ---------------------------------------------------------------------------------- * * The software in this package is published under the terms of the LGPL license * * a copy of which has been included with this distribution in the license.txt file. * **************************************************************************************/ package org.codehaus.aspectwerkz.annotation; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.DirectoryScanner; import org.apache.tools.ant.Project; import org.apache.tools.ant.Task; import org.apache.tools.ant.taskdefs.Copy; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.PatternSet; /** * AnnotationC Ant task. * * @author <a href='mailto:[email protected]'>the_mindstorm(at)evolva(dot)ro</a> */ public class AnnotationCTask extends Task { private static final int SRC_NOTSET = 0; private static final int SRC_FILESET = 1; private static final int SRC_DIR = 2; private static final int SRC_DIRPATH = 3; private static final int SRC_FILE = 4; private static final String[] MSG = {"", "srcfileset", "srcdir", "inner src", "srcincludes"}; private static final String[] COPY_ANONYMOUS_INNER_PATTERN = {"**/*$?.class","**/*$??.class"}; private static final String COPY_ALL_PATTERN = "**/*"; private static final String EXCLUDE_CLASS_PATTERN = "**/*.class"; protected Path classpath; protected boolean verbose; protected Path srcdir; protected List filesets = new ArrayList(); protected File srcincludes; protected Path clsdir; protected File properties; protected File destdir; protected boolean copyResources; // deal with duplicated parameters protected int srcParamType = SRC_NOTSET; public void setCopyResources(boolean copy) { this.copyResources = copy; } public void setVerbose(boolean isVerbose) { this.verbose = true; } public void setDestdir(File destdir) { this.destdir = destdir; } public Path createSrc() { if(isSet(SRC_DIRPATH)) { throw tooManyParameters(SRC_DIRPATH); } if(srcdir == null) { srcdir = new Path(getProject()); } return srcdir.createPath(); } public void setSrcdir(Path srcdir) { if(isSet(SRC_DIR)) { throw tooManyParameters(SRC_DIR); } if(this.srcdir == null) { this.srcdir = srcdir; } else { this.srcdir.append(srcdir); } } public void setSrcincludes(File srcinclude) { if(isSet(SRC_FILE)) { throw tooManyParameters(SRC_FILE); } this.srcincludes = srcinclude; } public void addSrcfileset(FileSet set) { if(isSet(SRC_FILESET)) { throw tooManyParameters(SRC_FILESET); } this.filesets.add(set); } public Path createCls() { if(this.clsdir == null) { clsdir = new Path(getProject()); } return clsdir.createPath(); } public void setClsdir(Path clsdir) { if(this.clsdir == null) { this.clsdir = clsdir; } else { this.clsdir.append(clsdir); } } public void setProperties(File annotationFile) { this.properties = annotationFile; } public void execute() throws BuildException { try { if((this.srcdir == null || this.srcdir.size() == 0) && this.filesets.size() == 0 && (this.srcincludes == null || !this.srcincludes.isFile())) { throw new BuildException("srcdir, srcfileset and srcincludes cannot be all empty"); } if(this.clsdir == null || this.clsdir.size() == 0) { throw new BuildException("clsdir cannot be null"); } if(this.properties == null || !this.properties.isFile()) { throw new BuildException("properties is not a valid file [" + this.properties + "]"); } boolean useDirs = (srcdir != null && srcdir.size() != 0); String[] srcList = null; switch(this.srcParamType) { case SRC_DIR: case SRC_DIRPATH: srcList = getDirList(this.srcdir, "srcdir", true); break; case SRC_FILESET: srcList = getSourceFiles(this.filesets); break; case SRC_FILE: srcList = getSourceFiles(this.srcincludes); break; } AnnotationC.compile(this.verbose, srcList, useDirs, getDirList(this.clsdir, "cls", true), this.destdir == null ? null : this.destdir.getAbsolutePath(), this.properties.getAbsolutePath() ); if(this.destdir != null) { runCopy(); } } catch(Exception e) { e.printStackTrace(); throw new BuildException(e); } } private void runCopy() throws BuildException { Copy copy = new Copy(); copy.setProject(getProject()); copy.setTodir(this.destdir); copy.setOverwrite(false); copy.setTaskName("copy"); copy.setVerbose(this.verbose); String[] clsDirs = getDirList(this.clsdir, "cls", false); for(int i = 0; i < clsDirs.length; i++) { FileSet anonFs = new FileSet(); File clsFileDir = new File(clsDirs[i]); anonFs.setDir(clsFileDir); for(int j=0; j<COPY_ANONYMOUS_INNER_PATTERN.length; j++) { PatternSet psAnonymous = anonFs.createPatternSet(); psAnonymous.setIncludes(COPY_ANONYMOUS_INNER_PATTERN[j]); } copy.addFileset(anonFs); if(this.copyResources) { FileSet resourceFs = new FileSet(); resourceFs.setDir(clsFileDir); PatternSet psIncludes = resourceFs.createPatternSet(); psIncludes.setIncludes(COPY_ALL_PATTERN); PatternSet psExcludes = resourceFs.createPatternSet(); psExcludes.setExcludes(EXCLUDE_CLASS_PATTERN); copy.addFileset(resourceFs); } } copy.execute(); } private String[] getSourceFiles(List fsList) throws BuildException { List allfiles = new ArrayList(); // deal with the filesets for(int i = 0; i < filesets.size(); i++) { FileSet fs = (FileSet) filesets.get(i); DirectoryScanner ds = fs.getDirectoryScanner(getProject()); File fromDir = fs.getDir(getProject()); String[] srcFiles = ds.getIncludedFiles(); for(int j = 0; j < srcFiles.length; j++) { allfiles.add(fromDir + File.separator + srcFiles[j]); } } return (String[]) allfiles.toArray(new String[allfiles.size()]); } private String[] getSourceFiles(File file) throws BuildException { List files = new ArrayList(); BufferedReader reader = null; try { reader = new BufferedReader(new FileReader(file)); String line = reader.readLine(); File tmpFile = null; while(line != null) { if(line.length() > 0) { tmpFile = getProject().resolveFile(line); if(!tmpFile.isFile()) { log("file not found: [" + tmpFile + "]", Project.MSG_WARN); } else { files.add(tmpFile.getAbsolutePath()); } } line = reader.readLine(); } } catch(IOException ioe) { throw new BuildException("an error occured while reading from pattern file: " + file, ioe); } finally { if(null != reader) { try { reader.close(); } catch(IOException ioe) { ;//Ignore exception } } } return (String[]) files.toArray(new String[files.size()]); } private String[] getDirList(Path path, String type, boolean check) throws BuildException { String[] list = path.list(); List dirs = new ArrayList(); for(int i = 0; i < list.length; i++) { File dir = getProject().resolveFile(list[i]); if(check) { if(!dir.exists()) { throw new BuildException(type + " \"" + dir.getPath() + "\" does not exist!", getLocation()); } } dirs.add(dir.getAbsolutePath()); } return (String[]) dirs.toArray(new String[dirs.size()]); } /** * Checks the src related parameters. */ private boolean isSet(int srcParam) { if(SRC_NOTSET == this.srcParamType) { // nothing is set this.srcParamType = srcParam; return false; } if(SRC_DIRPATH == srcParam && SRC_DIRPATH == this.srcParamType) { // inner is allowed multiple times return false; } return true; } private BuildException tooManyParameters(int srcType) { return new BuildException("cannot set both " + MSG[this.srcParamType] + " and " + MSG[srcType]); } }