123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160 |
- /* *******************************************************************
- * 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 Eclipse Public License v 2.0
- * which accompanies this distribution and is available at
- * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
- *
- * Contributors:
- * Xerox/PARC initial implementation
- * ******************************************************************/
-
-
- package org.aspectj.runtime.internal;
-
- import java.util.Stack;
-
- import org.aspectj.lang.NoAspectBoundException;
- import org.aspectj.runtime.CFlow;
- import org.aspectj.runtime.internal.cflowstack.ThreadStack;
- import org.aspectj.runtime.internal.cflowstack.ThreadStackFactory;
- import org.aspectj.runtime.internal.cflowstack.ThreadStackFactoryImpl;
- import org.aspectj.runtime.internal.cflowstack.ThreadStackFactoryImpl11;
-
- /*
- * How we benefit from ThreadLocal when it is available at runtime:
- *
- * When the CFlowStack class is loaded, we run its static initializer. This checks the JVM
- * version number and loads an appropriate implementation of the ThreadStackFactory.
- * There are two possible implementations depending on whether this is a 1.1 or 1.2+ JVM.
- * Rather than doing a Class.forName for ThreadLocal and catching a ClassNotFoundEx in order
- * to determine the JVM version, we look at the java class version which I believe can help
- * us identify the Java level.
- *
- * In the 1.1 JVM case we use a factory implementation that does not use ThreadLocal storage.
- * In the 1.2+ JVM case we use a factory implementation that does use ThreadLocal storage.
- *
- * Once we have the factory set, whenever someone builds a CFlowStack object, we ask the
- * factory for a new stack proxy - this is an object that can return us the right stack
- * that we should use on a particular thread. The reason we create the proxy in the ctor and
- * not lazily in the getThreadStack() method is because it means the getThreadStack() method in
- * this class does not have to be synchronized.
- *
- * When any of the methods in CFlowStack need to operate on the stack (peek/pop/etc), they
- * all delegate to getThreadStack() which asks the proxy for the right stack. Depending on the
- * factory loaded to build the proxy, the call to proxy.getThreadStack() will return a threadlocal
- * based stack or it will call the original implementation of getThreadStack() which manages
- * a Hashtable of threads->stacks.
- *
- */
-
- public class CFlowStack {
-
- private static ThreadStackFactory tsFactory;
- private ThreadStack stackProxy;
-
- static {
- selectFactoryForVMVersion();
- }
-
- public CFlowStack() {
- stackProxy = tsFactory.getNewThreadStack();
- }
-
- private Stack getThreadStack() {
- return stackProxy.getThreadStack();
- }
-
- //XXX dangerous, try to remove
- public void push(Object obj) {
- getThreadStack().push(obj);
- }
-
- public void pushInstance(Object obj) {
- getThreadStack().push(new CFlow(obj));
- }
-
- public void push(Object[] obj) {
- getThreadStack().push(new CFlowPlusState(obj));
- }
-
- public void pop() {
- Stack<?> s = getThreadStack();
- s.pop();
- if (s.isEmpty()) {
- stackProxy.removeThreadStack();
- }
- }
-
- public Object peek() {
- Stack<?> stack = getThreadStack();
- if (stack.isEmpty()) throw new org.aspectj.lang.NoAspectBoundException();
- return stack.peek();
- }
-
- public Object get(int index) {
- CFlow cf = peekCFlow();
- return (null == cf ? null : cf.get(index));
- }
-
- public Object peekInstance() {
- CFlow cf = peekCFlow();
- if (cf != null ) return cf.getAspect();
- else throw new NoAspectBoundException();
- }
-
- public CFlow peekCFlow() {
- Stack<?> stack = getThreadStack();
- if (stack.isEmpty()) return null;
- return (CFlow)stack.peek();
- }
-
- public CFlow peekTopCFlow() {
- Stack<?> stack = getThreadStack();
- if (stack.isEmpty()) return null;
- return (CFlow)stack.elementAt(0);
- }
-
- public boolean isValid() {
- return !getThreadStack().isEmpty();
- }
-
- private static ThreadStackFactory getThreadLocalStackFactory() { return new ThreadStackFactoryImpl(); }
- private static ThreadStackFactory getThreadLocalStackFactoryFor11() { return new ThreadStackFactoryImpl11(); }
-
- private static void selectFactoryForVMVersion() {
- String override = getSystemPropertyWithoutSecurityException("aspectj.runtime.cflowstack.usethreadlocal","unspecified");
- boolean useThreadLocalImplementation = false;
- if (override.equals("unspecified")) {
- String v = System.getProperty("java.class.version","0.0");
- // Java 1.2 is version 46.0 and above
- useThreadLocalImplementation = (v.compareTo("46.0") >= 0);
- } else {
- useThreadLocalImplementation = override.equals("yes") || override.equals("true");
- }
- // System.err.println("Trying to use thread local implementation? "+useThreadLocalImplementation);
- if (useThreadLocalImplementation) {
- tsFactory = getThreadLocalStackFactory();
- } else {
- tsFactory = getThreadLocalStackFactoryFor11();
- }
- }
-
- private static String getSystemPropertyWithoutSecurityException (String aPropertyName, String aDefaultValue) {
- try {
- return System.getProperty(aPropertyName, aDefaultValue);
- }
- catch (SecurityException ex) {
- return aDefaultValue;
- }
- }
-
-
- // For debug ...
- public static String getThreadStackFactoryClassName() {
- return tsFactory.getClass().getName();
- }
-
- }
|