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

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