You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CFlowStack.java 5.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* *******************************************************************
  2. * Copyright (c) 1999-2001 Xerox Corporation,
  3. * 2002 Palo Alto Research Center, Incorporated (PARC).
  4. * All rights reserved.
  5. * This program and the accompanying materials are made available
  6. * under the terms of the Eclipse Public License v 2.0
  7. * which accompanies this distribution and is available at
  8. * https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.txt
  9. *
  10. * Contributors:
  11. * Xerox/PARC initial implementation
  12. * ******************************************************************/
  13. package org.aspectj.runtime.internal;
  14. import java.util.Stack;
  15. import org.aspectj.lang.NoAspectBoundException;
  16. import org.aspectj.runtime.CFlow;
  17. import org.aspectj.runtime.internal.cflowstack.ThreadStack;
  18. import org.aspectj.runtime.internal.cflowstack.ThreadStackFactory;
  19. import org.aspectj.runtime.internal.cflowstack.ThreadStackFactoryImpl;
  20. import org.aspectj.runtime.internal.cflowstack.ThreadStackFactoryImpl11;
  21. /*
  22. * How we benefit from ThreadLocal when it is available at runtime:
  23. *
  24. * When the CFlowStack class is loaded, we run its static initializer. This checks the JVM
  25. * version number and loads an appropriate implementation of the ThreadStackFactory.
  26. * There are two possible implementations depending on whether this is a 1.1 or 1.2+ JVM.
  27. * Rather than doing a Class.forName for ThreadLocal and catching a ClassNotFoundEx in order
  28. * to determine the JVM version, we look at the java class version which I believe can help
  29. * us identify the Java level.
  30. *
  31. * In the 1.1 JVM case we use a factory implementation that does not use ThreadLocal storage.
  32. * In the 1.2+ JVM case we use a factory implementation that does use ThreadLocal storage.
  33. *
  34. * Once we have the factory set, whenever someone builds a CFlowStack object, we ask the
  35. * factory for a new stack proxy - this is an object that can return us the right stack
  36. * that we should use on a particular thread. The reason we create the proxy in the ctor and
  37. * not lazily in the getThreadStack() method is because it means the getThreadStack() method in
  38. * this class does not have to be synchronized.
  39. *
  40. * When any of the methods in CFlowStack need to operate on the stack (peek/pop/etc), they
  41. * all delegate to getThreadStack() which asks the proxy for the right stack. Depending on the
  42. * factory loaded to build the proxy, the call to proxy.getThreadStack() will return a threadlocal
  43. * based stack or it will call the original implementation of getThreadStack() which manages
  44. * a Hashtable of threads->stacks.
  45. *
  46. */
  47. public class CFlowStack {
  48. private static ThreadStackFactory tsFactory;
  49. private ThreadStack stackProxy;
  50. static {
  51. selectFactoryForVMVersion();
  52. }
  53. public CFlowStack() {
  54. stackProxy = tsFactory.getNewThreadStack();
  55. }
  56. private Stack getThreadStack() {
  57. return stackProxy.getThreadStack();
  58. }
  59. //XXX dangerous, try to remove
  60. public void push(Object obj) {
  61. getThreadStack().push(obj);
  62. }
  63. public void pushInstance(Object obj) {
  64. getThreadStack().push(new CFlow(obj));
  65. }
  66. public void push(Object[] obj) {
  67. getThreadStack().push(new CFlowPlusState(obj));
  68. }
  69. public void pop() {
  70. Stack<?> s = getThreadStack();
  71. s.pop();
  72. if (s.isEmpty()) {
  73. stackProxy.removeThreadStack();
  74. }
  75. }
  76. public Object peek() {
  77. Stack<?> stack = getThreadStack();
  78. if (stack.isEmpty()) throw new org.aspectj.lang.NoAspectBoundException();
  79. return stack.peek();
  80. }
  81. public Object get(int index) {
  82. CFlow cf = peekCFlow();
  83. return (null == cf ? null : cf.get(index));
  84. }
  85. public Object peekInstance() {
  86. CFlow cf = peekCFlow();
  87. if (cf != null ) return cf.getAspect();
  88. else throw new NoAspectBoundException();
  89. }
  90. public CFlow peekCFlow() {
  91. Stack<?> stack = getThreadStack();
  92. if (stack.isEmpty()) return null;
  93. return (CFlow)stack.peek();
  94. }
  95. public CFlow peekTopCFlow() {
  96. Stack<?> stack = getThreadStack();
  97. if (stack.isEmpty()) return null;
  98. return (CFlow)stack.elementAt(0);
  99. }
  100. public boolean isValid() {
  101. return !getThreadStack().isEmpty();
  102. }
  103. private static ThreadStackFactory getThreadLocalStackFactory() { return new ThreadStackFactoryImpl(); }
  104. private static ThreadStackFactory getThreadLocalStackFactoryFor11() { return new ThreadStackFactoryImpl11(); }
  105. private static void selectFactoryForVMVersion() {
  106. String override = getSystemPropertyWithoutSecurityException("aspectj.runtime.cflowstack.usethreadlocal","unspecified");
  107. boolean useThreadLocalImplementation = false;
  108. if (override.equals("unspecified")) {
  109. String v = System.getProperty("java.class.version","0.0");
  110. // Java 1.2 is version 46.0 and above
  111. useThreadLocalImplementation = (v.compareTo("46.0") >= 0);
  112. } else {
  113. useThreadLocalImplementation = override.equals("yes") || override.equals("true");
  114. }
  115. // System.err.println("Trying to use thread local implementation? "+useThreadLocalImplementation);
  116. if (useThreadLocalImplementation) {
  117. tsFactory = getThreadLocalStackFactory();
  118. } else {
  119. tsFactory = getThreadLocalStackFactoryFor11();
  120. }
  121. }
  122. private static String getSystemPropertyWithoutSecurityException (String aPropertyName, String aDefaultValue) {
  123. try {
  124. return System.getProperty(aPropertyName, aDefaultValue);
  125. }
  126. catch (SecurityException ex) {
  127. return aDefaultValue;
  128. }
  129. }
  130. // For debug ...
  131. public static String getThreadStackFactoryClassName() {
  132. return tsFactory.getClass().getName();
  133. }
  134. }