123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- /* *******************************************************************
- * Copyright (c) 2005 Contributors.
- * All rights reserved.
- * This program and the accompanying materials are made available
- * under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution and is available at
- * http://eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * Adrian Colyer Initial implementation
- * ******************************************************************/
- package org.aspectj.bridge.context;
-
- import java.lang.ref.WeakReference;
- import java.util.HashMap;
- import java.util.Iterator;
- import java.util.Map;
- import java.util.Stack;
-
- /**
- * @author colyer
- * This class is responsible for tracking progress through the various phases of
- * compilation and weaving. When an exception occurs (or a message is issued, if
- * desired), you can ask this class for a "stack trace" that gives information about
- * what the compiler was doing at the time. The trace will say something like:
- *
- * when matching pointcut xyz
- * when matching shadow sss
- * when weaving type ABC
- * when weaving shadow mungers
- *
- * Since we can't use ThreadLocal (have to work on 1.3), we use a
- * map from Thread -> ContextStack.
- */
- public class CompilationAndWeavingContext {
-
- private static int nextTokenId = 1;
-
- // unique constants for the different phases that can be registered
-
- // "FRONT END"
- public static final int BATCH_BUILD = 0;
- public static final int INCREMENTAL_BUILD = 1;
- public static final int PROCESSING_COMPILATION_UNIT = 2;
- public static final int RESOLVING_COMPILATION_UNIT = 3;
- public static final int ANALYSING_COMPILATION_UNIT = 4;
- public static final int GENERATING_UNWOVEN_CODE_FOR_COMPILATION_UNIT = 5;
- public static final int COMPLETING_TYPE_BINDINGS = 6;
- public static final int PROCESSING_DECLARE_PARENTS = 7;
- public static final int CHECK_AND_SET_IMPORTS = 8;
- public static final int CONNECTING_TYPE_HIERARCHY = 9;
- public static final int BUILDING_FIELDS_AND_METHODS = 10;
- public static final int COLLECTING_ITDS_AND_DECLARES = 11;
- public static final int PROCESSING_DECLARE_ANNOTATIONS = 12;
- public static final int WEAVING_INTERTYPE_DECLARATIONS = 13;
- public static final int RESOLVING_POINTCUT_DECLARATIONS = 14;
- public static final int ADDING_DECLARE_WARNINGS_AND_ERRORS = 15;
- public static final int VALIDATING_AT_ASPECTJ_ANNOTATIONS = 16;
- public static final int ACCESS_FOR_INLINE = 17;
- public static final int ADDING_AT_ASPECTJ_ANNOTATIONS = 18;
- public static final int FIXING_SUPER_CALLS_IN_ITDS = 19;
- public static final int FIXING_SUPER_CALLS = 20;
- public static final int OPTIMIZING_THIS_JOIN_POINT_CALLS = 21;
-
- // "BACK END"
-
- public static final int WEAVING = 22;
- public static final int PROCESSING_REWEAVABLE_STATE = 23;
- public static final int PROCESSING_TYPE_MUNGERS = 24;
- public static final int WEAVING_ASPECTS = 25;
- public static final int WEAVING_CLASSES = 26;
- public static final int WEAVING_TYPE = 27;
- public static final int MATCHING_SHADOW = 28;
- public static final int IMPLEMENTING_ON_SHADOW = 29;
- public static final int MATCHING_POINTCUT = 30;
- public static final int MUNGING_WITH = 31;
- public static final int PROCESSING_ATASPECTJTYPE_MUNGERS_ONLY = 32;
-
-
- // phase names
- public static final String[] PHASE_NAMES = new String[] {
- "batch building",
- "incrementally building",
- "processing compilation unit",
- "resolving types defined in compilation unit",
- "analysing types defined in compilation unit",
- "generating unwoven code for type defined in compilation unit",
- "completing type bindings",
- "processing declare parents",
- "checking and setting imports",
- "connecting type hierarchy",
- "building fields and methods",
- "collecting itds and declares",
- "processing declare annotations",
- "weaving intertype declarations",
- "resolving pointcut declarations",
- "adding declare warning and errors",
- "validating @AspectJ annotations",
- "creating accessors for inlining",
- "adding @AspectJ annotations",
- "fixing super calls in ITDs in interface context",
- "fixing super calls in ITDs",
- "optimizing thisJoinPoint calls",
-
- // BACK END
-
- "weaving",
- "processing reweavable state",
- "processing type mungers",
- "weaving aspects",
- "weaving classes",
- "weaving type",
- "matching shadow",
- "implementing on shadow",
- "matching pointcut",
- "type munging with",
- "type munging for @AspectJ aspectOf"
- };
-
- // context stacks, one per thread
- private static Map contextMap = new HashMap();
-
- // single thread mode stack
- private static Stack contextStack = new Stack();
-
- // formatters, by phase id
- private static Map formatterMap = new HashMap();
-
- private static ContextFormatter defaultFormatter = new DefaultFormatter();
-
- private static boolean multiThreaded = true;
-
- /**
- * this is a static service
- */
- private CompilationAndWeavingContext() {
- }
-
- // for testing...
- public static void reset() {
- contextMap = new HashMap();
- contextStack = new Stack();
- formatterMap = new HashMap();
- nextTokenId = 1;
- }
-
- public static void setMultiThreaded(boolean mt) { multiThreaded = mt; }
-
- public static void registerFormatter(int phaseId, ContextFormatter aFormatter) {
- formatterMap.put(new Integer(phaseId),aFormatter);
- }
-
- /**
- * Returns a string description of what the compiler/weaver is currently doing
- */
- public static String getCurrentContext() {
- Stack contextStack = getContextStack();
- Stack explanationStack = new Stack();
- for (Iterator iter = contextStack.iterator(); iter.hasNext();) {
- ContextStackEntry entry = (ContextStackEntry) iter.next();
- Object data = entry.getData();
- if (data != null) {
- explanationStack.push(getFormatter(entry).formatEntry(entry.phaseId,data));
- }
- }
- StringBuffer sb = new StringBuffer();
- while (!explanationStack.isEmpty()) {
- sb.append("when ");
- sb.append(explanationStack.pop().toString());
- sb.append("\n");
- }
- return sb.toString();
- }
-
- public static ContextToken enteringPhase(int phaseId, Object data) {
- Stack contextStack = getContextStack();
- ContextTokenImpl nextToken = nextToken();
- contextStack.push(new ContextStackEntry(nextToken,phaseId,new WeakReference(data)));
- return nextToken;
- }
-
- /**
- * Exit a phase, all stack entries from the one with the given token
- * down will be removed.
- */
- public static void leavingPhase(ContextToken aToken) {
- Stack contextStack = getContextStack();
- while (!contextStack.isEmpty()) {
- ContextStackEntry entry = (ContextStackEntry) contextStack.pop();
- if (entry.contextToken == aToken) break;
- }
- }
-
- private static Stack getContextStack() {
- if (!multiThreaded) {
- return contextStack;
- }
- else {
- if (contextMap.containsKey(Thread.currentThread())) {
- return (Stack) contextMap.get(Thread.currentThread());
- } else {
- Stack contextStack = new Stack();
- contextMap.put(Thread.currentThread(),contextStack);
- return contextStack;
- }
- }
- }
-
- private static ContextTokenImpl nextToken() {
- return new ContextTokenImpl(nextTokenId++);
- }
-
- private static ContextFormatter getFormatter(ContextStackEntry entry) {
- Integer key = new Integer(entry.phaseId);
- if (formatterMap.containsKey(key)) {
- return (ContextFormatter) formatterMap.get(key);
- } else {
- return defaultFormatter;
- }
- }
-
- private static class ContextTokenImpl implements ContextToken {
- public int tokenId;
- public ContextTokenImpl(int id) { this.tokenId = id; }
- }
-
- // dumb data structure
- private static class ContextStackEntry {
- public ContextTokenImpl contextToken;
- public int phaseId;
- private WeakReference dataRef;
- public ContextStackEntry(ContextTokenImpl ct, int phase, WeakReference data) {
- this.contextToken = ct;
- this.phaseId = phase;
- this.dataRef = data;
- }
-
- public Object getData() {
- return dataRef.get();
- }
-
- public String toString() {
- Object data = getData();
- if (data == null) {
- return "referenced context entry has gone out of scope";
- } else {
- return CompilationAndWeavingContext.getFormatter(this).formatEntry(phaseId, data);
- }
- }
- }
-
- private static class DefaultFormatter implements ContextFormatter {
-
- public String formatEntry(int phaseId, Object data) {
- StringBuffer sb = new StringBuffer();
- sb.append(PHASE_NAMES[phaseId]);
- sb.append(" ");
- if (data instanceof char[]) {
- sb.append(new String((char[])data));
- } else {
- try {
- sb.append(data.toString());
- } catch (RuntimeException ex) {
- // don't lose vital info because of bad toString
- sb.append("** broken toString in data object **");
- }
- }
- return sb.toString();
- }
-
- }
- }
|