1. /*
  2. * Copyright 2002-2004 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.springframework.core;
  17. import java.io.PrintWriter;
  18. import java.io.StringWriter;
  19. /**
  20. * Singleton factory to conceal automatic choice of Java 1.4 or 1.3
  21. * ControlFlow implementation class. We want to use the more efficient
  22. * Java 1.4 StackTraceElement if we can, and we don't want to impose
  23. * a runtime dependency on 1.4.
  24. * @author Rod Johnson
  25. * @version $Id: ControlFlowFactory.java,v 1.2 2004/03/18 02:46:06 trisberg Exp $
  26. */
  27. public abstract class ControlFlowFactory {
  28. public static ControlFlow createControlFlow() {
  29. return JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_14 ?
  30. (ControlFlow) new Jdk14ControlFlow() :
  31. (ControlFlow) new Jdk13ControlFlow();
  32. }
  33. /**
  34. * Utilities for cflow-style pointcuts. Note that such pointcuts are
  35. * 5-10 times more expensive to evaluate than other pointcuts, as they require
  36. * analysis of the stack trace (through constructing a new throwable).
  37. * However, they are useful in some cases.
  38. * <p>This implementation uses the StackTraceElement class introduced in Java 1.4.
  39. * @author Rod Johnson
  40. * @version $Id: ControlFlowFactory.java,v 1.2 2004/03/18 02:46:06 trisberg Exp $
  41. */
  42. static class Jdk14ControlFlow implements ControlFlow {
  43. private StackTraceElement[] stack;
  44. public Jdk14ControlFlow() {
  45. stack = new Throwable().getStackTrace();
  46. }
  47. public boolean under(Class clazz) {
  48. String className = clazz.getName();
  49. for (int i = 0; i < stack.length; i++) {
  50. //System.out.println(stack[i]);
  51. if (stack[i].getClassName().equals(className)) {
  52. return true;
  53. }
  54. }
  55. return false;
  56. }
  57. /**
  58. * Matches whole method name
  59. * @param clazz
  60. * @param methodName
  61. * @return
  62. */
  63. public boolean under(Class clazz, String methodName) {
  64. String className = clazz.getName();
  65. for (int i = 0; i < stack.length; i++) {
  66. if (stack[i].getClassName().equals(className) && stack[i].getMethodName().equals(methodName)) {
  67. return true;
  68. }
  69. }
  70. return false;
  71. }
  72. /**
  73. * Leave it up to the caller to decide what matches.
  74. * Caller must understand stack trace format, so there's less abstraction.
  75. * @param token
  76. * @return
  77. */
  78. public boolean underToken(String token) {
  79. StringWriter sw = new StringWriter();
  80. new Throwable().printStackTrace(new PrintWriter(sw));
  81. //System.err.println(sw);
  82. String stackTrace = sw.toString();
  83. return stackTrace.indexOf(token) != -1;
  84. }
  85. public String toString() {
  86. StringBuffer sb = new StringBuffer("Jdk14ControlFlow: ");
  87. for (int i = 0; i < stack.length; i++) {
  88. if (i > 0)
  89. sb.append("\n\t@");
  90. sb.append(stack[i]);
  91. }
  92. return sb.toString();
  93. }
  94. }
  95. /**
  96. * Java 1.3 version of utilities for cflow-style pointcuts. We can't
  97. * rely on the Java 1.4 StackTraceElement class.
  98. * <p>Note that such pointcuts are 10-15 times more expensive to evaluate under
  99. * JDK 1.3 than other pointcuts, as they require analysis of the stack trace
  100. * (through constructing a new throwable). However, they are useful in some cases.
  101. * @author Rod Johnson
  102. * @version $Id: ControlFlowFactory.java,v 1.2 2004/03/18 02:46:06 trisberg Exp $
  103. */
  104. static class Jdk13ControlFlow implements ControlFlow {
  105. private String stackTrace;
  106. public Jdk13ControlFlow() {
  107. StringWriter sw = new StringWriter();
  108. new Throwable().printStackTrace(new PrintWriter(sw));
  109. stackTrace = sw.toString();
  110. }
  111. public boolean under(Class clazz) {
  112. return stackTrace.indexOf(clazz.getName()) != -1;
  113. }
  114. /**
  115. * Matches whole method name
  116. * @param clazz
  117. * @param methodName
  118. * @return
  119. */
  120. public boolean under(Class clazz, String methodName) {
  121. return stackTrace.indexOf(clazz.getName() + "." + methodName + "(") != -1;
  122. }
  123. /**
  124. * Leave it up to the caller to decide what matches.
  125. * Caller must understand stack trace format, so there's less abstraction.
  126. * @param token
  127. * @return
  128. */
  129. public boolean underToken(String token) {
  130. return stackTrace.indexOf(token) != -1;
  131. }
  132. }
  133. }