diff options
Diffstat (limited to 'weaver')
-rw-r--r-- | weaver/src/org/aspectj/weaver/Dump.java | 378 | ||||
-rw-r--r-- | weaver/src/org/aspectj/weaver/World.java | 49 | ||||
-rw-r--r-- | weaver/testsrc/org/aspectj/weaver/BcweaverTests.java | 1 | ||||
-rw-r--r-- | weaver/testsrc/org/aspectj/weaver/DumpTestCase.java | 152 |
4 files changed, 565 insertions, 15 deletions
diff --git a/weaver/src/org/aspectj/weaver/Dump.java b/weaver/src/org/aspectj/weaver/Dump.java new file mode 100644 index 000000000..76b06e6a6 --- /dev/null +++ b/weaver/src/org/aspectj/weaver/Dump.java @@ -0,0 +1,378 @@ +/* ******************************************************************* + * Copyright (c) 2004 IBM Corporation + * 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: + * Matthew Webster + * ******************************************************************/ +package org.aspectj.weaver; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.IMessageHolder; +import org.aspectj.bridge.Version; + +/** + * @author websterm + * + * To change the template for this generated type comment go to + * Window>Preferences>Java>Code Generation>Code and Comments + */ +public class Dump { + + /* Format for unique filename based on date & time */ + private static final String FILENAME_PREFIX = "ajcore"; + private static final DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd"); + private static final DateFormat timeFormat = new SimpleDateFormat("HHmmss.SSS"); + private static final String FILENAME_SUFFIX = "txt"; + + public static final String UNKNOWN_FILENAME = "Unknown"; + public static final String DUMP_EXCLUDED = "Excluded"; + public static final String NULL_OR_EMPTY = "Empty"; + + private static Class exceptionClass; + private static IMessage.Kind conditionKind = IMessage.ABORT; + + private String reason; + private String fileName; + private PrintStream print; + + private static String[] savedCommandLine; + private static List savedFullClasspath; + private static IMessageHolder savedMessageHolder; + + private static Map nodes = new HashMap(); + private static String lastDumpFileName = UNKNOWN_FILENAME; + + /* + * Dump methods + */ + public static String dump (String reason) { + String fileName = UNKNOWN_FILENAME; + Dump dump = null; + try { + dump = new Dump(reason); + fileName = dump.getFileName(); + dump.dumpDefault(); + } + finally { + if (dump != null) dump.close(); + } + return fileName; + } + + public static String dumpWithException (Throwable th) { + String fileName = UNKNOWN_FILENAME; + Dump dump = null; + try { + dump = new Dump(th.getClass().getName()); + fileName = dump.getFileName(); + dump.dumpException(th); + } + finally { + if (dump != null) dump.close(); + } + return fileName; + } + + public static String dumpOnExit () { + if (!shouldDumpOnExit()) return DUMP_EXCLUDED; + + String fileName = UNKNOWN_FILENAME; + Dump dump = null; + try { + dump = new Dump(conditionKind.toString()); + fileName = dump.getFileName(); + dump.dumpDefault(); + } + finally { + if (dump != null) dump.close(); + } + return fileName; + } + + private static boolean shouldDumpOnExit () { + return (savedMessageHolder == null) || savedMessageHolder.hasAnyMessage(conditionKind,true); + } + + /* + * Dump configuration + */ + public static void setDumpOnException (boolean b) { + if (b) { + exceptionClass = java.lang.Throwable.class; + } + else { + exceptionClass = null; + } + } + + public static boolean getDumpOnException () { + return (exceptionClass != null); + } + + public static boolean setDumpOnExit (IMessage.Kind condition) { + conditionKind = condition; + return true; + } + + public static boolean setDumpOnExit (String condition) { + for (Iterator i = IMessage.KINDS.iterator(); i.hasNext();) { + IMessage.Kind kind = (IMessage.Kind)i.next(); + if (kind.toString().equals(condition)) { + return setDumpOnExit(kind); + } + } + return false; + } + + public static IMessage.Kind getDumpOnExit () { + return conditionKind; + } + + public static String getLastDumpFileName () { + return lastDumpFileName; + } + + /* + * Dump registration + */ + public static void saveCommandLine (String[] args) { + savedCommandLine = new String[args.length]; + System.arraycopy(args,0,savedCommandLine,0,args.length); + } + + public static void saveFullClasspath (List list) { + savedFullClasspath = list; + } + + public static void saveMessageHolder (IMessageHolder holder) { + savedMessageHolder = holder; + } + + public static void registerNode (Class module, INode newNode) { + nodes.put(module,newNode); + } + + /* + * Dump methods + */ + private Dump (String reason) { + this.reason = reason; + + openDump(); + dumpAspectJProperties(); + dumpDumpConfiguration(); + } + + public String getFileName() { + return fileName; + } + + private void dumpDefault () { + dumpSytemProperties(); + dumpCommandLine(); + dumpFullClasspath(); + dumpCompilerMessages(); + + /* + * Dump registered nodes + */ + IVisitor dumpVisitor = new IVisitor() { + + public void visitString (String s) { + println(s); + } + + public void visitList (List list) { + println(list); + } + }; + for (Iterator i = nodes.keySet().iterator(); i.hasNext();) { + Class module = (Class)i.next(); + println("---- " + module.getName() + " ----"); + INode dumpNode = (INode)nodes.get(module); + try { + dumpNode.accept(dumpVisitor); + } + catch (Exception ex) { + println(ex.toString()); + } + } + } + + private void dumpException (Throwable th) { + println("---- Exception Information ---"); + println(th); + dumpDefault(); + } + + private void dumpAspectJProperties () { + println("---- AspectJ Properties ---"); + println("AspectJ Compiler " + Version.text + " built on " + Version.time_text); + } + + private void dumpDumpConfiguration () { + println("---- Dump Properties ---"); + println("Dump file: " + fileName); + println("Dump reason: " + reason); + println("Dump on exception: " + (exceptionClass != null)); + println("Dump at exit condition: " + conditionKind); + } + + private void dumpFullClasspath () { + println("---- Full Classpath ---"); + if (savedFullClasspath != null && savedFullClasspath.size() > 0) { + for (Iterator iter = savedFullClasspath.iterator(); iter.hasNext(); ) { + String fileName = (String)iter.next(); + File file = new File(fileName); + println(file); + } + } + else { + println(NULL_OR_EMPTY); + } + } + + private void dumpSytemProperties () { + println("---- System Properties ---"); + Properties props = System.getProperties(); + println(props); + } + + private void dumpCommandLine () { + println("---- Command Line ---"); + println(savedCommandLine); + } + + private void dumpCompilerMessages () { + println("---- Compiler Messages ---"); + if (savedMessageHolder != null) for (Iterator i = savedMessageHolder.getUnmodifiableListView().iterator(); i.hasNext(); ) { + IMessage message = (IMessage)i.next(); + println(message.toString()); + } + else { + println(NULL_OR_EMPTY); + } + } + + /* + * Dump output + */ + private void openDump () { + if (print != null) return; + + Date now = new Date(); + fileName = FILENAME_PREFIX + "." + + dateFormat.format(now) + "." + + timeFormat.format(now) + "." + + FILENAME_SUFFIX; + try { + print = new PrintStream(new FileOutputStream(fileName),true); + System.out.println("Dumping to " + fileName); + } + catch (FileNotFoundException ex) { + print = System.err; + System.out.println("Dumping to stderr"); + fileName = UNKNOWN_FILENAME; + } + + lastDumpFileName = fileName; + } + + public void close () { + print.close(); + } + + private void println (String s) { + print.println(s); + } + + private void println (Object[] array) { + if (array == null) { + println(NULL_OR_EMPTY); + return; + } + + for (int i = 0; i < array.length; i++) { + print.println(array[i]); + } + } + + private void println (Properties props) { + Iterator iter = props.keySet().iterator(); + while (iter.hasNext()) { + String key = (String)iter.next(); + String value = props.getProperty(key); + print.println(key + "=" + value); + } + } + + private void println (Throwable th) { + th.printStackTrace(print); + } + + private void println (File file) { + print.print(file.getAbsolutePath()); + if (!file.exists()) { + println("(missing)"); + } + else if (file.isDirectory()) { + int count = file.listFiles().length; + println("(" + count + " entries)"); + } + else { + println("(" + file.length() + " bytes)"); + } + } + + private void println (List list) { + if (list == null || list.isEmpty()) println(NULL_OR_EMPTY); + else for (Iterator i = list.iterator(); i.hasNext();) { + Object o = i.next(); + if (o instanceof Exception) { + println((Exception)o); + } else { + println(i.next().toString()); + } + } + } + + static { + String exceptionName = System.getProperty("org.aspectj.weaver.Dump.exception","true"); + if (!exceptionName.equals("false")) setDumpOnException(true); + + String conditionName = System.getProperty("org.aspectj.weaver.Dump.condition","true"); + setDumpOnExit(conditionName); + } + + public interface INode { + + public void accept (IVisitor visior); + + } + + public interface IVisitor { + + public void visitString (String s); + public void visitList (List list); + } +} diff --git a/weaver/src/org/aspectj/weaver/World.java b/weaver/src/org/aspectj/weaver/World.java index 071af0678..468a6ba8c 100644 --- a/weaver/src/org/aspectj/weaver/World.java +++ b/weaver/src/org/aspectj/weaver/World.java @@ -13,9 +13,11 @@ package org.aspectj.weaver; +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.WeakHashMap; @@ -30,7 +32,7 @@ import org.aspectj.bridge.IMessage.Kind; import org.aspectj.weaver.patterns.DeclarePrecedence; import org.aspectj.weaver.patterns.Pointcut; -public abstract class World { +public abstract class World implements Dump.INode { protected IMessageHandler messageHandler = IMessageHandler.SYSTEM_ERR; protected ICrossReferenceHandler xrefHandler = null; @@ -44,9 +46,12 @@ public abstract class World { protected boolean XnoInline; protected boolean XlazyTjp; + + private List dumpState_cantFindTypeExceptions = null; protected World() { super(); + Dump.registerNode(this.getClass(),this); typeMap.put("B", ResolvedTypeX.BYTE); typeMap.put("S", ResolvedTypeX.SHORT); typeMap.put("I", ResolvedTypeX.INT); @@ -57,6 +62,18 @@ public abstract class World { typeMap.put("Z", ResolvedTypeX.BOOLEAN); typeMap.put("V", ResolvedTypeX.VOID); } + + public void accept (Dump.IVisitor visitor) { + visitor.visitString("Shadow mungers:"); + visitor.visitList(crosscuttingMembersSet.getShadowMungers()); + visitor.visitString("Type mungers:"); + visitor.visitList(crosscuttingMembersSet.getTypeMungers()); + if (dumpState_cantFindTypeExceptions!=null) { + visitor.visitString("Cant find type problems:"); + visitor.visitList(dumpState_cantFindTypeExceptions); + dumpState_cantFindTypeExceptions = null; + } + } public ResolvedTypeX[] resolve(TypeX[] types) { int len = types.length; @@ -110,10 +127,12 @@ public abstract class World { } else { ret = resolveObjectType(ty); if (!allowMissing && ret == ResolvedTypeX.MISSING) { - //Thread.currentThread().dumpStack(); MessageUtil.error(messageHandler, WeaverMessages.format(WeaverMessages.CANT_FIND_TYPE,ty.getName())); - // + " on classpath " + classPath); + if (dumpState_cantFindTypeExceptions==null) { + dumpState_cantFindTypeExceptions = new ArrayList(); + } + dumpState_cantFindTypeExceptions.add(new RuntimeException("Can't find type "+ty.getName())); } } //System.out.println("ret: " + ret); @@ -223,18 +242,18 @@ public abstract class World { // ---- empty world - public static final World EMPTY = new World() { - public List getShadowMungers() { return Collections.EMPTY_LIST; } - public ResolvedTypeX.ConcreteName resolveObjectType(ResolvedTypeX.Name ty) { - return null; - } - public Advice concreteAdvice(AjAttribute.AdviceAttribute attribute, Pointcut p, Member m) { - throw new RuntimeException("unimplemented"); - } - public ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedTypeX aspectType) { - throw new RuntimeException("unimplemented"); - } - }; +// public static final World EMPTY = new World() { +// public List getShadowMungers() { return Collections.EMPTY_LIST; } +// public ResolvedTypeX.ConcreteName resolveObjectType(ResolvedTypeX.Name ty) { +// return null; +// } +// public Advice concreteAdvice(AjAttribute.AdviceAttribute attribute, Pointcut p, Member m) { +// throw new RuntimeException("unimplemented"); +// } +// public ConcreteTypeMunger concreteTypeMunger(ResolvedTypeMunger munger, ResolvedTypeX aspectType) { +// throw new RuntimeException("unimplemented"); +// } +// }; public abstract Advice concreteAdvice( diff --git a/weaver/testsrc/org/aspectj/weaver/BcweaverTests.java b/weaver/testsrc/org/aspectj/weaver/BcweaverTests.java index ac1587b54..94cb7ddac 100644 --- a/weaver/testsrc/org/aspectj/weaver/BcweaverTests.java +++ b/weaver/testsrc/org/aspectj/weaver/BcweaverTests.java @@ -54,6 +54,7 @@ public class BcweaverTests extends TestCase { suite.addTestSuite(TypeXTestCase.class); suite.addTestSuite(WeavingURLClassLoaderTest.class); suite.addTestSuite(WeaverMessagesTestCase.class); + suite.addTestSuite(DumpTestCase.class); //$JUnit-END$ return suite; } diff --git a/weaver/testsrc/org/aspectj/weaver/DumpTestCase.java b/weaver/testsrc/org/aspectj/weaver/DumpTestCase.java new file mode 100644 index 000000000..4354fa907 --- /dev/null +++ b/weaver/testsrc/org/aspectj/weaver/DumpTestCase.java @@ -0,0 +1,152 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * 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: + * Matthew Webster + *******************************************************************************/ +package org.aspectj.weaver; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.Reader; +import java.sql.Savepoint; + +import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.IMessageHolder; +import org.aspectj.bridge.Message; +import org.aspectj.bridge.MessageHandler; +import org.aspectj.util.FileUtil; + +import sun.security.krb5.internal.crypto.d; + +import junit.framework.TestCase; + +/** + * @author websterm + * + * Test Dump facility. Ensure it can be configured and files contain expected contents. Testcase + * returns Dump configuration to orginal state. + */ +public class DumpTestCase extends TestCase { + + private File dumpFile; + private IMessage.Kind savedDumpCondition; + + public DumpTestCase(String name) { + super(name); + } + + protected void setUp() throws Exception { + super.setUp(); + + dumpFile = null; + savedDumpCondition = Dump.getDumpOnExit(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + + if (dumpFile != null && dumpFile.exists()) { + boolean deleted = dumpFile.delete(); + assertTrue("Dump file '" + dumpFile.getPath() + "' could not be deleted",deleted); + } + Dump.setDumpOnExit(savedDumpCondition); + } + + public void testSetDumpOnException () { + Dump.setDumpOnException(true); + assertTrue("DumpOnException should be true",Dump.getDumpOnException()); + } + + public void testSetDumpOnExit () { + assertTrue("Should be able to set condition 'error'",Dump.setDumpOnExit("error")); + assertTrue("Should be able to set condition 'warning'",Dump.setDumpOnExit("warning")); + assertFalse("Should not be able to set condition 'junk'",Dump.setDumpOnExit("junk")); + } + + public void testDump () { + String fileName = Dump.dump("testDump()"); + dumpFile = new File(fileName); + assertTrue("Dump file '" + fileName + "' should exist",dumpFile.exists()); + } + + public void testDumpWithException () { + String message = "testDumpWithException()"; + String fileName = recursiveCall(message,100); + dumpFile = new File(fileName); + assertContents(dumpFile,"Exception Information",message); + } + + public void testDumpOnExit () { + Dump.setDumpOnExit("abort"); + Dump.saveMessageHolder(null); + String fileName = Dump.dumpOnExit(); + dumpFile = new File(fileName); + assertTrue("Dump file '" + fileName + "' should exist",dumpFile.exists()); + } + + public void testDumpOnExitExcluded () { + Dump.setDumpOnExit("abort"); + IMessageHolder holder = new MessageHandler(); + Dump.saveMessageHolder(holder); + holder.handleMessage(new Message("testDumpOnExitExcluded()",IMessage.ERROR,null,null)); + String fileName = Dump.dumpOnExit(); + dumpFile = new File(fileName); + assertEquals("Dump '" + fileName + "' should be excluded",Dump.DUMP_EXCLUDED,fileName); + } + + public void testDumpOnExitIncluded () { + Dump.setDumpOnExit("error"); + IMessageHolder holder = new MessageHandler(); + Dump.saveMessageHolder(holder); + IMessage error = new Message("testDumpOnExitIncluded()",IMessage.ERROR,null,null); + holder.handleMessage(error); + String fileName = Dump.dumpOnExit(); + dumpFile = new File(fileName); + assertContents(dumpFile,"Compiler Messages",error.getMessage()); + } + + /* Ensure dump file exists and contains certain contents under a given heading */ + public static void assertContents (File dumpFile, String heading, String contents) { + assertTrue("Dump file '" + dumpFile.getPath() + "' should exist",dumpFile.exists()); + assertTrue("Dump file '" + dumpFile.getPath()+ "' should contain '" + contents + "'",fileContains(dumpFile,heading,contents)); + } + + private static boolean fileContains (File dumpFile, String heading, String contents) { + boolean result = false; + + try { + BufferedReader reader = new BufferedReader(new FileReader(dumpFile)); + String currentHeading = ""; + String record; + while ((null != (record = reader.readLine())) && (result == false)) { + if (record.startsWith("----")) currentHeading = record; + else if ((record.indexOf(contents) != -1) && currentHeading.indexOf(heading) != -1) result = true; + } + reader.close(); + } + catch (IOException ex) { + fail(ex.toString()); + } + + return result; + } + + /* Generate a big stack trace */ + private String recursiveCall (String message, int depth) { + if (depth == 0) { + Throwable th = new RuntimeException(message); + return Dump.dumpWithException(th); + } + else { + return recursiveCall(message,--depth); + } + } + +} |