Package org.aspectj.runtime.internal

Source Code of org.aspectj.runtime.internal.CFlowStack

/* *******************************************************************
* 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 v1.0
* which accompanies this distribution and is available at
* http://www.eclipse.org/legal/epl-v10.html
* 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 (Object)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();
  }

}
TOP

Related Classes of org.aspectj.runtime.internal.CFlowStack

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.