@@ -0,0 +1,11 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<classpath> | |||
<classpathentry kind="src" path="src"/> | |||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> | |||
<classpathentry kind="src" path="/asm"/> | |||
<classpathentry kind="src" path="/org.aspectj.ajdt.core"/> | |||
<classpathentry kind="src" path="/bridge"/> | |||
<classpathentry kind="src" path="/util"/> | |||
<classpathentry kind="lib" path="C:/Apps/j2sdk1.4.2/lib/tools.jar"/> | |||
<classpathentry kind="output" path="bin"/> | |||
</classpath> |
@@ -0,0 +1,21 @@ | |||
<?xml version="1.0" encoding="UTF-8"?> | |||
<projectDescription> | |||
<name>ajdoc</name> | |||
<comment></comment> | |||
<projects> | |||
<project>asm</project> | |||
<project>bridge</project> | |||
<project>org.aspectj.ajdt.core</project> | |||
<project>util</project> | |||
</projects> | |||
<buildSpec> | |||
<buildCommand> | |||
<name>org.eclipse.jdt.core.javabuilder</name> | |||
<arguments> | |||
</arguments> | |||
</buildCommand> | |||
</buildSpec> | |||
<natures> | |||
<nature>org.eclipse.jdt.core.javanature</nature> | |||
</natures> | |||
</projectDescription> |
@@ -0,0 +1,43 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 1999-2001 Xerox Corporation, | |||
* 2002 Palo Alto Research Center, Incorporated (PARC). | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Common Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/cpl-v10.html | |||
* | |||
* Contributors: | |||
* Xerox/PARC initial implementation | |||
* Mik Kersten port to AspectJ 1.1+ code base | |||
* ******************************************************************/ | |||
package org.aspectj.tools.ajdoc; | |||
interface Config { | |||
static final String DECL_ID_STRING = "__AJDECLID:"; | |||
static final String DECL_ID_TERMINATOR = ":__"; | |||
static final String WORKING_DIR = "ajdocworkingdir"; | |||
static final String DIR_SEP_CHAR = "/"; | |||
static final String VERSION = "ajdoc version 0.8beta4"; | |||
static final String USAGE = | |||
"Usage: ajdoc <options> <source files>\n" + | |||
"\n" + | |||
"where <options> includes:\n"+ | |||
" -public Show only public classes and members\n"+ | |||
" -protected Show protected/public classes and members\n"+ | |||
" -package Show package/protected/public classes and members\n" + // default | |||
" -private Show all classes and members\n" + | |||
" -help Display command line options\n" + | |||
" -sourcepath <pathlist> Specify where to find source files\n" + | |||
" -classpath <pathlist> Specify where to find user class files\n" + | |||
" -bootclasspath <pathlist> Override location of class files loaded\n" + | |||
" -d <directory> Destination directory for output files\n" + | |||
" -argfile <file> the file is a line-delimted list of arguments" + | |||
" -verbose Output messages about what Javadoc is doing\n" + | |||
" -v Print out the version of ajdoc" + | |||
"\n"+ | |||
"If an argument is of the form @<filename>, the file will be interpreted as\n"+ | |||
"a line delimited set of arguments to insert into the argument list."; | |||
} |
@@ -0,0 +1,293 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 1999-2001 Xerox Corporation, | |||
* 2002 Palo Alto Research Center, Incorporated (PARC). | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Common Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/cpl-v10.html | |||
* | |||
* Contributors: | |||
* Xerox/PARC initial implementation | |||
* Mik Kersten port to AspectJ 1.1+ code base | |||
* ******************************************************************/ | |||
package org.aspectj.tools.ajdoc; | |||
import java.util.Enumeration; | |||
import java.io.IOException; | |||
import java.io.ObjectOutputStream; | |||
import java.io.Serializable; | |||
import java.util.*; | |||
// Make sure that references to Vector use the standard version | |||
// This lets us generate serialized files which interoperate with other code better | |||
import java.util.Vector; | |||
public class Declaration implements Serializable { | |||
private int beginLine; | |||
private int endLine; | |||
private int beginColumn; | |||
private int endColumn; | |||
private String modifiers; | |||
private String fullSignature; | |||
private String signature; | |||
private String crosscutDesignator; | |||
private String packageName; | |||
private String kind; | |||
private String declaringType; | |||
private String filename; | |||
private String formalComment; | |||
private Declaration[] declarations; | |||
private Handle crosscutDeclarationHandle; | |||
private Handle[] pointedToByHandles; | |||
private Handle[] pointsToHandles; | |||
transient private Declaration crosscutDeclaration; | |||
transient private Declaration[] pointedToBy = null; | |||
transient private Declaration[] pointsTo = null; | |||
private Declaration parentDeclaration = null; | |||
public Declaration(int beginLine, int endLine, int beginColumn, int endColumn, | |||
String modifiers, String signature, String fullSignature, | |||
String crosscutDesignator, | |||
String declaringType, String kind, | |||
String filename, String formalComment, | |||
String packageName) | |||
{ | |||
this.beginLine = beginLine; | |||
this.endLine = endLine; | |||
this.beginColumn = beginColumn; | |||
this.endColumn = endColumn; | |||
this.modifiers = modifiers; | |||
this.signature = signature; | |||
this.fullSignature = fullSignature; | |||
this.crosscutDesignator = crosscutDesignator; | |||
this.declaringType = declaringType; | |||
this.kind = kind; | |||
this.filename = filename; | |||
this.formalComment = formalComment; | |||
this.packageName = packageName; | |||
this.pointedToByHandles = new Handle[0]; | |||
this.pointsToHandles = new Handle[0]; | |||
//??? | |||
this.declarations = new Declaration[0]; | |||
} | |||
public int getBeginLine() { return beginLine; } | |||
public int getEndLine() { return endLine; } | |||
public int getBeginColumn() { return beginColumn; } | |||
public int getEndColumn() { return endColumn; } | |||
public String getModifiers() { return modifiers; } | |||
public String getFullSignature() { return fullSignature; } | |||
public String getSignature() { return signature; } | |||
public String getPackageName() { return packageName; } | |||
public String getCrosscutDesignator() { return crosscutDesignator; } | |||
public Declaration getParentDeclaration() { return parentDeclaration; } | |||
public Declaration getCrosscutDeclaration() { | |||
if (crosscutDeclaration == null && crosscutDeclarationHandle != null) { | |||
crosscutDeclaration = crosscutDeclarationHandle.resolve(); | |||
} | |||
return crosscutDeclaration; | |||
} | |||
public void setCrosscutDeclaration(Declaration _crosscutDeclaration) { | |||
crosscutDeclaration = _crosscutDeclaration; | |||
} | |||
public String getDeclaringType() { return declaringType; } | |||
public String getKind() { | |||
if (kind.startsWith("introduced-")) { | |||
return kind.substring(11); | |||
} else { | |||
return kind; | |||
} | |||
} | |||
public String getFilename() { return filename; } | |||
public String getFormalComment() { return formalComment; } | |||
public Declaration[] getDeclarations() { | |||
return declarations; | |||
} | |||
public void setDeclarations(Declaration[] decs) { | |||
declarations = decs; | |||
if (decs != null) { | |||
for (int i = 0; i < decs.length; i++) { | |||
decs[i].parentDeclaration = this; | |||
} | |||
} | |||
} | |||
public void setPointedToBy(Declaration[] decs) { pointedToBy = decs; } | |||
public void setPointsTo(Declaration[] decs) { pointsTo = decs; } | |||
public Declaration[] getPointedToBy() { | |||
if (pointedToBy == null) { | |||
pointedToBy = resolveHandles(pointedToByHandles); | |||
} | |||
return pointedToBy; //.elements(); | |||
} | |||
public Declaration[] getPointsTo() { | |||
if (pointsTo == null) { | |||
pointsTo = resolveHandles(pointsToHandles); | |||
} | |||
return pointsTo; //.elements(); | |||
} | |||
private Declaration[] filterTypes(Declaration[] a_decs) { | |||
List decs = new LinkedList(Arrays.asList(a_decs)); | |||
for(Iterator i = decs.iterator(); i.hasNext(); ) { | |||
Declaration dec = (Declaration)i.next(); | |||
if (!dec.isType()) i.remove(); | |||
} | |||
return (Declaration[])decs.toArray(new Declaration[decs.size()]); | |||
} | |||
public Declaration[] getTargets() { | |||
Declaration[] pointsTo = getPointsTo(); | |||
if (kind.equals("advice")) { | |||
return pointsTo; | |||
} else if (kind.equals("introduction")) { | |||
return filterTypes(pointsTo); | |||
} else { | |||
return new Declaration[0]; | |||
} | |||
} | |||
// Handles are used to deal with dependencies between Declarations in different files | |||
private Handle getHandle() { | |||
return new Handle(filename, beginLine, beginColumn); | |||
} | |||
private Declaration[] resolveHandles(Handle[] handles) { | |||
Declaration[] declarations = new Declaration[handles.length]; | |||
int missed = 0; | |||
for(int i=0; i<handles.length; i++) { | |||
//if (handles[i] == null) continue; | |||
declarations[i] = handles[i].resolve(); | |||
if (declarations[i] == null) missed++; | |||
} | |||
if (missed > 0) { | |||
Declaration[] decs = new Declaration[declarations.length - missed]; | |||
for (int i=0, j=0; i < declarations.length; i++) { | |||
if (declarations[i] != null) decs[j++] = declarations[i]; | |||
} | |||
declarations = decs; | |||
} | |||
return declarations; | |||
} | |||
private Handle[] getHandles(Declaration[] declarations) { | |||
Handle[] handles = new Handle[declarations.length]; | |||
for(int i=0; i<declarations.length; i++) { | |||
//if (declarations[i] == null) continue; | |||
handles[i] = declarations[i].getHandle(); | |||
} | |||
return handles; | |||
} | |||
// Make sure that all decs are convertted to handles before serialization | |||
private void writeObject(ObjectOutputStream out) throws IOException { | |||
pointedToByHandles = getHandles(getPointedToBy()); | |||
pointsToHandles = getHandles(getPointsTo()); | |||
if (crosscutDeclaration != null) { | |||
crosscutDeclarationHandle = crosscutDeclaration.getHandle(); | |||
} | |||
out.defaultWriteObject(); | |||
} | |||
// support functions | |||
public Declaration[] getCrosscutDeclarations() { | |||
return getDeclarationsHelper("pointcut"); | |||
} | |||
public Declaration[] getAdviceDeclarations() { | |||
return getDeclarationsHelper("advice"); | |||
} | |||
public Declaration[] getIntroductionDeclarations() { | |||
return getDeclarationsHelper("introduction"); | |||
} | |||
private Declaration[] getDeclarationsHelper(String kind) { | |||
Declaration[] decls = getDeclarations(); | |||
List result = new ArrayList(); | |||
for ( int i = 0; i < decls.length; i++ ) { | |||
Declaration decl = decls[i]; | |||
if ( decl.getKind().equals(kind) ) { | |||
result.add(decl); | |||
} | |||
} | |||
return (Declaration[])result.toArray(new Declaration[result.size()]); | |||
} | |||
public boolean isType() { | |||
return getKind().equals("interface") || getKind().equals("class"); | |||
} | |||
public boolean hasBody() { | |||
String kind = getKind(); | |||
return kind.equals("class") || kind.endsWith("constructor") || | |||
(kind.endsWith("method") && getModifiers().indexOf("abstract") == -1 && | |||
getModifiers().indexOf("native") == -1); | |||
} | |||
public boolean isIntroduced() { | |||
return kind.startsWith("introduced-"); | |||
} | |||
public boolean hasSignature() { | |||
String kind = getKind(); | |||
if ( kind.equals( "class" ) || | |||
kind.equals( "interface" ) || | |||
kind.equals( "initializer" ) || | |||
kind.equals( "field" ) || | |||
kind.equals( "constructor" ) || | |||
kind.equals( "method" ) ) { | |||
return true; | |||
} | |||
else { | |||
return false; | |||
} | |||
} | |||
private static class Handle implements Serializable { | |||
public String filename; | |||
public int line, column; | |||
public Handle(String filename, int line, int column) { | |||
this.filename = filename; | |||
this.line = line; | |||
this.column = column; | |||
} | |||
public Declaration resolve() { | |||
SymbolManager manager = SymbolManager.getDefault(); | |||
return manager.getDeclarationAtPoint(filename, line, column); | |||
} | |||
} | |||
} |
@@ -0,0 +1,700 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 1999-2001 Xerox Corporation, | |||
* 2002 Palo Alto Research Center, Incorporated (PARC). | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Common Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/cpl-v10.html | |||
* | |||
* Contributors: | |||
* Xerox/PARC initial implementation | |||
* Mik Kersten port to AspectJ 1.1+ code base | |||
* ******************************************************************/ | |||
package org.aspectj.tools.ajdoc; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.BufferedWriter; | |||
import java.io.PrintWriter; | |||
import java.io.IOException; | |||
import java.io.BufferedReader; | |||
import java.io.FileReader; | |||
import java.io.FileWriter; | |||
import java.io.StringReader; | |||
import java.io.FilenameFilter; | |||
import java.util.*; | |||
/** | |||
* This is an old implementation of ajdoc that does not use an OO style. However, it | |||
* does the job, and should serve to evolve a lightweight ajdoc implementation until | |||
* we can make a properly extended javadoc implementation. | |||
* | |||
* @author Mik Kersten | |||
*/ | |||
public class Main implements Config { | |||
static SymbolManager symbolManager = null; | |||
/** Command line options. */ | |||
static Vector options = new Vector(); | |||
/** Options to pass to ajc. */ | |||
static Vector ajcOptions = new Vector(); | |||
/** All of the files to be processed by ajdoc. */ | |||
static Vector filenames = new Vector(); | |||
/** List of files to pass to javadoc. */ | |||
static Vector fileList= new Vector(); | |||
/** List of packages to pass to javadoc. */ | |||
static Vector packageList = new Vector(); | |||
/** Default to package visiblity. */ | |||
static String docModifier = "package"; | |||
static Vector sourcepath = new Vector(); | |||
static boolean verboseMode = false; | |||
static boolean packageMode = false; | |||
static boolean authorStandardDocletSwitch = false; | |||
static boolean versionStandardDocletSwitch = false; | |||
static File rootDir = null; | |||
static Hashtable declIDTable = new Hashtable(); | |||
static String docDir = "."; | |||
public static void clearState() { | |||
symbolManager = null; | |||
options = new Vector(); | |||
ajcOptions = new Vector(); | |||
filenames = new Vector(); | |||
fileList= new Vector(); | |||
packageList = new Vector(); | |||
docModifier = "package"; | |||
sourcepath = new Vector(); | |||
verboseMode = false; | |||
packageMode = false; | |||
rootDir = null; | |||
declIDTable = new Hashtable(); | |||
docDir = "."; | |||
} | |||
public static void main(String[] args) { | |||
// STEP 1: parse the command line and do other global setup | |||
sourcepath.addElement("."); // add the current directory to the classapth | |||
parseCommandLine(args); | |||
rootDir = getRootDir(); | |||
symbolManager = SymbolManager.getDefault(); | |||
File[] inputFiles = new File[filenames.size()]; | |||
File[] signatureFiles = new File[filenames.size()]; | |||
try { | |||
// create the workingdir if it doesn't exist | |||
if ( !(new File( Config.WORKING_DIR ).isDirectory()) ) { | |||
File dir = new File( Config.WORKING_DIR ); | |||
dir.mkdir(); | |||
dir.deleteOnExit(); | |||
} | |||
for (int i = 0; i < filenames.size(); i++) { | |||
inputFiles[i] = findFile((String)filenames.elementAt(i)); | |||
//signatureFiles[i] = createSignatureFile(inputFiles[i]); | |||
} | |||
// PHASE 0: call ajc | |||
ajcOptions.addElement( "-noExit" ); | |||
ajcOptions.addElement( "-emacssym" ); // TODO: wrong option to force model gen | |||
String[] argsToCompiler = new String[ajcOptions.size() + inputFiles.length]; | |||
int i = 0; | |||
for ( ; i < ajcOptions.size(); i++ ) { | |||
argsToCompiler[i] = (String)ajcOptions.elementAt(i); | |||
//System.out.println(">>> ajc: " + argsToCompiler[i]); | |||
} | |||
for ( int j = 0; j < inputFiles.length; j++) { | |||
argsToCompiler[i] = inputFiles[j].getAbsolutePath(); | |||
//System.out.println(">> file to ajc: " + inputFiles[j].getAbsolutePath()); | |||
i++; | |||
} | |||
System.out.println( "> calling ajc..." ); | |||
try { | |||
(new org.aspectj.tools.ajc.Main() { | |||
public void exit(int status) { | |||
if (status != 0) { | |||
System.out.println( "> compile failed, exiting ajdoc" ); | |||
System.exit( -1 ); | |||
} | |||
} | |||
}).main(argsToCompiler); | |||
} | |||
catch ( SecurityException se ) { | |||
System.exit( -1 ); | |||
} | |||
/* | |||
for (int ii = 0; ii < inputFiles.length; ii++) { | |||
String tempFP = inputFiles[ii].getAbsolutePath(); | |||
tempFP = tempFP.substring(0, tempFP.length()-4); | |||
tempFP += "ajsym"; | |||
System.out.println( ">> checking: " + tempFP); | |||
File tempF = new File(tempFP); | |||
if ( !tempF.exists() ) System.out.println( ">>> doesn't exist!" ); | |||
} | |||
*/ | |||
for (int ii = 0; ii < filenames.size(); ii++) { | |||
signatureFiles[ii] = createSignatureFile(inputFiles[ii]); | |||
} | |||
// PHASE 1: generate Signature files (Java with DeclIDs and no bodies). | |||
System.out.println( "> building signature files..." ); | |||
Phase1.doFiles(declIDTable, symbolManager, inputFiles, signatureFiles); | |||
// PHASE 2: let Javadoc generate HTML (with DeclIDs) | |||
System.out.println( "> calling javadoc..." ); | |||
String[] javadocargs = null; | |||
if ( packageMode ) { | |||
int numExtraArgs = 2; | |||
if (authorStandardDocletSwitch) numExtraArgs++; | |||
if (versionStandardDocletSwitch) numExtraArgs++; | |||
javadocargs = new String[numExtraArgs + options.size() + packageList.size() + | |||
fileList.size() ]; | |||
javadocargs[0] = "-sourcepath"; | |||
javadocargs[1] = Config.WORKING_DIR; | |||
int argIndex = 2; | |||
if (authorStandardDocletSwitch) { | |||
javadocargs[argIndex] = "-author"; | |||
argIndex++; | |||
} | |||
if (versionStandardDocletSwitch) { | |||
javadocargs[argIndex] = "-version"; | |||
} | |||
//javadocargs[1] = getSourcepathAsString(); | |||
for (int k = 0; k < options.size(); k++) { | |||
javadocargs[numExtraArgs+k] = (String)options.elementAt(k); | |||
} | |||
for (int k = 0; k < packageList.size(); k++) { | |||
javadocargs[numExtraArgs+options.size() + k] = (String)packageList.elementAt(k); | |||
} | |||
for (int k = 0; k < fileList.size(); k++) { | |||
javadocargs[numExtraArgs+options.size() + packageList.size() + k] = (String)fileList.elementAt(k); | |||
} | |||
} | |||
else { | |||
javadocargs = new String[options.size() + signatureFiles.length]; | |||
for (int k = 0; k < options.size(); k++) { | |||
javadocargs[k] = (String)options.elementAt(k); | |||
} | |||
for (int k = 0; k < signatureFiles.length; k++) { | |||
javadocargs[options.size() + k] = signatureFiles[k].getCanonicalPath(); | |||
} | |||
} | |||
Phase2.callJavadoc(javadocargs); | |||
//for ( int o = 0; o < inputFiles.length; o++ ) { | |||
// System.out.println( "file: " + inputFiles[o] ); | |||
//} | |||
// PHASE 3: add AspectDoc specific stuff to the HTML (and remove the DeclIDS). | |||
/** We start with the known HTML files (the ones that correspond directly to the | |||
* input files.) As we go along, we may learn that Javadoc split one .java file | |||
* into multiple .html files to handle inner classes or local classes. The html | |||
* file decorator picks that up. | |||
*/ | |||
System.out.println( "> Decorating html files..." ); | |||
Phase3.decorateHTMLFromInputFiles(declIDTable, | |||
rootDir, | |||
symbolManager, | |||
inputFiles, | |||
docModifier); | |||
removeDeclIDsFromFile("index-all.html"); | |||
removeDeclIDsFromFile("serialized-form.html"); | |||
for (int p = 0; p < packageList.size(); p++) { | |||
removeDeclIDsFromFile(((String)packageList.elementAt(p)).replace('.','/') + | |||
Config.DIR_SEP_CHAR + | |||
"package-summary.html" ); | |||
} | |||
} catch (Throwable e) { | |||
handleInternalError(e); | |||
exit(-2); | |||
} | |||
} | |||
static void removeDeclIDsFromFile(String filename) { | |||
// Remove the decl ids from "index-all.html" | |||
File indexFile = new File( docDir + Config.DIR_SEP_CHAR + filename ); | |||
try { | |||
if ( indexFile.exists() ) { | |||
BufferedReader indexFileReader = new BufferedReader( new FileReader( indexFile ) ); | |||
String indexFileBuffer = ""; | |||
String line = indexFileReader.readLine(); | |||
while ( line != null ) { | |||
int indexStart = line.indexOf( Config.DECL_ID_STRING ); | |||
int indexEnd = line.indexOf( Config.DECL_ID_TERMINATOR ); | |||
if ( indexStart != -1 && indexEnd != -1 ) { | |||
line = line.substring( 0, indexStart ) + | |||
line.substring( indexEnd+Config.DECL_ID_TERMINATOR.length() ); | |||
} | |||
indexFileBuffer += line; | |||
line = indexFileReader.readLine(); | |||
} | |||
FileOutputStream fos = new FileOutputStream( indexFile ); | |||
fos.write( indexFileBuffer.getBytes() ); | |||
} | |||
} | |||
catch (IOException ioe) { | |||
// be siltent | |||
} | |||
} | |||
static void callAJC( String[] ajcargs ) { | |||
final SecurityManager defaultSecurityManager = System.getSecurityManager(); | |||
System.setSecurityManager( new SecurityManager() { | |||
public void checkExit(int status) { | |||
System.setSecurityManager( defaultSecurityManager ); | |||
//throw new SecurityException( "status code: " + status ); | |||
//System.exit( -1 ); | |||
} | |||
public void checkPermission( java.security.Permission permission ) { | |||
if ( defaultSecurityManager != null ) | |||
defaultSecurityManager.checkPermission( permission ); | |||
} | |||
public void checkPermission( java.security.Permission permission, | |||
Object context ) { | |||
if ( defaultSecurityManager != null ) | |||
defaultSecurityManager.checkPermission( permission, context ); | |||
} | |||
} ); | |||
try { | |||
org.aspectj.tools.ajc.Main.main( ajcargs ); | |||
} | |||
catch ( SecurityException se ) { | |||
// Do nothing since we expect it to be thrown | |||
//System.out.println( ">> se: " + se.getMessage() ); | |||
} catch ( IOException ioe ) { | |||
System.out.println( ">> io error: " + ioe.getMessage() ); | |||
} | |||
// Set the security manager back | |||
System.setSecurityManager( defaultSecurityManager ); | |||
} | |||
/** | |||
* If the file doesn't exist on the specified path look for it in all the other | |||
* paths specified by the "sourcepath" option. | |||
*/ | |||
static File findFile( String filename ) throws IOException { | |||
return new File( filename ); | |||
/* | |||
File file = new File(filename); | |||
if (file.exists()) { | |||
return file; | |||
} | |||
else { | |||
for ( int i = 0; i < sourcePath.size(); i++ ) { | |||
File currPath = new File((String)sourcePath.elementAt(i)); | |||
File currFile = new File(currPath + "/" + filename); // !!! | |||
if ( file.exists()) { | |||
return file; | |||
} | |||
} | |||
} | |||
throw new IOException("couldn't find source file: " + filename); | |||
*/ | |||
} | |||
static Vector getSourcePath() { | |||
Vector sourcePath = new Vector(); | |||
boolean found = false; | |||
for ( int i = 0; i < options.size(); i++ ) { | |||
String currOption = (String)options.elementAt(i); | |||
if (found && !currOption.startsWith("-")) { | |||
sourcePath.add(currOption); | |||
} | |||
if (currOption.equals("-sourcepath")) { | |||
found = true; | |||
} | |||
} | |||
return sourcePath; | |||
} | |||
static File getRootDir() { | |||
File rootDir = new File( "." ); | |||
for ( int i = 0; i < options.size(); i++ ) { | |||
if ( ((String)options.elementAt(i)).equals( "-d" ) ) { | |||
rootDir = new File((String)options.elementAt(i+1)); | |||
if ( !rootDir.exists() ) { | |||
System.out.println( "Destination directory not found: " + | |||
(String)options.elementAt(i+1) ); | |||
System.exit( -1 ); | |||
} | |||
} | |||
} | |||
return rootDir; | |||
} | |||
static File createSignatureFile(File inputFile) throws IOException { | |||
Declaration[] decls = symbolManager.getDeclarations(inputFile.getAbsolutePath()); | |||
Declaration decl = null; | |||
String packageName = null; | |||
if ( decls != null && decls[0] != null ) { | |||
decl = decls[0]; | |||
packageName = decl.getPackageName(); | |||
} | |||
String filename = ""; | |||
if ( packageName != null ) { | |||
//System.err.println(">> creating: " + packageName); | |||
String pathName = Config.WORKING_DIR + '/' + packageName.replace('.', '/'); | |||
//System.err.println(">> pathName: " + pathName); | |||
File packageDir = new File(pathName); | |||
if ( !packageDir.exists() ) { | |||
packageDir.mkdirs(); | |||
//packageDir.deleteOnExit(); | |||
} | |||
//verifyPackageDirExists(packageName, null); | |||
packageName = packageName.replace( '.','/' ); // !!! | |||
filename = Config.WORKING_DIR + Config.DIR_SEP_CHAR + packageName + | |||
Config.DIR_SEP_CHAR + inputFile.getName(); | |||
} | |||
else { | |||
filename = Config.WORKING_DIR + Config.DIR_SEP_CHAR + inputFile.getName(); | |||
} | |||
File signatureFile = new File( filename ); | |||
//signatureFile.deleteOnExit(); | |||
return signatureFile; | |||
} | |||
static void verifyPackageDirExists( String packageName, String offset ) { | |||
System.err.println(">>> name: " + packageName + ", offset: " + offset); | |||
if ( packageName.indexOf( "." ) != -1 ) { | |||
File tempFile = new File("c:/aspectj-test/d1/d2/d3"); | |||
tempFile.mkdirs(); | |||
String currPkgDir = packageName.substring( 0, packageName.indexOf( "." ) ); | |||
String remainingPkg = packageName.substring( packageName.indexOf( "." )+1 ); | |||
String filePath = null; | |||
if ( offset != null ) { | |||
filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + | |||
offset + Config.DIR_SEP_CHAR + currPkgDir ; | |||
} | |||
else { | |||
filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + currPkgDir; | |||
} | |||
File packageDir = new File( filePath ); | |||
if ( !packageDir.exists() ) { | |||
packageDir.mkdir(); | |||
packageDir.deleteOnExit(); | |||
} | |||
if ( remainingPkg != "" ) { | |||
verifyPackageDirExists( remainingPkg, currPkgDir ); | |||
} | |||
} | |||
else { | |||
String filePath = null; | |||
if ( offset != null ) { | |||
filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + offset + Config.DIR_SEP_CHAR + packageName; | |||
} | |||
else { | |||
filePath = Config.WORKING_DIR + Config.DIR_SEP_CHAR + packageName; | |||
} | |||
File packageDir = new File( filePath ); | |||
if ( !packageDir.exists() ) { | |||
packageDir.mkdir(); | |||
packageDir.deleteOnExit(); | |||
} | |||
} | |||
} | |||
static void parseCommandLine(String[] args) { | |||
if (args.length == 0) { | |||
displayHelpAndExit( null ); | |||
} | |||
List vargs = new LinkedList(Arrays.asList(args)); | |||
parseArgs(vargs, new File( "." )); // !!! | |||
if (filenames.size() == 0) { | |||
displayHelpAndExit( "ajdoc: No packages or classes specified" ); | |||
} | |||
} | |||
static void setSourcepath(String arg) { | |||
sourcepath.clear(); | |||
arg = arg + ";"; // makes things easier for ourselves | |||
StringTokenizer tokenizer = new StringTokenizer(arg, ";"); | |||
while (tokenizer.hasMoreElements()) { | |||
sourcepath.addElement(tokenizer.nextElement()); | |||
} | |||
} | |||
static String getSourcepathAsString() { | |||
String cPath = ""; | |||
for (int i = 0; i < sourcepath.size(); i++) { | |||
cPath += (String)sourcepath.elementAt(i) + Config.DIR_SEP_CHAR + Config.WORKING_DIR; | |||
if (i != sourcepath.size()-1) { | |||
cPath += ";"; | |||
} | |||
} | |||
return cPath; | |||
} | |||
static void parseArgs(List vargs, File currentWorkingDir) { | |||
boolean addNextAsOption = false; | |||
boolean addNextAsArgFile = false; | |||
boolean addNextToAJCOptions = false; | |||
boolean addNextAsDocDir = false; | |||
boolean addNextAsClasspath = false; | |||
boolean ignoreArg = false; // used for discrepancy betwen class/sourcepath in ajc/javadoc | |||
boolean addNextAsSourcePath = false; | |||
if ( vargs.size() == 0 ) { | |||
displayHelpAndExit( null ); | |||
} | |||
for (int i = 0; i < vargs.size() ; i++) { | |||
String arg = (String)vargs.get(i); | |||
ignoreArg = false; | |||
if ( addNextToAJCOptions ) { | |||
ajcOptions.addElement( arg ); | |||
addNextToAJCOptions = false; | |||
} | |||
if ( addNextAsDocDir ) { | |||
docDir = arg; | |||
addNextAsDocDir = false; | |||
} | |||
if ( addNextAsClasspath ) { | |||
addNextAsClasspath = false; | |||
} | |||
if ( addNextAsSourcePath ) { | |||
setSourcepath( arg ); | |||
addNextAsSourcePath = false; | |||
ignoreArg = true; | |||
} | |||
if ( arg.startsWith("@") ) { | |||
expandAtSignFile(arg.substring(1), currentWorkingDir); | |||
} | |||
else if ( arg.equals( "-argfile" ) ) { | |||
addNextAsArgFile = true; | |||
} | |||
else if ( addNextAsArgFile ) { | |||
expandAtSignFile(arg, currentWorkingDir); | |||
addNextAsArgFile = false; | |||
} | |||
else if (arg.equals("-d") ) { | |||
addNextAsOption = true; | |||
options.addElement(arg); | |||
addNextAsDocDir = true; | |||
} | |||
else if ( arg.equals( "-bootclasspath" ) ) { | |||
addNextAsOption = true; | |||
addNextToAJCOptions = true; | |||
options.addElement( arg ); | |||
ajcOptions.addElement( arg ); | |||
} | |||
else if ( arg.equals( "-classpath" ) ) { | |||
addNextAsOption = true; | |||
addNextToAJCOptions = true; | |||
addNextAsClasspath = true; | |||
options.addElement( arg ); | |||
ajcOptions.addElement( arg ); | |||
} | |||
else if ( arg.equals( "-sourcepath" ) ) { | |||
addNextAsSourcePath = true; | |||
//options.addElement( arg ); | |||
//ajcOptions.addElement( arg ); | |||
} | |||
else if (arg.startsWith("-") || addNextAsOption) { | |||
if ( arg.equals( "-private" ) ) { | |||
docModifier = "private"; | |||
} | |||
else if ( arg.equals( "-package" ) ) { | |||
docModifier = "package"; | |||
} | |||
else if ( arg.equals( "-protected" ) ) { | |||
docModifier = "protected"; | |||
} | |||
else if ( arg.equals( "-public" ) ) { | |||
docModifier = "public"; | |||
} | |||
else if ( arg.equals( "-verbose" ) ) { | |||
verboseMode = true; | |||
} | |||
else if ( arg.equals( "-author" ) ) { | |||
authorStandardDocletSwitch = true; | |||
} | |||
else if ( arg.equals( "-version" ) ) { | |||
versionStandardDocletSwitch = true; | |||
} | |||
else if ( arg.equals( "-v" ) ) { | |||
printVersion(); | |||
exit(0); | |||
} | |||
else if ( arg.equals( "-help" ) ) { | |||
displayHelpAndExit( null ); | |||
} | |||
else if ( arg.equals( "-doclet" ) || arg.equals( "-docletpath" ) ) { | |||
System.out.println( "The doclet and docletpath options are not currently supported \n" + | |||
"since ajdoc makes assumptions about the behavior of the standard \n" + | |||
"doclet. If you would find this option useful please email us at: \n" + | |||
" \n" + | |||
" asupport@aspectj.org \n" + | |||
" \n" ); | |||
exit(0); | |||
} | |||
else if ( addNextAsOption ) { | |||
// just pass through | |||
} | |||
else { | |||
displayHelpAndExit( null ); | |||
} | |||
options.addElement(arg); | |||
addNextAsOption = false; | |||
} | |||
else { | |||
// check if this is a file or a package | |||
if ( arg.indexOf( ".java" ) == arg.length() - 5 || | |||
arg.indexOf( ".lst" ) == arg.length() - 4 && | |||
arg != null ) { | |||
File f = new File(arg); | |||
if (f.isAbsolute()) { | |||
filenames.addElement(arg); | |||
} | |||
else { | |||
filenames.addElement( currentWorkingDir + Config.DIR_SEP_CHAR + arg ); | |||
} | |||
fileList.addElement( arg ); | |||
} | |||
// PACKAGE MODE STUFF | |||
else if (!ignoreArg) { | |||
packageMode = true; | |||
packageList.addElement( arg ); | |||
arg = arg.replace( '.', '/' ); // !!! | |||
// do this for every item in the classpath | |||
for ( int c = 0; c < sourcepath.size(); c++ ) { | |||
String path = (String)sourcepath.elementAt(c) + Config.DIR_SEP_CHAR + arg; | |||
File pkg = new File(path); | |||
if ( pkg.isDirectory() ) { | |||
String[] files = pkg.list( new FilenameFilter() { | |||
public boolean accept( File dir, String name ) { | |||
int index1 = name.lastIndexOf( "." ); | |||
int index2 = name.length(); | |||
if ( (index1 >= 0 && index2 >= 0 ) && | |||
(name.substring(index1, index2).equals( ".java" ) ) ) { | |||
return true; | |||
} | |||
else { | |||
return false; | |||
} | |||
} | |||
} ); | |||
for ( int j = 0; j < files.length; j++ ) { | |||
filenames.addElement( (String)sourcepath.elementAt(c) + | |||
Config.DIR_SEP_CHAR + | |||
arg + Config.DIR_SEP_CHAR + files[j] ); | |||
} | |||
} | |||
else if (c == sourcepath.size() ) { // last element on classpath | |||
System.out.println( "ajdoc: No package, class, or source file " + | |||
"found named " + arg + "." ); | |||
} | |||
else { | |||
// didn't find it on that element of the classpath but that's ok | |||
} | |||
} | |||
} | |||
} | |||
} | |||
// set the default visibility as an option to javadoc option | |||
if ( !options.contains( "-private" ) && | |||
!options.contains( "-package" ) && | |||
!options.contains( "-protected" ) && | |||
!options.contains( "-public" ) ) { | |||
options.addElement( "-package" ); | |||
} | |||
} | |||
static void expandAtSignFile(String filename, File currentWorkingDir) { | |||
List result = new LinkedList(); | |||
File atFile = qualifiedFile(filename, currentWorkingDir); | |||
String atFileParent = atFile.getParent(); | |||
File myWorkingDir = null; | |||
if (atFileParent != null) myWorkingDir = new File(atFileParent); | |||
try { | |||
BufferedReader stream = new BufferedReader(new FileReader(atFile)); | |||
String line = null; | |||
while ( (line = stream.readLine()) != null) { | |||
// strip out any comments of the form # to end of line | |||
int commentStart = line.indexOf("//"); | |||
if (commentStart != -1) { | |||
line = line.substring(0, commentStart); | |||
} | |||
// remove extra whitespace that might have crept in | |||
line = line.trim(); | |||
// ignore blank lines | |||
if (line.length() == 0) continue; | |||
result.add(line); | |||
} | |||
} catch (IOException e) { | |||
System.err.println("Error while reading the @ file " + atFile.getPath() + ".\n" | |||
+ e); | |||
System.exit( -1 ); | |||
} | |||
parseArgs(result, myWorkingDir); | |||
} | |||
static File qualifiedFile(String name, File currentWorkingDir) { | |||
name = name.replace('/', File.separatorChar); | |||
File file = new File(name); | |||
if (!file.isAbsolute() && currentWorkingDir != null) { | |||
file = new File(currentWorkingDir, name); | |||
} | |||
return file; | |||
} | |||
static void displayHelpAndExit(String message) { | |||
if (message != null) System.err.println(message); | |||
System.err.println(); | |||
System.err.println(Config.USAGE); | |||
exit(0); | |||
} | |||
static protected void exit(int value) { | |||
System.out.flush(); | |||
System.err.flush(); | |||
System.exit(value); | |||
} | |||
/* This section of code handles errors that occur during compilation */ | |||
static final String internalErrorMessage = | |||
"Please copy the following text into an email message and send it,\n" + | |||
"along with any additional information you can add to: \n" + | |||
" \n" + | |||
" support@aspectj.org \n" + | |||
" \n"; | |||
static public void handleInternalError(Throwable uncaughtThrowable) { | |||
System.err.println("An internal error occured in ajdoc"); | |||
System.err.println(internalErrorMessage); | |||
System.err.println(uncaughtThrowable.toString()); | |||
uncaughtThrowable.printStackTrace(); | |||
System.err.println(); | |||
} | |||
static void printVersion() { | |||
System.out.println( Config.VERSION ); | |||
} | |||
} | |||
@@ -0,0 +1,229 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 1999-2001 Xerox Corporation, | |||
* 2002 Palo Alto Research Center, Incorporated (PARC). | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Common Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/cpl-v10.html | |||
* | |||
* Contributors: | |||
* Xerox/PARC initial implementation | |||
* Mik Kersten port to AspectJ 1.1+ code base | |||
* ******************************************************************/ | |||
package org.aspectj.tools.ajdoc; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.BufferedWriter; | |||
import java.io.PrintWriter; | |||
import java.io.IOException; | |||
import java.io.BufferedReader; | |||
import java.io.FileReader; | |||
import java.io.FileWriter; | |||
import java.io.StringReader; | |||
import java.util.StringTokenizer; | |||
import java.util.*; | |||
class Phase1 { | |||
static Hashtable declIDTable = null; | |||
static void doFiles(Hashtable table, | |||
SymbolManager symbolManager, | |||
File[] inputFiles, | |||
File[] signatureFiles) { | |||
declIDTable = table; | |||
for (int i = 0; i < inputFiles.length; i++) { | |||
doFile(symbolManager, inputFiles[i], signatureFiles[i]); | |||
} | |||
} | |||
static void doFile(SymbolManager symbolManager, File inputFile, File signatureFile) { | |||
try { | |||
Declaration[] decls = symbolManager.getDeclarations(inputFile.getCanonicalPath()); | |||
PrintWriter writer = new PrintWriter(new BufferedWriter(new FileWriter(signatureFile.getCanonicalPath()))); | |||
// write the package info | |||
if ( decls != null && decls[0] != null && decls[0].getPackageName() != null ) { | |||
writer.println( "package " + decls[0].getPackageName() + ";" ); | |||
} | |||
if (decls != null) { | |||
doDecls(decls, writer, false); | |||
} | |||
writer.close(); //this isn't in a finally, because if we got an | |||
//error we don't really want the contents anyways | |||
} | |||
catch (IOException e) { | |||
System.err.println(e.getMessage()); | |||
e.printStackTrace(); | |||
} | |||
} | |||
static void doDecls (Declaration[] decls, | |||
PrintWriter writer, | |||
boolean declaringDeclIsInterface) throws IOException { | |||
for (int i = 0; i < decls.length; i++) { | |||
Declaration decl = decls[i]; | |||
//System.out.println( ">> sig: " + decl.getSignature() ); | |||
doDecl(decl, writer, declaringDeclIsInterface); | |||
} | |||
} | |||
static void doDecl(Declaration decl, | |||
PrintWriter writer, | |||
boolean declaringDeclIsInterface) throws IOException { | |||
String formalComment = decl.getFormalComment(); | |||
String fullSignature = decl.getFullSignature(); | |||
System.err.println("> full: " + fullSignature); | |||
Declaration[] ptbs = decl.getPointedToBy(); | |||
Declaration[] subs = decl.getDeclarations(); | |||
if (decl.hasSignature()) { | |||
formalComment = addDeclID(decl, formalComment); | |||
writer.println(formalComment); | |||
// HACK: this should be in Declaration | |||
int implementsClauseIndex = fullSignature.indexOf(" implements"); | |||
if (implementsClauseIndex != -1) { | |||
String newSignature = ""; | |||
StringTokenizer st = new StringTokenizer(fullSignature.substring(implementsClauseIndex, fullSignature.length())); | |||
for (String element = (String)st.nextElement(); st.hasMoreElements(); element = (String)st.nextElement()) { | |||
if (element.indexOf("$MightHaveAspect") != -1 | |||
&& element.indexOf("implements") != -1) { | |||
newSignature += element; | |||
} | |||
} | |||
if (!newSignature.equals("")) { | |||
writer.print(fullSignature.substring(0, implementsClauseIndex) | |||
+ " implements " + newSignature + " " ); | |||
} else { | |||
writer.print(fullSignature.substring(0, implementsClauseIndex) + " " ); | |||
} | |||
} else { | |||
writer.print(fullSignature + " " ); | |||
} | |||
if ((!decl.hasBody() && !decl.getKind().equals( "interface" ) || | |||
(decl.getKind().equals( "method" ) && declaringDeclIsInterface)) && // !!! bug in Jim's API? | |||
!(decl.getKind().equals("initializer") && decl.getModifiers().indexOf("static") != -1 ) ) { | |||
System.err.println(">>>> kind: " + decl.getKind()); | |||
if (decl.getModifiers().indexOf("static final") != -1) { | |||
String fullSig = decl.getFullSignature().trim(); | |||
String stripped = fullSig.substring(0, fullSig.lastIndexOf(' ')); | |||
//System.err.println(">>> " + fullSig); | |||
String type = stripped.substring(stripped.lastIndexOf(' '), stripped.length()); | |||
//System.err.println("> type: " + type); | |||
if (type.equals("boolean")) { | |||
writer.println(" = false"); | |||
} else if (type.equals("char")) { | |||
writer.println(" = '0'"); | |||
} else if (type.equals("byte")) { | |||
writer.println(" = 0"); | |||
} else if (type.equals("short")) { | |||
writer.println(" = 0"); | |||
} else if (type.equals("int")) { | |||
writer.println(" = 0"); | |||
} else if (type.equals("long")) { | |||
writer.println(" = 0"); | |||
} else if (type.equals("float")) { | |||
writer.println(" = 0"); | |||
} else if (type.equals("double")) { | |||
writer.println(" = 0"); | |||
} else if (type.equals("String")) { | |||
writer.println(" = \"\""); | |||
} else { | |||
writer.println(" = null"); | |||
} | |||
} | |||
writer.println(";"); | |||
// } else if ((!decl.hasBody() && !decl.getKind().equals( "interface" ) || | |||
// (decl.getKind().equals( "method" ) && declaringDeclIsInterface)) && // !!! bug in Jim's API? | |||
// !(decl.getKind().equals("initializer") && decl.getModifiers().indexOf("static") != -1 ) ) { | |||
// | |||
// writer.println(";"); | |||
} else { | |||
if (subs != null) { | |||
if ( decl.getKind().equals( "interface" ) ) { | |||
declaringDeclIsInterface = true; | |||
} | |||
writer.println("{"); | |||
doDecls(subs, writer, declaringDeclIsInterface); | |||
writer.println("}"); | |||
} | |||
} | |||
writer.println(); | |||
} | |||
} | |||
static int nextDeclID = 0; | |||
static String addDeclID(Declaration decl, String formalComment) { | |||
String declID = "" + ++nextDeclID; | |||
declIDTable.put(declID, decl); | |||
return addToFormal(formalComment, Config.DECL_ID_STRING + declID + Config.DECL_ID_TERMINATOR); | |||
} | |||
/** | |||
* We want to go: | |||
* just before the first period | |||
* just before the first @ | |||
* just before the end of the comment | |||
* | |||
* Adds a place holder for the period ('#') if one will need to be | |||
* replaced. | |||
*/ | |||
static String addToFormal(String formalComment, String string) { | |||
boolean appendPeriod = true; | |||
if ( (formalComment == null) || formalComment.equals("")) { | |||
//formalComment = "/**\n * . \n */\n"; | |||
formalComment = "/**\n * \n */\n"; | |||
appendPeriod = false; | |||
} | |||
formalComment = formalComment.trim(); | |||
int atsignPos = formalComment.indexOf('@'); | |||
int endPos = formalComment.indexOf("*/"); | |||
int periodPos = formalComment.indexOf("/**")+2; | |||
//if ( atsignPos == -1 ) { | |||
// periodPos = formalComment.lastIndexOf("."); | |||
//} else { | |||
// periodPos = formalComment.substring(0, atsignPos).lastIndexOf("."); | |||
//} | |||
int position = 0; | |||
String periodPlaceHolder = ""; | |||
if ( periodPos != -1 ) { | |||
position = periodPos+1; | |||
//if ( appendPeriod ) { | |||
//periodPlaceHolder = "#"; | |||
//} | |||
} | |||
else if ( atsignPos != -1 ) { | |||
string = string + "\n * "; | |||
position = atsignPos; | |||
} | |||
else if ( endPos != -1 ) { | |||
string = "* " + string + "\n"; | |||
position = endPos; | |||
} | |||
else { | |||
// !!! perhaps this error should not be silent | |||
throw new Error("Failed to append to formal comment for comment: " + | |||
formalComment ); | |||
} | |||
return | |||
formalComment.substring(0, position) + periodPlaceHolder + | |||
string + | |||
formalComment.substring(position); | |||
} | |||
} |
@@ -0,0 +1,66 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 1999-2001 Xerox Corporation, | |||
* 2002 Palo Alto Research Center, Incorporated (PARC). | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Common Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/cpl-v10.html | |||
* | |||
* Contributors: | |||
* Xerox/PARC initial implementation | |||
* Mik Kersten port to AspectJ 1.1+ code base | |||
* ******************************************************************/ | |||
package org.aspectj.tools.ajdoc; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.BufferedWriter; | |||
import java.io.PrintWriter; | |||
import java.io.IOException; | |||
import java.io.BufferedReader; | |||
import java.io.FileReader; | |||
import java.io.FileWriter; | |||
import java.io.StringReader; | |||
import java.util.*; | |||
class Phase2 { | |||
static void callJavadoc( String[] javadocargs ) { | |||
final SecurityManager defaultSecurityManager = System.getSecurityManager(); | |||
System.setSecurityManager( new SecurityManager() { | |||
public void checkExit(int status) { | |||
if (status == 0) { | |||
throw new SecurityException(); | |||
} | |||
else { | |||
System.setSecurityManager(defaultSecurityManager); | |||
//System.out.println("Error: javadoc exited unexpectedly"); | |||
System.exit(0); | |||
throw new SecurityException(); | |||
} | |||
} | |||
public void checkPermission( java.security.Permission permission ) { | |||
if ( defaultSecurityManager != null ) | |||
defaultSecurityManager.checkPermission( permission ); | |||
} | |||
public void checkPermission( java.security.Permission permission, | |||
Object context ) { | |||
if ( defaultSecurityManager != null ) | |||
defaultSecurityManager.checkPermission( permission, context ); | |||
} | |||
} ); | |||
try { | |||
com.sun.tools.javadoc.Main.main( javadocargs ); | |||
} | |||
catch ( SecurityException se ) { | |||
// Do nothing since we expect it to be thrown | |||
//System.out.println( ">> se: " + se.getMessage() ); | |||
} | |||
// Set the security manager back | |||
System.setSecurityManager( defaultSecurityManager ); | |||
} | |||
} |
@@ -0,0 +1,731 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 1999-2001 Xerox Corporation, | |||
* 2002 Palo Alto Research Center, Incorporated (PARC). | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Common Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/cpl-v10.html | |||
* | |||
* Contributors: | |||
* Xerox/PARC initial implementation | |||
* Mik Kersten port to AspectJ 1.1+ code base | |||
* ******************************************************************/ | |||
package org.aspectj.tools.ajdoc; | |||
import java.io.File; | |||
import java.io.FileOutputStream; | |||
import java.io.BufferedWriter; | |||
import java.io.PrintWriter; | |||
import java.io.IOException; | |||
import java.io.BufferedReader; | |||
import java.io.FileReader; | |||
import java.io.FileWriter; | |||
import java.io.StringReader; | |||
import java.util.*; | |||
class Phase3 { | |||
static List visibleFileList = new ArrayList(); | |||
static Hashtable declIDTable = null; | |||
static SymbolManager symbolManager = null; | |||
static File rootDir = null; | |||
static void decorateHTMLFromInputFiles(Hashtable table, | |||
File newRootDir, | |||
SymbolManager sm, | |||
File[] inputFiles, | |||
String docModifier ) throws IOException { | |||
rootDir = newRootDir; | |||
declIDTable = table; | |||
symbolManager = sm; | |||
for (int i = 0; i < inputFiles.length; i++) { | |||
decorateHTMLFromDecls(symbolManager.getDeclarations(inputFiles[i].getCanonicalPath()), | |||
rootDir.getCanonicalPath() + Config.DIR_SEP_CHAR, | |||
docModifier, | |||
false); | |||
} | |||
} | |||
static void decorateHTMLFromDecls(Declaration[] decls, String base, String docModifier, boolean exceededNestingLevel) throws IOException { | |||
if ( decls != null ) { | |||
for (int i = 0; i < decls.length; i++) { | |||
Declaration decl = decls[i]; | |||
decorateHTMLFromDecl(decl, base, docModifier, exceededNestingLevel); | |||
} | |||
} | |||
} | |||
/** | |||
* Before attempting to decorate the HTML file we have to verify that it exists, | |||
* which depends on the documentation visibility specified to javadoc. | |||
* | |||
* Depending on docModifier, can document | |||
* - public: only public | |||
* - protected: protected and public (default) | |||
* - package: package protected and public | |||
* - private: everything | |||
*/ | |||
static void decorateHTMLFromDecl(Declaration decl, | |||
String base, | |||
String docModifier, | |||
boolean exceededNestingLevel ) throws IOException { | |||
boolean nestedClass = false; | |||
if ( decl.isType() ) { | |||
boolean decorateFile = true; | |||
if ( (docModifier.equals( "private" )) || // everything | |||
(docModifier.equals( "package" ) && decl.getModifiers().indexOf( "private" ) == -1) || // package | |||
(docModifier.equals( "protected" ) && (decl.getModifiers().indexOf( "protected" ) != -1 || | |||
decl.getModifiers().indexOf( "public" ) != -1 )) || | |||
(docModifier.equals( "public" ) && decl.getModifiers().indexOf( "public" ) != -1) ) { | |||
visibleFileList.add( getName( decl ) ); | |||
String packageName = decl.getPackageName(); | |||
String filename = ""; | |||
//System.out.println(">>>" + decl.getDeclaringType() + ", " + base); | |||
if ( packageName != null ) { | |||
int index1 = base.lastIndexOf(Config.DIR_SEP_CHAR); | |||
int index2 = base.lastIndexOf("."); | |||
String currFileClass = ""; | |||
if (index1 > -1 && index2 > 0 && index1 < index2) { | |||
currFileClass = base.substring(index1+1, index2); | |||
} | |||
if (currFileClass.equals(decl.getDeclaringType())) { | |||
// !!! hack for inner class !!! | |||
packageName = packageName.replace( '.','/' ); | |||
String newBase = ""; | |||
if ( base.lastIndexOf(Config.DIR_SEP_CHAR) > 0 ) { | |||
newBase = base.substring(0, base.lastIndexOf(Config.DIR_SEP_CHAR)); | |||
} | |||
filename = newBase + Config.DIR_SEP_CHAR + packageName + | |||
Config.DIR_SEP_CHAR + currFileClass + "." + | |||
getName(decl) + ".html"; | |||
nestedClass = true; | |||
} | |||
else { | |||
packageName = packageName.replace( '.','/' ); // !!! | |||
filename = base + packageName + Config.DIR_SEP_CHAR + getName(decl) + ".html"; | |||
} | |||
} | |||
else { | |||
filename = base + getName(decl) + ".html"; | |||
} | |||
if (!exceededNestingLevel) { | |||
decorateHTMLFile(new File(filename)); | |||
decorateHTMLFromDecls(decl.getDeclarations(), | |||
base + getName(decl) + ".", | |||
docModifier, | |||
nestedClass); | |||
} | |||
else { | |||
System.out.println("Warning: can not generate documentation for nested " + | |||
"inner class: " + getName(decl) ); | |||
} | |||
} | |||
} | |||
} | |||
static void decorateHTMLFile(File file) throws IOException { | |||
System.out.println( "> Decorating " + file.getCanonicalPath() + "..." ); | |||
BufferedReader reader = new BufferedReader(new FileReader(file)); | |||
StringBuffer fileContents = new StringBuffer(); | |||
String line = reader.readLine(); | |||
while( line != null ) { | |||
fileContents.append(line + "\n"); | |||
line = reader.readLine(); | |||
} | |||
boolean isSecond = false; | |||
int index = 0; | |||
Declaration decl; | |||
while ( true ) { | |||
//---this next part is an inlined procedure that returns two values--- | |||
//---the next declaration and the index at which that declaration's--- | |||
//---DeclID sits in the .html file --- | |||
String contents = fileContents.toString(); | |||
int start = contents.indexOf( Config.DECL_ID_STRING, index); | |||
int end = contents.indexOf( Config.DECL_ID_TERMINATOR, index ); | |||
if ( start == -1 ) | |||
decl = null; | |||
else if ( end == -1 ) | |||
throw new Error("Malformed DeclID."); | |||
else { | |||
String tid = contents.substring(start + Config.DECL_ID_STRING.length(), end); | |||
decl = (Declaration)declIDTable.get(tid); | |||
index = start; | |||
} | |||
//--- --- | |||
//--- --- | |||
if ( decl == null ) break; | |||
fileContents.delete(start, end + Config.DECL_ID_TERMINATOR.length()); | |||
if ( decl.isType() ) { | |||
isSecond = true; | |||
goAddIntroductions(decl, fileContents, index); | |||
goAddAdvice(decl, fileContents, index); | |||
goAddCrosscuts(decl, fileContents, index); | |||
} | |||
else { | |||
decorateMemberDocumentation(decl, fileContents, index); | |||
} | |||
} | |||
// Change "Class" to "Aspect", HACK: depends on "affects:" | |||
if (fileContents.toString().indexOf("affects: ") != -1) { | |||
int classStartIndex = fileContents.toString().indexOf("<BR>\nClass "); | |||
int classEndIndex = fileContents.toString().indexOf("</H2>", classStartIndex); | |||
if (classStartIndex != -1 && classEndIndex != -1) { | |||
String classLine = fileContents.toString().substring(classStartIndex, classEndIndex); | |||
String aspectLine = "<BR>\n" + "Aspect" + classLine.substring(11, classLine.length()); | |||
fileContents.delete(classStartIndex, classEndIndex); | |||
fileContents.insert(classStartIndex, aspectLine); | |||
} | |||
} | |||
file.delete(); | |||
FileOutputStream fos = new FileOutputStream( file ); | |||
fos.write( fileContents.toString().getBytes() ); | |||
} | |||
static void goAddCrosscuts(Declaration decl, StringBuffer fileBuffer, int index ) { | |||
Declaration[] crosscuts = decl.getCrosscutDeclarations(); | |||
if ( crosscuts.length > 0 ) { | |||
insertDeclarationsSummary(fileBuffer, crosscuts, "Pointcut Summary", index); | |||
insertDeclarationsDetails(fileBuffer, crosscuts, "Pointcut Detail", index); | |||
} | |||
} | |||
static void goAddAdvice(Declaration decl, StringBuffer fileBuffer, int index ) { | |||
Declaration[] advice = decl.getAdviceDeclarations(); | |||
if ( advice.length > 0 ) { | |||
insertDeclarationsSummary(fileBuffer, advice, "Advice Summary", index); | |||
insertDeclarationsDetails(fileBuffer, advice, "Advice Detail", index); | |||
} | |||
} | |||
static void goAddIntroductions(Declaration decl, | |||
StringBuffer fileBuffer, | |||
int index ) { | |||
Declaration[] introductions = decl.getIntroductionDeclarations(); | |||
if ( introductions.length > 0 ) { | |||
insertDeclarationsSummary(fileBuffer, | |||
introductions, | |||
"Introduction Summary", | |||
index); | |||
insertDeclarationsDetails(fileBuffer, | |||
introductions, | |||
"Introduction Detail", | |||
index); | |||
} | |||
} | |||
static void insertDeclarationsSummary(StringBuffer fileBuffer, | |||
Declaration[] decls, | |||
String kind, | |||
int index) { | |||
int insertIndex = findSummaryIndex(fileBuffer, index); | |||
// insert the head of the table | |||
String tableHead = | |||
"<!-- ======== " + kind.toUpperCase() + " ======= -->\n\n" + | |||
"<TABLE BORDER=\"1\" WIDTH=\"100%\" CELLPADDING=\"1\"" + | |||
"CELLSPACING=\"0\"><TR><TD COLSPAN=2 BGCOLOR=\"#CCCCFF\">" + | |||
"<FONT SIZE=\"+2\"><B>" + kind + "</B></FONT></TD></TR>\n"; | |||
fileBuffer.insert(insertIndex, tableHead); | |||
insertIndex += tableHead.length(); | |||
// insert the body of the table | |||
for ( int i = 0; i < decls.length; i++ ) { | |||
Declaration decl = decls[i]; | |||
// insert the table row accordingly | |||
String comment = generateSummaryComment(decl); | |||
String entry = ""; | |||
if ( kind.equals( "Advice Summary" ) ) { | |||
entry += | |||
"<TR><TD>" + | |||
"<A HREF=\"#" + generateHREFName(decl) + "\">" + | |||
"<TT>advice " + decl.getCrosscutDesignator() + "</TT></A><BR><TT>" + | |||
generateAdviceSignatures(decl) + "</TT><BR> "; | |||
if (!comment.equals("")) { | |||
entry += comment + "<P>"; | |||
} | |||
entry += | |||
generateAffects(decl, false) + "</TD>" + | |||
"</TR><TD>\n"; | |||
} | |||
else if ( kind.equals( "Pointcut Summary" ) ) { | |||
entry += | |||
"<TR><TD WIDTH=\"1%\">" + | |||
"<FONT SIZE=-1><TT>" + decl.getModifiers() + "</TT></FONT>" + | |||
"</TD>\n" + | |||
"<TD>" + | |||
"<TT><A HREF=\"#" + generateHREFName(decl) + "\">" + | |||
decl.getSignature() + "</A></TT><BR> "; | |||
if (!comment.equals("")) { | |||
entry += comment + "<P>"; | |||
} | |||
entry += | |||
"</TR></TD>\n"; | |||
} | |||
else if ( kind.equals( "Introduction Summary" ) ) { | |||
entry += | |||
"<TR><TD WIDTH=\"1%\">" + | |||
"<FONT SIZE=-1><TT>" + decl.getModifiers() + "</TT></FONT>" + | |||
"</TD>" + | |||
"<TD>" + | |||
"<A HREF=\"#" + generateHREFName(decl) + "\">" + | |||
"<TT>introduction " + decl.getCrosscutDesignator() + "</TT></A><P>" + | |||
generateIntroductionSignatures(decl, false) + | |||
generateAffects(decl, true); | |||
} | |||
// insert the entry | |||
fileBuffer.insert(insertIndex, entry); | |||
insertIndex += entry.length(); | |||
} | |||
// insert the end of the table | |||
String tableTail = "</TABLE><P> \n"; | |||
fileBuffer.insert(insertIndex, tableTail); | |||
insertIndex += tableTail.length(); | |||
} | |||
static void insertDeclarationsDetails(StringBuffer fileBuffer, | |||
Declaration[] decls, | |||
String kind, | |||
int index) { | |||
int insertIndex = findDetailsIndex(fileBuffer, index); | |||
// insert the table heading | |||
String detailsHeading | |||
= "<P> \n" + | |||
"<!-- ======== " + kind.toUpperCase() + " SUMMARY ======= -->\n\n" + | |||
"<TABLE BORDER=\"1\" CELLPADDING=\"3\" CELLSPACING=\"0\" WIDTH=\"100%\">\n" + | |||
"<TR BGCOLOR=\"#CCCCFF\" CLASS=\"TableHeadingColor\">\n" + | |||
"<TD COLSPAN=1><FONT SIZE=\"+2\">\n" + | |||
"<B>" + kind + "</B></FONT></TD>\n" + | |||
"</TR>\n" + | |||
"</TABLE>"; | |||
fileBuffer.insert(insertIndex, detailsHeading); | |||
insertIndex += detailsHeading.length(); | |||
// insert the details | |||
for ( int i = 0; i < decls.length; i++ ) { | |||
Declaration decl = decls[i]; | |||
String entry = ""; | |||
// insert the table row accordingly | |||
entry += "<A NAME=\"" + generateHREFName(decl) + "\"><!-- --></A>\n"; | |||
if ( kind.equals( "Advice Detail" ) ) { | |||
String designatorHREFLink = generateDesignatorHREFLink(decl); | |||
if (designatorHREFLink != null) { | |||
entry += | |||
"<H3>advice " + designatorHREFLink + "</H3><P>"; | |||
} | |||
else { | |||
entry += | |||
"<H3>advice " + decl.getCrosscutDesignator() + "</H3><P>"; | |||
} | |||
entry += | |||
"<TT>" + | |||
generateAdviceSignatures(decl) + "</TT>\n" + "<P>" + | |||
generateDetailsComment(decl) + "<P>" + | |||
generateAffects(decl, false); | |||
} | |||
else if (kind.equals("Pointcut Detail")) { | |||
entry += | |||
"<H3>" + | |||
decl.getSignature() + | |||
"</H3><P>" + | |||
generateDetailsComment(decl); | |||
} | |||
else if (kind.equals("Introduction Detail")) { | |||
//String designatorHREFLink = generateDesignatorHREFLink(decl); | |||
//if (designatorHREFLink != null) { | |||
// entry += | |||
// "<H3>introduction " + designatorHREFLink + "</H3><P>"; | |||
//} | |||
//else { | |||
entry += | |||
"<H3>introduction " + decl.getCrosscutDesignator() + "</H3><P>"; | |||
//} | |||
entry += | |||
generateIntroductionSignatures(decl, true) + | |||
generateAffects(decl, true) + | |||
generateDetailsComment(decl); | |||
} | |||
// insert the entry | |||
if (i != decls.length-1) { | |||
entry += "<P><HR>\n"; | |||
} | |||
else { | |||
entry += "<P>"; | |||
} | |||
fileBuffer.insert(insertIndex, entry); | |||
insertIndex += entry.length(); | |||
} | |||
} | |||
/** | |||
* TODO: don't place the summary first. | |||
*/ | |||
static int findSummaryIndex(StringBuffer fileBuffer, int index) { | |||
String fbs = fileBuffer.toString(); | |||
String MARKER_1 = "<!-- =========== FIELD SUMMARY =========== -->"; | |||
String MARKER_2 = "<!-- ======== CONSTRUCTOR SUMMARY ======== -->"; | |||
int index1 = fbs.indexOf(MARKER_1, index); | |||
int index2 = fbs.indexOf(MARKER_2, index); | |||
if (index1 < index2) { | |||
return index1; | |||
} | |||
else { | |||
return index2; | |||
} | |||
} | |||
static int findDetailsIndex(StringBuffer fileBuffer, int index) { | |||
String fbs = fileBuffer.toString(); | |||
String MARKER_1 = "<!-- ========= CONSTRUCTOR DETAIL ======== -->"; | |||
String MARKER_2 = "<!-- ============ FIELD DETAIL =========== -->"; | |||
String MARKER_3 = "<!-- ============ METHOD DETAIL ========== -->"; | |||
int index1 = fbs.indexOf(MARKER_1, index); | |||
int index2 = fbs.indexOf(MARKER_2, index); | |||
int index3 = fbs.indexOf(MARKER_3, index); | |||
if (index1 < index2 && index1 < index3) { | |||
return index1; | |||
} | |||
else if (index2 < index1 && index2 < index3) { | |||
return index2; | |||
} | |||
else { | |||
return index3; | |||
} | |||
} | |||
static void decorateMemberDocumentation( Declaration decl, | |||
StringBuffer fileContentsBuffer, | |||
int index ) { | |||
if (decl.isIntroduced()) { | |||
// !!! HACK, THIS HAS TO BE CHANGED WITH THE SYMBOL MANAGER | |||
String fname = decl.getFilename(); | |||
int index1 = fname.lastIndexOf('\\'); | |||
int index2 = fname.lastIndexOf(".java"); | |||
String introducingType = fname; | |||
if (index1 != -1 && index2 != -1) { | |||
introducingType = fname.substring(index1+1, index2); | |||
} | |||
//System.out.println( "decl: " + decl.getSignature() + ", ptb: " + decl.getFilename()); | |||
String hrefName = ""; | |||
if (decl.getPackageName() != null ) { | |||
hrefName = decl.getPackageName().replace('.', '/') + Config.DIR_SEP_CHAR + | |||
introducingType; | |||
} | |||
else { | |||
hrefName = introducingType; | |||
} | |||
String hrefLink = generateAffectsHREFLink( hrefName ); | |||
fileContentsBuffer.insert( index, | |||
"<BR><B><FONT COLOR=CC6699>Introduced by: </FONT></B>" + | |||
"<A HREF=\"" + hrefLink + "\">" + | |||
hrefName.replace('/', '.') + "</A>" ); // !!! don't replace | |||
return; | |||
} | |||
Declaration[] ptb = decl.getPointedToBy(); | |||
if ( ptb.length > 0 ) { | |||
String prevName = ""; | |||
String adviceDoc = "<BR><B><FONT COLOR=CC6699>Advised by: </FONT></B>"; | |||
for ( int i = 0; i < ptb.length; i++ ) { | |||
Declaration currDecl = ptb[i]; | |||
String hrefName = ""; | |||
if (currDecl.getPackageName() != null ) { | |||
hrefName = currDecl.getPackageName().replace('.', '/') + Config.DIR_SEP_CHAR + | |||
currDecl.getDeclaringType(); | |||
} | |||
else { | |||
hrefName = currDecl.getDeclaringType(); | |||
} | |||
String hrefLink = generateAffectsHREFLink( hrefName ); | |||
if (!hrefName.equals(prevName)) { // !!! eliminates dupilcates since it's ordered | |||
//if ( currDecl.getKind().equals( "introduction" ) ) { | |||
// fileContentsBuffer.insert( index, | |||
// "<BR><B><FONT COLOR=CC6699>Introduced by: </FONT></B>" + | |||
// "<A HREF=\"" + hrefLink + "\">" + | |||
// hrefName.replace('/', '.') + "</A>" ); // !!! don't replace | |||
// return; | |||
//} | |||
if ( currDecl.getKind().equals( "advice" ) ) { | |||
if ( i > 0 ) { | |||
adviceDoc = adviceDoc + ", "; | |||
} | |||
adviceDoc = adviceDoc + | |||
"<A HREF=\"" + hrefLink + "\">" | |||
+ hrefName.replace('/', '.') + "</A>"; // !!! don't replace | |||
} | |||
} | |||
prevName = hrefName; | |||
} | |||
//adviceDoc += "<BR> "; | |||
fileContentsBuffer.insert( index, adviceDoc ); | |||
//return lineHead + adviceDoc + lineTail; | |||
} | |||
else { | |||
;// nop return lineHead + lineTail; | |||
} | |||
} | |||
/** | |||
* TODO: probably want to make this the same for intros and advice. | |||
*/ | |||
static String generateAffects( Declaration decl, boolean isIntroduction) { | |||
Declaration[] decls = null; | |||
if ( isIntroduction ) { | |||
decls = decl.getTargets(); // !!! | |||
} | |||
else { | |||
decls = decl.getPointsTo(); | |||
} | |||
List addedDecls = new ArrayList(); | |||
List packageList = new ArrayList(); | |||
for ( int i = 0; i < decls.length; i++ ) { | |||
Declaration currDecl = decls[i]; | |||
//if ( currDecl.getDeclaringType().equals( "not$found" ) ) { | |||
// System.out.println( "!!!!!! " + currDecl.getSignature() ); | |||
//} | |||
if ( currDecl != null ) { | |||
String extendedName = ""; | |||
String packageName = currDecl.getPackageName(); | |||
// !!! HACK FOR INNER CLASSES, ONLY WORKS FOR 1 LEVEL OF NESTING !!! | |||
String declaringType = currDecl.getDeclaringType(); | |||
if (packageName != null && !packageName.equals("")) { | |||
if (currDecl.isType() && declaringType != null && !declaringType.equals("not$found")) { | |||
extendedName = packageName.replace('.', '/') + Config.DIR_SEP_CHAR + declaringType + "."; | |||
} | |||
else { | |||
extendedName = packageName.replace('.', '/') + Config.DIR_SEP_CHAR; | |||
} | |||
} | |||
//System.out.println("extendedName: " + extendedName); | |||
if ( isIntroduction ) { | |||
if ( !addedDecls.contains(currDecl.getSignature() ) ) { | |||
//addedDecls.add(currDecl.getPackageName() + "." + currDecl.getSignature()); | |||
addedDecls.add(extendedName + currDecl.getSignature()); | |||
} | |||
} | |||
else if ( !addedDecls.contains(currDecl.getDeclaringType() ) ) { | |||
//addedDecls.add(currDecl.getPackageName() + "." + currDecl.getDeclaringType()); | |||
addedDecls.add(extendedName + currDecl.getDeclaringType()); | |||
} | |||
} | |||
} | |||
Collections.sort(addedDecls, | |||
new Comparator() { | |||
public int compare(Object o1, Object o2) { | |||
String s1 = (String)o1; | |||
String s2 = (String)o2; | |||
return s1.compareTo(s2); | |||
} | |||
} | |||
); | |||
String entry | |||
= "<TABLE WIDTH=\"100%\" BGCOLOR=#FFFFFF><TR><TD WIDTH=\"20\"> </TD>" + | |||
"<TD><FONT SIZE=-1>affects: "; | |||
String prevType = ""; | |||
for ( int j = 0; j < addedDecls.size(); j++ ) { | |||
String currType = (String)addedDecls.get(j); | |||
// don't add duplicates | |||
if ( !currType.equals( prevType ) && currType.indexOf("not$found") == -1 ) { //!!! | |||
if ( j > 0 ) { | |||
entry += ", "; | |||
} | |||
if ( generateAffectsHREFLink(currType) != "" ) { | |||
entry += "<A HREF=\"" + generateAffectsHREFLink(currType) + | |||
"\">" + currType.replace('/', '.') + "</A>"; // !!! don't replace | |||
} | |||
else { | |||
entry += currType; | |||
} | |||
} | |||
prevType = currType; | |||
} | |||
entry += "</FONT></TD></TR></TABLE>\n</TR></TD>\n"; | |||
return entry; | |||
} | |||
static String generateIntroductionSignatures(Declaration decl, boolean isDetails) { | |||
Declaration[] decls = decl.getDeclarations(); | |||
String entry = ""; | |||
for ( int j = 0; j < decls.length; j++ ) { | |||
Declaration currDecl = decls[j]; | |||
if ( currDecl != null ) { | |||
entry += | |||
"<TT><B>" + | |||
currDecl.getSignature() + | |||
"</B></TT><BR>"; | |||
} | |||
if (isDetails) { | |||
entry += generateDetailsComment(currDecl) + "<P>"; | |||
} | |||
else { | |||
entry += generateSummaryComment(currDecl) + "<P>"; | |||
} | |||
} | |||
return entry; | |||
} | |||
static String generateAdviceSignatures( Declaration decl ) { | |||
return "<B>" + decl.getSignature() + "</B>"; | |||
} | |||
static String generateSummaryComment(Declaration decl) { | |||
String COMMENT_INDENT = " "; // !!! | |||
String formattedComment = getFormattedComment(decl); | |||
int periodIndex = formattedComment.indexOf( '.' ); | |||
if (formattedComment.equals("")) { | |||
return ""; | |||
} | |||
else if ( periodIndex != -1 ) { | |||
return COMMENT_INDENT + formattedComment.substring( 0, periodIndex+1 ) ; | |||
} | |||
else { | |||
return COMMENT_INDENT + formattedComment; | |||
} | |||
} | |||
static String generateDetailsComment(Declaration decl) { | |||
return getFormattedComment(decl); | |||
} | |||
static String generateHREFName(Declaration decl) { | |||
String hrefLink = decl.getSignature(); // !!! | |||
return hrefLink; | |||
} | |||
/** | |||
* Figure out the link relative to the package. | |||
*/ | |||
static String generateAffectsHREFLink(String declaringType) { | |||
//String offset = rootDir.getAbsolutePath() + "/" + declaringType.replace('.', '/') + ".html"; | |||
String link = rootDir.getAbsolutePath() + "/" + declaringType + ".html"; | |||
//System.out.println(">>" + link); | |||
return link; | |||
} | |||
/** | |||
* This formats a comment according to the rules in the Java Langauge Spec: | |||
* <I>The text of a docuemntation comment consists of the characters between | |||
* the /** that begins the comment and the 'star-slash' that ends it. The text is | |||
* devided into one or more lines. On each of these lines, the leading * | |||
* characters are ignored; for lines other than the first, blanks and | |||
* tabs preceding the initial * characters are also discarded.</I> | |||
* | |||
* TODO: implement formatting or linking for tags. | |||
*/ | |||
static String getFormattedComment(Declaration decl) { | |||
String formattedComment = ""; | |||
// strip the comment markers | |||
String comment = decl.getFormalComment(); | |||
int startIndex = comment.indexOf("/**"); | |||
int endIndex = comment.indexOf("*/"); | |||
if ( startIndex == -1 ) { | |||
startIndex = 0; | |||
} | |||
else { | |||
startIndex += 3; | |||
} | |||
if ( endIndex == -1 ) { | |||
endIndex = comment.length(); | |||
} | |||
comment = comment.substring( startIndex, endIndex ); | |||
// string the leading whitespace and '*' characters at the beginning of each line | |||
BufferedReader reader | |||
= new BufferedReader( new StringReader( comment ) ); | |||
try { | |||
for (String line = reader.readLine(); line != null; line = reader.readLine()) { | |||
line = line.trim(); | |||
for (int i = 0; i < line.length(); i++ ) { | |||
if ( line.charAt(0) == '*' ) { | |||
line = line.substring(1, line.length()); | |||
} | |||
else { | |||
break; | |||
} | |||
} | |||
// !!! remove any @see and @link tags from the line | |||
//int seeIndex = line.indexOf("@see"); | |||
//int linkIndex = line.indexOf("@link"); | |||
//if ( seeIndex != -1 ) { | |||
// line = line.substring(0, seeIndex) + line.substring(seeIndex); | |||
//} | |||
//if ( linkIndex != -1 ) { | |||
// line = line.substring(0, linkIndex) + line.substring(linkIndex); | |||
//} | |||
formattedComment += line; | |||
} | |||
} catch ( IOException ioe ) { | |||
throw new Error( "Couldn't format comment for declaration: " + | |||
decl.getSignature() ); | |||
} | |||
return formattedComment; | |||
} | |||
static String generateDesignatorHREFLink(Declaration decl) { | |||
Declaration ccutDecl = decl.getCrosscutDeclaration(); | |||
if (ccutDecl != null) { | |||
// !!! the following stuff should use ccutDecl | |||
return | |||
"<A HREF=" + | |||
ccutDecl.getDeclaringType() + ".html#" + generateHREFName(ccutDecl) + ">" + | |||
ccutDecl.getSignature() + "</A>"; | |||
} | |||
else { | |||
//String link = decl.getCrosscutDesignator(); | |||
//System.out.println(">> link: " + link); | |||
//return | |||
// "<A HREF=\"TransportAspect.html#" + generateHREFName( decl ) + "\">" + | |||
// decl.getCrosscutDesignator() + "</A>"; | |||
//return null; | |||
return null; | |||
} | |||
} | |||
// *************************************************************************** // | |||
// ** This stuff should be in Declaration ** // | |||
// *************************************************************************** // | |||
static Declaration getCrosscutDeclaration(Declaration decl) { | |||
//String filename = "D:\\Projects\\AJDoc\\apples\\TransportAspect.java"; | |||
//Declaration[] decls = symbolManager.getDeclarations(filename); | |||
//decls = decls[0].getDeclarations(); | |||
//return decls[decls.length-2]; !!! | |||
return null; | |||
} | |||
static String getName(Declaration decl) { | |||
return decl.getSignature(); | |||
} | |||
} | |||
// | |||
// !!! this stub only guaranteed to work for classes or interfaces | |||
// | |||
/* | |||
static String getFullyQualifiedName(Declaration decl) { | |||
if ( decl.getDeclaringType() == null ) | |||
return getName(decl); | |||
else | |||
return getFullyQualifiedName(decl.getDeclaringType()) + "$" + getName(decl); | |||
} | |||
*/ |
@@ -0,0 +1,54 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 1999-2001 Xerox Corporation, | |||
* 2002 Palo Alto Research Center, Incorporated (PARC). | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Common Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/cpl-v10.html | |||
* | |||
* Contributors: | |||
* Xerox/PARC initial implementation | |||
* Mik Kersten port to AspectJ 1.1+ code base | |||
* ******************************************************************/ | |||
package org.aspectj.tools.ajdoc; | |||
import java.io.Serializable; | |||
import java.io.File; | |||
public class SourceLine implements Serializable { | |||
public int line; | |||
public String filename; | |||
//boolean hasBody; | |||
public SourceLine(String filename, int line) { | |||
this.line = line; | |||
this.filename = filename; | |||
} | |||
public String getDirectory() { | |||
return new File(filename).getParent(); | |||
} | |||
public int hashCode() { | |||
return filename.hashCode() ^ line; | |||
} | |||
public boolean equals(Object other) { | |||
if (!(other instanceof SourceLine)) return false; | |||
SourceLine otherLine = (SourceLine)other; | |||
return otherLine.line == line && otherLine.filename.equals(filename); | |||
} | |||
public String toString() { | |||
return filename + "::" + line; | |||
} | |||
/** | |||
* @return true when the method has a corresponding signature in the source code | |||
* @return false otherwise | |||
*/ | |||
//public boolean hasBody() { return hasBody; } | |||
} |
@@ -0,0 +1,390 @@ | |||
/* ******************************************************************* | |||
* Copyright (c) 1999-2001 Xerox Corporation, | |||
* 2002 Palo Alto Research Center, Incorporated (PARC). | |||
* All rights reserved. | |||
* This program and the accompanying materials are made available | |||
* under the terms of the Common Public License v1.0 | |||
* which accompanies this distribution and is available at | |||
* http://www.eclipse.org/legal/cpl-v10.html | |||
* | |||
* Contributors: | |||
* Xerox/PARC initial implementation | |||
* Mik Kersten port to AspectJ 1.1+ code base | |||
* ******************************************************************/ | |||
package org.aspectj.tools.ajdoc; | |||
import java.util.*; | |||
import org.aspectj.asm.*; | |||
public class SymbolManager { | |||
// public static File mapFilenameToSymbolFile(String filename) { | |||
// return mapFilenameToNewExtensionFile(filename, SYMBOL_FILE_EXTENSION); | |||
// } | |||
// | |||
// public static File mapFilenameToSourceLinesFile(String filename) { | |||
// return mapFilenameToNewExtensionFile(filename, SOURCE_LINES_FILE_EXTENSION); | |||
// } | |||
// | |||
// public static File getSourceToOutputFile(String dirname) { | |||
// return new File(dirname, ".ajsline"); | |||
// } | |||
// | |||
// public static File getOutputToSourceFile(String dirname) { | |||
// return new File(dirname, ".ajoline"); | |||
// } | |||
// | |||
// private static File mapFilenameToNewExtensionFile(String filename, String ext) { | |||
// int lastDot = filename.lastIndexOf('.'); | |||
// String basename = filename; | |||
// if (lastDot != -1) { | |||
// basename = basename.substring(0, lastDot); | |||
// } | |||
// | |||
// return new File(basename+ext); | |||
// } | |||
private static SymbolManager INSTANCE = new SymbolManager(); | |||
public static SymbolManager getDefault() { | |||
return INSTANCE; | |||
} | |||
/** | |||
* @param filePath the full path to the preprocessed source file | |||
* @param lineNumber line number in the preprocessed source file | |||
* @return the <CODE>SourceLine</CODE> corresponding to the original file/line | |||
* @see SourceLine | |||
*/ | |||
public SourceLine mapToSourceLine(String filePath, int lineNumber) { | |||
System.err.println("> mapping: " + filePath); | |||
return null; | |||
// Map map = lookupOutputToSource(filePath); | |||
// | |||
// if (map == null) return null; | |||
// | |||
// return (SourceLine)map.get(new SourceLine(filePath, lineNumber)); | |||
} | |||
/** | |||
* @param filePath the full path to the original source file | |||
* @param lineNumber line number in the original source file | |||
* @return the <CODE>SourceLine</CODE> corresponding to the preprocessed file/line | |||
* @see SourceLine | |||
*/ | |||
public SourceLine mapToOutputLine(String filePath, int lineNumber) { | |||
return null; | |||
// Map map = lookupSourceToOutput(filePath); | |||
// | |||
// if (map == null) return null; | |||
// | |||
// return (SourceLine)map.get(new SourceLine(filePath, lineNumber)); | |||
} | |||
/**** | |||
public int mapToOutputLine(String filename, int line) { | |||
Vector sourceLines = lookupSourceLines(filename); | |||
// do linear search here | |||
if (sourceLines == null) return -1; | |||
for(int outputLine = 0; outputLine < sourceLines.size(); outputLine++) { | |||
SourceLine sl = (SourceLine)sourceLines.elementAt(outputLine); | |||
if (sl == null) continue; | |||
if (sl.line == line) { | |||
String outputRoot = new File(filename).getName(); | |||
String sourceRoot = new File(sl.filename).getName(); | |||
if (outputRoot.equals(sourceRoot)) return outputLine + 1; | |||
} | |||
} | |||
return -1; | |||
} | |||
****/ | |||
/** | |||
* TODO: only works for one class | |||
*/ | |||
public Declaration[] getDeclarations(String filename) { | |||
IProgramElement file = (IProgramElement)AsmManager.getDefault().getHierarchy().findElementForSourceFile(filename); | |||
IProgramElement node = (IProgramElement)file.getChildren().get(0); | |||
// Declaration[] decls = new Declaration[node.getChildren().size()+1]; | |||
final List nodes = new ArrayList(); | |||
HierarchyWalker walker = new HierarchyWalker() { | |||
public void preProcess(IProgramElement node) { | |||
IProgramElement p = (IProgramElement)node; | |||
nodes.add(buildDecl(p)); | |||
} | |||
}; | |||
file.walk(walker); | |||
return (Declaration[])nodes.toArray(new Declaration[nodes.size()]); | |||
// return lookupDeclarations(filename); | |||
} | |||
private Declaration buildDecl(IProgramElement node) { | |||
System.err.println("> getting decs: " + node); | |||
String modifiers = ""; | |||
for (Iterator modIt = node.getModifiers().iterator(); modIt.hasNext(); ) { | |||
modifiers += modIt.next() + " "; | |||
} | |||
// Declaration dec = new Declaration( | |||
// node.getSourceLocation().getLine(), | |||
// node.getSourceLocation().getEndLine(), | |||
// node.getSourceLocation().getColumn(), | |||
// -1, | |||
// modifiers, | |||
// node.getName(), | |||
// node.getFullSignature(), | |||
// "", | |||
// node.getDeclaringType(), | |||
// node.getKind(), | |||
// node.getSourceLocation().getSourceFile().getAbsolutePath(), | |||
// node.getFormalComment(), | |||
// node.getPackageName() | |||
// ); | |||
// return dec; | |||
return null; | |||
} | |||
// // In the unusual case that there are multiple declarations on a single line | |||
// // This will return a random one | |||
// public Declaration getDeclarationAtLine(String filename, int line) { | |||
// return getDeclarationAtPoint(filename, line, -1); | |||
// } | |||
public Declaration getDeclarationAtPoint(String filename, int line, int column) { | |||
Declaration[] declarations = lookupDeclarations(filename); | |||
//System.out.println("getting "+filename+", "+line+":"+column); | |||
//System.out.println("decs: "+declarations); | |||
return getDeclarationAtPoint(declarations, line, column); | |||
} | |||
public Declaration getDeclarationAtPoint(Declaration[] declarations, int line, int column) { | |||
//!!! when we care about the performance of this method | |||
//!!! these should be guaranteed to be sorted and a binary search used here | |||
//!!! for now we use the simple (and reliable) linear search | |||
if (declarations == null) return null; | |||
for(int i=0; i<declarations.length; i++) { | |||
Declaration dec = declarations[i]; | |||
if (dec.getBeginLine() == line) { // && dec.getEndLine() >= line) { | |||
if (column == -1) return dec; | |||
if (dec.getBeginColumn() == column) { // && dec.getEndColumn() >= column) { | |||
return dec; | |||
} | |||
} | |||
Declaration[] enclosedDecs = dec.getDeclarations(); | |||
if (enclosedDecs.length == 0) continue; | |||
Declaration dec1 = getDeclarationAtPoint(enclosedDecs, line, column); | |||
if (dec1 != null) return dec1; | |||
} | |||
//??? what should be returned for no declaration found | |||
return null; | |||
} | |||
// private Hashtable symbolFileEntryCache = new Hashtable(); | |||
private Declaration[] lookupDeclarations(String filename) { | |||
System.err.println("> looking up: " + filename); | |||
return null; | |||
// CorrFileEntry entry = lookup(filename, mapFilenameToSymbolFile(filename), | |||
// symbolFileEntryCache); | |||
// return (Declaration[])entry.data; | |||
} | |||
// private Hashtable sourceToOutputCache = new Hashtable(); | |||
// private Hashtable outputToSourceCache = new Hashtable(); | |||
// private Map lookupSourceToOutput(String filename) { | |||
// CorrFileEntry entry = lookup(filename, | |||
// getSourceToOutputFile(new File(filename).getParent()), | |||
// sourceToOutputCache); | |||
// return (Map)entry.data; | |||
// } | |||
// private Map lookupOutputToSource(String filename) { | |||
// CorrFileEntry entry = lookup(filename, | |||
// getOutputToSourceFile(new File(filename).getParent()), | |||
// outputToSourceCache); | |||
// return (Map)entry.data; | |||
// } | |||
/* generic code for dealing with correlation files, serialization, and caching */ | |||
// private static class CorrFileEntry { | |||
// public long lastModified; | |||
// public Object data; | |||
// | |||
// public CorrFileEntry(long lastModified, Object data) { | |||
// this.lastModified = lastModified; | |||
// this.data = data; | |||
// } | |||
// } | |||
// private CorrFileEntry lookup(String filename, File file, Hashtable cache) { | |||
// CorrFileEntry entry = (CorrFileEntry)cache.get(filename); | |||
// if (entry != null && entry.lastModified == file.lastModified()) { | |||
// return entry; | |||
// } | |||
// | |||
// entry = createCorrFileEntry(file); | |||
// cache.put(filename, entry); | |||
// return entry; | |||
// } | |||
// private CorrFileEntry createCorrFileEntry(File file) { | |||
// if (!file.exists()) { | |||
// return new CorrFileEntry(0l, null); | |||
// } | |||
// | |||
// try { | |||
// long lastModified = file.lastModified(); | |||
// ObjectInputStream stream = | |||
// new ObjectInputStream(new BufferedInputStream(new FileInputStream(file))); | |||
// Object data = stream.readObject(); | |||
// stream.close(); | |||
// return new CorrFileEntry(lastModified, data); | |||
// } catch (IOException ioe) { | |||
// //System.err.println("ERROR!!!"); | |||
// //ioe.printStackTrace(); | |||
// return new CorrFileEntry(0l, null); | |||
// } catch (ClassNotFoundException cce) { | |||
// //System.err.println("ERROR!!!"); | |||
// //cce.printStackTrace(); | |||
// return new CorrFileEntry(0l, null); | |||
// } | |||
// } | |||
/** | |||
* @param methodName method name without type or parameter list | |||
* @return method name with ajc-specific name mangling removed, | |||
* unchanged if there's not ajc name mangling present | |||
*/ | |||
public static String translateMethodName(String methodName) { | |||
int firstDollar = methodName.indexOf('$'); | |||
if (firstDollar == -1) return methodName; | |||
String baseName = methodName.substring(firstDollar); | |||
if (methodName.indexOf("ajc") != -1) { | |||
return "<" + baseName + " advice>"; | |||
} else { | |||
return baseName; | |||
} | |||
} | |||
/************************************************************************ | |||
The rest of the code in this file is just for testing purposes | |||
************************************************************************/ | |||
// private static final void printIndentation(int indent, String prefix) { | |||
// for(int i=0; i< indent; i++) System.out.print(" "); | |||
// System.out.print(prefix); | |||
// } | |||
// | |||
// | |||
// private static final void printDeclaration(Declaration dec, int indent, String prefix) { | |||
// printIndentation(indent, prefix); | |||
// if (dec == null) { | |||
// System.out.println("null"); | |||
// return; | |||
// } | |||
// | |||
// System.out.println(dec.getKind()+": "+dec.getDeclaringType()+": "+ | |||
// dec.getModifiers()+": "+dec.getSignature()+": " + | |||
// //dec.getFullSignature()+": "+ | |||
// dec.getCrosscutDesignator()+ | |||
// ": "+dec.isIntroduced()+": "+dec.getPackageName()+": "+dec.getBeginLine()+":"+dec.getBeginColumn() | |||
// ); | |||
// | |||
// //printIndentation(indent, "\"\"\""); | |||
// //System.out.println(dec.getFormalComment()); | |||
// /* | |||
// if (dec.getParentDeclaration() != null) { | |||
// printDeclaration(dec.getParentDeclaration(), indent+INDENT, "PARENT "); | |||
// } | |||
// if (dec.getCrosscutDeclaration() != null) { | |||
// printDeclaration(dec.getCrosscutDeclaration(), indent+INDENT, "XC "); | |||
// } | |||
// */ | |||
// if (prefix.equals("")) { | |||
// printDeclarations(dec.getTargets(), indent+INDENT, "T> "); | |||
// printDeclarations(dec.getPointsTo(), indent+INDENT, ">> "); | |||
// printDeclarations(dec.getPointedToBy(), indent+INDENT, "<< "); | |||
// printDeclarations(dec.getDeclarations(), indent+INDENT, ""); | |||
// } | |||
// } | |||
// private static final void printDeclarations(Declaration[] decs, int indent, String prefix) { | |||
// for(int i=0; i<decs.length; i++) { | |||
// printDeclaration(decs[i], indent, prefix); | |||
// } | |||
// } | |||
// private static final int INDENT = 2; | |||
// static void printLines(String filename, Map baseMap) throws IOException { | |||
// if (baseMap == null) return; | |||
// | |||
// String fullName = new File(filename).getCanonicalPath(); | |||
// java.util.TreeMap map = new java.util.TreeMap(); | |||
// | |||
// for (Iterator i = baseMap.entrySet().iterator(); i.hasNext(); ) { | |||
// Map.Entry entry = (Map.Entry)i.next(); | |||
// SourceLine keyLine = (SourceLine)entry.getKey(); | |||
// if (!keyLine.filename.equals(fullName)) continue; | |||
// | |||
// map.put(new Integer(keyLine.line), entry.getValue()); | |||
// } | |||
// | |||
// for (java.util.Iterator j = map.entrySet().iterator(); j.hasNext(); ) { | |||
// java.util.Map.Entry entry = (java.util.Map.Entry)j.next(); | |||
// | |||
// System.out.println(entry.getKey() + ":\t" + entry.getValue()); | |||
// } | |||
// } | |||
// public static void main(String[] args) throws IOException { | |||
// for(int i=0; i<args.length; i++) { | |||
// String filename = args[i]; | |||
// System.out.println(filename); | |||
// | |||
// System.out.println("declaration mappings"); | |||
// System.out.println("kind: declaringType: modifiers: signature: fullSignature: crosscutDesignator: isIntroduced: packageName: parentDeclaration"); | |||
// | |||
// Declaration[] declarations = getSymbolManager().getDeclarations(filename); | |||
// if (declarations != null) { | |||
// printDeclarations(declarations, INDENT, ""); | |||
// } | |||
// | |||
// System.out.println("source to output"); | |||
// printLines(filename, getSymbolManager().lookupSourceToOutput(filename)); | |||
// System.out.println("output to source"); | |||
// printLines(filename, getSymbolManager().lookupOutputToSource(filename)); | |||
// } | |||
// } | |||
} |
@@ -0,0 +1 @@ | |||
figures-demo-all.ajsym |
@@ -0,0 +1,3 @@ | |||
figures/*.java | |||
figures/support/*.java | |||
figures/gui/*.java |
@@ -0,0 +1,55 @@ | |||
/* | |||
Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved. | |||
*/ | |||
package figures; | |||
import java.awt.*; | |||
import java.awt.geom.*; | |||
public class Box extends ShapeFigureElement { | |||
private Point _p0; | |||
private Point _p1; | |||
private Point _p2; | |||
private Point _p3; | |||
public Box(int x0, int y0, int width, int height) { | |||
_p0 = new Point(x0, y0); | |||
_p1 = new Point(x0+width, y0); | |||
_p2 = new Point(x0+width, y0+height); | |||
_p3 = new Point(x0, y0+height); | |||
} | |||
public Point getP0() { return _p0; } | |||
public Point getP1() { return _p1; } | |||
public Point getP2() { return _p2; } | |||
public Point getP3() { return _p3; } | |||
public void move(int dx, int dy) { | |||
_p0.move(dx, dy); | |||
_p1.move(dx, dy); | |||
_p2.move(dx, dy); | |||
_p3.move(dx, dy); | |||
} | |||
public void checkBoxness() { | |||
if ((_p0.getX() == _p3.getX()) && | |||
(_p1.getX() == _p2.getX()) && | |||
(_p0.getY() == _p1.getY()) && | |||
(_p2.getY() == _p3.getY())) | |||
return; | |||
throw new IllegalStateException("This is not a square."); | |||
} | |||
public String toString() { | |||
return "Box(" + _p0 + ", " + _p1 + ", " + _p2 + ", " + _p3 + ")"; | |||
} | |||
public Shape getShape() { | |||
return new Rectangle(getP1().getX(), | |||
getP1().getY(), | |||
getP3().getX() - getP1().getX(), | |||
getP3().getY() - getP1().getY()); | |||
} | |||
} | |||
@@ -0,0 +1,11 @@ | |||
/* | |||
Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved. | |||
*/ | |||
package figures; | |||
public class Canvas { | |||
public static void updateHistory() { | |||
// not implemented | |||
} | |||
} |
@@ -0,0 +1,20 @@ | |||
/* | |||
Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved. | |||
*/ | |||
package figures; | |||
import java.awt.Color; | |||
import figures.FigureElement; | |||
public aspect ColorControl { | |||
public static void setFillColor(FigureElement fe, Color color) { | |||
// fill in here | |||
} | |||
public static void setLineColor(FigureElement fe, Color color) { | |||
// fill in here | |||
} | |||
// fill in here | |||
} |
@@ -0,0 +1,65 @@ | |||
/* | |||
* (c) Copyright 2001 MyCorporation. | |||
* All Rights Reserved. | |||
*/ | |||
package figures; | |||
public aspect Enforcement { | |||
before(int newValue): set(int Point.*) && args(newValue) { | |||
if (newValue < 0) { | |||
throw new IllegalArgumentException("> val: " + newValue + " is too small"); | |||
} | |||
} | |||
declare warning: call(void Canvas.updateHistory(..)) && !within(Enforcement): ""; | |||
after() returning: call(void FigureElement+.set*(..)) { | |||
//Canvas.updateHistory(); | |||
} | |||
declare error: | |||
set(private * FigureElement+.*) && | |||
!(withincode(* FigureElement+.set*(..)) || withincode(FigureElement+.new(..))): | |||
"should only assign to fileds from set methods"; | |||
} | |||
// before(int newValue): set(int Point.*) && args(newValue) { | |||
// if (newValue < 0) { | |||
// throw new IllegalArgumentException("> value: " + newValue + " too small"); | |||
// } | |||
// } | |||
// | |||
// declare warning: call(void Canvas.updateHistory(..)) && !within(Enforcement): | |||
// "found call"; | |||
// | |||
// after() returning: call(void FigureElement+.set*(..)) { | |||
// Canvas.updateHistory(); | |||
// } | |||
// | |||
// declare error: | |||
// set(private * FigureElement+.*) && | |||
// !(withincode(* FigureElement+.set*(..)) || withincode(FigureElement+.new(..))): | |||
// "should only assign to fields from set methods"; |
@@ -0,0 +1,21 @@ | |||
/* | |||
Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved. | |||
*/ | |||
package figures; | |||
import java.awt.*; | |||
import java.awt.geom.*; | |||
public interface FigureElement { | |||
public static final int MIN_VALUE = 0; | |||
public static final int MAX_VALUE = 500; | |||
public abstract void move(int dx, int dy); | |||
public abstract Rectangle getBounds(); | |||
public abstract boolean contains(Point2D p); | |||
public abstract void paint(Graphics2D g2); | |||
} |
@@ -0,0 +1,88 @@ | |||
/* | |||
Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved. | |||
*/ | |||
package figures; | |||
import java.util.*; | |||
import java.awt.*; | |||
import java.awt.geom.*; | |||
public class Group implements FigureElement { | |||
private Collection _members; | |||
private String _identifier; | |||
public Group(FigureElement first) { | |||
this._members = new ArrayList(); | |||
add(first); | |||
} | |||
public void add(FigureElement fe) { | |||
_members.add(fe); | |||
} | |||
public Iterator members() { | |||
return _members.iterator(); | |||
} | |||
public void move(int dx, int dy) { | |||
for (Iterator i = _members.iterator(); i.hasNext(); ) { | |||
FigureElement fe = (FigureElement)i.next(); | |||
fe.move(dx, dy); | |||
} | |||
} | |||
public void resetIdentifier(String identifier) { | |||
resetIdentifier(identifier); | |||
} | |||
public String toString() { | |||
if (_identifier != null) { | |||
return _identifier; | |||
} | |||
StringBuffer buf = new StringBuffer("Group("); | |||
for (Iterator i = _members.iterator(); i.hasNext(); ) { | |||
buf.append(i.next().toString()); | |||
if (i.hasNext()) { | |||
buf.append(", "); | |||
} | |||
} | |||
buf.append(")"); | |||
return buf.toString(); | |||
} | |||
public Rectangle getBounds() { | |||
Rectangle previous = null; | |||
for (Iterator i = _members.iterator(); i.hasNext(); ) { | |||
FigureElement fe = (FigureElement)i.next(); | |||
Rectangle rect = fe.getBounds(); | |||
if (previous != null) { | |||
previous = previous.union(rect); | |||
} else { | |||
previous = rect; | |||
} | |||
} | |||
return previous; | |||
} | |||
public boolean contains(Point2D p) { | |||
for (Iterator i = _members.iterator(); i.hasNext(); ) { | |||
FigureElement fe = (FigureElement)i.next(); | |||
if (fe.contains(p)) return true; | |||
} | |||
return false; | |||
} | |||
public void paint(Graphics2D g2) { | |||
for (Iterator i = _members.iterator(); i.hasNext(); ) { | |||
FigureElement fe = (FigureElement)i.next(); | |||
fe.paint(g2); | |||
} | |||
} | |||
public int size() { | |||
return _members.size(); | |||
} | |||
} | |||
@@ -0,0 +1,73 @@ | |||
/* | |||
Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved. | |||
*/ | |||
package figures; | |||
import java.awt.*; | |||
import java.awt.geom.*; | |||
public class Line extends ShapeFigureElement { | |||
private Point _p1; | |||
private Point _p2; | |||
public Line(Point p1, Point p2) { | |||
_p1 = p1; | |||
_p2 = p2; | |||
} | |||
public Point getP1() { | |||
return _p1; | |||
} | |||
public void setP1(Point p1) { | |||
_p1 = p1; | |||
Canvas.updateHistory(); | |||
} | |||
public Point getP2() { | |||
return _p2; | |||
} | |||
public void setP2(Point p2) { | |||
_p2 = p2; | |||
Canvas.updateHistory(); | |||
} | |||
public void move(int dx, int dy) { | |||
//_x = dx; | |||
//_y = dy; | |||
//_p1.move(dx, dy); | |||
//_p2.move(dx, dy); | |||
} | |||
public String toString() { | |||
return "Line(" + _p1 + ", " + _p2 + ")"; | |||
} | |||
/** | |||
* Used to determine if this line {@link contains(Point2D)} a point. | |||
*/ | |||
final static int THRESHHOLD = 5; | |||
/** | |||
* Returns <code>true</code> if the point segment distance is less than | |||
* {@link THRESHHOLD}. | |||
*/ | |||
public boolean contains(Point2D p) { | |||
return getLine2D().ptLineDist(p) < THRESHHOLD; | |||
} | |||
private Line2D getLine2D() { | |||
return new Line2D.Float((float)getP1().getX(), | |||
(float)getP1().getY(), | |||
(float)getP2().getX(), | |||
(float)getP2().getY()); | |||
} | |||
public Shape getShape() { | |||
return getLine2D(); | |||
} | |||
} | |||
@@ -0,0 +1,34 @@ | |||
/* | |||
Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved. | |||
*/ | |||
public class Log { | |||
private static StringBuffer data = new StringBuffer(); | |||
public static void traceObject(Object o) { | |||
throw new UnsupportedOperationException(); | |||
} | |||
public static void log(String s) { | |||
data.append(s); | |||
data.append(';'); | |||
} | |||
public static void logClassName(Class _class) { | |||
String name = _class.getName(); | |||
int dot = name.lastIndexOf('.'); | |||
if (dot == -1) { | |||
log(name); | |||
} else { | |||
log(name.substring(dot+1, name.length())); | |||
} | |||
} | |||
public static String getString() { | |||
return data.toString(); | |||
} | |||
public static void clear() { | |||
data.setLength(0); | |||
} | |||
} |
@@ -0,0 +1,59 @@ | |||
/* | |||
Copyright (c) 2001-2002 Palo Alto Research Center Incorporated. All Rights Reserved. | |||
*/ | |||
package figures; | |||
import java.awt.*; | |||
import java.awt.geom.*; | |||
public class Point extends ShapeFigureElement { | |||
private int _x; | |||
private int _y; | |||
public Point(int x, int y) { | |||
_x = x; | |||
_y = y; | |||
} | |||
public int getX() { | |||
return _x; | |||
} | |||
public void setX(int x) { | |||
_x = x; | |||
//Canvas.updateHistory(); | |||
} | |||
public int getY() { | |||
return _y; | |||
} | |||
public void setY(int y) { | |||
_y = y; | |||
//Canvas.updateHistory(); | |||
} | |||
public void move(int dx, int dy) { | |||
setX(_x + dx); | |||
setY(_y + dy); | |||
} | |||
public String toString() { | |||
return "Point(" + _x + ", " + _y + ")"; | |||
} | |||
/** The height of displayed {@link Point}s. */ | |||
private final static int HEIGHT = 10; | |||
/** The width of displayed {@link Point}s. -- same as {@link HEIGHT}. */ | |||
private final static int WIDTH = Point.HEIGHT; | |||
public Shape getShape() { | |||
return new Ellipse2D.Float((float)getX()-Point.WIDTH/2, | |||
(float)getY()-Point.HEIGHT/2, | |||
(float)Point.HEIGHT, | |||
(float)Point.WIDTH); | |||
} | |||
} | |||
@@ -0,0 +1,38 @@ | |||
/* | |||
Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved. | |||
*/ | |||
package figures; | |||
import java.awt.*; | |||
import java.awt.geom.*; | |||
public abstract class ShapeFigureElement implements FigureElement { | |||
public abstract void move(int dx, int dy); | |||
public abstract Shape getShape(); | |||
public Rectangle getBounds() { | |||
return getShape().getBounds(); | |||
} | |||
public boolean contains(Point2D p) { | |||
return getShape().contains(p); | |||
} | |||
public Color getLineColor() { | |||
return Color.black; | |||
} | |||
public Color getFillColor() { | |||
return Color.red; | |||
} | |||
public final void paint(Graphics2D g2) { | |||
Shape shape = getShape(); | |||
g2.setPaint(getFillColor()); | |||
g2.fill(shape); | |||
g2.setPaint(getLineColor()); | |||
g2.draw(shape); | |||
} | |||
} |
@@ -0,0 +1,42 @@ | |||
/* | |||
Copyright (c) 2002 Palo Alto Research Center Incorporated. All Rights Reserved. | |||
*/ | |||
package figures; | |||
import java.awt.*; | |||
import java.awt.geom.*; | |||
/** | |||
* This class makes mistakes to be caught by invariant checkers. | |||
*/ | |||
public class SlothfulPoint extends ShapeFigureElement { | |||
private int _x; | |||
private int _y; | |||
public SlothfulPoint(int x, int y) { | |||
} | |||
public void setX(int x) { | |||
_x = x; | |||
} | |||
public void setY(int y) { | |||
_y = y; | |||
} | |||
public void move(int dx, int dy) { | |||
//_x += dx; | |||
//_y += dy; | |||
} | |||
public String toString() { | |||
return "SlothfulPoint"; | |||
} | |||
public Shape getShape() { | |||
return new Ellipse2D.Float((float)_x, | |||
(float)_y, 1.0f, 1.0f); | |||
} | |||
} | |||