001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package org.terracotta.dso;
005:
006: import org.apache.commons.lang.StringUtils;
007: import org.eclipse.jdt.core.Flags;
008: import org.eclipse.jdt.core.ICompilationUnit;
009: import org.eclipse.jdt.core.IField;
010: import org.eclipse.jdt.core.IJavaElement;
011: import org.eclipse.jdt.core.IMethod;
012: import org.eclipse.jdt.core.IPackageDeclaration;
013: import org.eclipse.jdt.core.IPackageFragment;
014: import org.eclipse.jdt.core.IType;
015: import org.eclipse.jdt.core.JavaModelException;
016: import org.eclipse.jdt.core.Signature;
017: import org.eclipse.jdt.core.dom.IMethodBinding;
018: import org.eclipse.jdt.core.dom.MethodDeclaration;
019:
020: import com.tc.aspectwerkz.expression.ExpressionContext;
021: import com.tc.aspectwerkz.expression.ExpressionVisitor;
022: import com.tc.aspectwerkz.expression.PointcutType;
023: import com.tc.aspectwerkz.reflect.ClassInfo;
024: import com.tc.aspectwerkz.reflect.FieldInfo;
025: import com.tc.aspectwerkz.reflect.MemberInfo;
026: import com.tc.aspectwerkz.reflect.MethodInfo;
027: import com.tc.object.bytecode.aspectwerkz.ExpressionHelper;
028: import com.terracottatech.config.Root;
029:
030: import java.util.HashMap;
031:
032: /**
033: * Utility singleton for bridging the gap between Eclipse internal
034: * Java parser constructs (MethodDeclaration) and Aspectwerks expressions.
035: */
036:
037: public class PatternHelper {
038: private static PatternHelper m_helper = new PatternHelper();
039: private ExpressionHelper m_expressionHelper;
040: private ClassInfoFactory m_classInfoFactory;
041: private HashMap m_expressionContextCache;
042: private HashMap m_executionExpressionContextCache;
043:
044: public static final PatternHelper getHelper() {
045: return m_helper;
046: }
047:
048: private PatternHelper() {
049: m_expressionHelper = new ExpressionHelper();
050: m_classInfoFactory = new ClassInfoFactory();
051: m_expressionContextCache = new HashMap();
052: m_executionExpressionContextCache = new HashMap();
053: }
054:
055: // public boolean matchesFieldName(Root root, String fieldName) {
056: // if(root.isSetFieldName()) {
057: // return root.getFieldName().equals(fieldName);
058: // } else {
059: // String fieldExpr = root.getFieldExpression();
060: // ExpressionVisitor visitor = m_expressionHelper.createExpressionVisitor("get(" + fieldExpr + ")");
061: // return visitor.match(new ExpressionContext(PointcutType.GET, fi, fi));
062: // }
063: // }
064:
065: public boolean matchesField(Root root, IField field) {
066: if (root.isSetFieldName()) {
067: return root.getFieldName().equals(
068: ConfigurationHelper.getFullName(field));
069: } else {
070: FieldInfo fi = getFieldInfo(field);
071: String fieldExpr = root.getFieldExpression();
072: ExpressionVisitor visitor = m_expressionHelper
073: .createExpressionVisitor("get(" + fieldExpr + ")");
074: return visitor.match(new ExpressionContext(
075: PointcutType.GET, fi, fi));
076: }
077: }
078:
079: public boolean matchesMethod(String expression, final IMethod method) {
080: MethodInfo methodInfo = method != null ? getMethodInfo(method)
081: : null;
082:
083: int parentIndex = expression.indexOf('(');
084: if (parentIndex > 0) {
085: String tmp = expression.substring(parentIndex);
086: tmp = StringUtils.replaceChars(tmp, '$', '.');
087: expression = expression.substring(0, parentIndex) + tmp;
088: }
089:
090: return methodInfo != null
091: && matchesMember(expression, methodInfo);
092: }
093:
094: public boolean matchesMethod(final String expression,
095: final MethodDeclaration methodDecl) {
096: return matchesMember(expression, getMethodInfo(methodDecl));
097: }
098:
099: public ExpressionContext createExecutionExpressionContext(
100: final IMethod method) {
101: return createExecutionExpressionContext(getMethodInfo(method));
102: }
103:
104: public ExpressionContext createExecutionExpressionContext(
105: final MemberInfo methodInfo) {
106: ExpressionContext exprCntx = (ExpressionContext) m_executionExpressionContextCache
107: .get(methodInfo);
108: if (exprCntx == null) {
109: exprCntx = m_expressionHelper
110: .createExecutionExpressionContext(methodInfo);
111: m_executionExpressionContextCache.put(methodInfo, exprCntx);
112: }
113: return exprCntx;
114: }
115:
116: public void testValidateMethodExpression(final String expr)
117: throws Exception {
118: String execExpr = ExpressionHelper
119: .expressionPattern2ExecutionExpression(expr);
120: m_expressionHelper.createExpressionVisitor(execExpr);
121: }
122:
123: public boolean matchesMethod(final String expr,
124: final ExpressionContext exprCntx) {
125: try {
126: String execExpr = ExpressionHelper
127: .expressionPattern2ExecutionExpression(expr);
128: ExpressionVisitor visitor = m_expressionHelper
129: .createExpressionVisitor(execExpr);
130:
131: return visitor.match(exprCntx);
132: } catch (Exception e) {
133: return false;
134: }
135: }
136:
137: public boolean matchesMember(String expr,
138: final MemberInfo methodInfo) {
139: int parentIndex = expr.indexOf('(');
140: if (parentIndex > 0) {
141: String tmp = expr.substring(parentIndex);
142: tmp = StringUtils.replaceChars(tmp, '$', '.');
143: expr = expr.substring(0, parentIndex) + tmp;
144: }
145:
146: return matchesMethod(expr,
147: createExecutionExpressionContext(methodInfo));
148: }
149:
150: public static String getFullyQualifiedName(IType type) {
151: return type.getFullyQualifiedName('$');
152: }
153:
154: public ExpressionContext createWithinExpressionContext(
155: final IType type) {
156: return createWithinExpressionContext(m_classInfoFactory
157: .getClassInfo(type));
158: }
159:
160: public ExpressionContext createWithinExpressionContext(
161: final IPackageDeclaration packageDecl) {
162: return createWithinExpressionContext(packageDecl
163: .getElementName());
164: }
165:
166: public ExpressionContext createWithinExpressionContext(
167: final IPackageFragment fragment) {
168: return createWithinExpressionContext(fragment.getElementName());
169: }
170:
171: public ExpressionContext createWithinExpressionContext(
172: final String className) {
173: return createWithinExpressionContext(m_classInfoFactory
174: .getClassInfo(className));
175: }
176:
177: public ExpressionContext createWithinExpressionContext(
178: final ClassInfo classInfo) {
179: ExpressionContext exprCntx = (ExpressionContext) m_expressionContextCache
180: .get(classInfo);
181: if (exprCntx == null) {
182: exprCntx = m_expressionHelper
183: .createWithinExpressionContext(classInfo);
184: m_expressionContextCache.put(classInfo, exprCntx);
185: }
186: return exprCntx;
187: }
188:
189: public boolean matchesClass(final String expr,
190: final ExpressionContext exprCntx) {
191: try {
192: String withinExpr = ExpressionHelper
193: .expressionPattern2WithinExpression(expr);
194: ExpressionVisitor visitor = m_expressionHelper
195: .createExpressionVisitor(withinExpr);
196:
197: return visitor.match(exprCntx);
198: } catch (Exception e) {
199: return false;
200: }
201: }
202:
203: public JavaModelClassInfo getClassInfo(IType type) {
204: return (JavaModelClassInfo) m_classInfoFactory
205: .getClassInfo(type);
206: }
207:
208: public boolean matchesClass(final String expression,
209: final String className) {
210: if (expression != null && expression.equals(className))
211: return true;
212: return matchesClass(expression, m_classInfoFactory
213: .getClassInfo(className));
214: }
215:
216: public boolean matchesClass(final String expr,
217: final ClassInfo classInfo) {
218: return matchesClass(expr,
219: createWithinExpressionContext(classInfo));
220: }
221:
222: public boolean matchesType(final String expr, final IType type) {
223: return matchesClass(expr, createWithinExpressionContext(type));
224: }
225:
226: public boolean matchesPackageFragment(final String expr,
227: final IPackageFragment fragment) {
228: return matchesClass(expr,
229: createWithinExpressionContext(fragment));
230: }
231:
232: public boolean matchesPackageDeclaration(final String expr,
233: final IPackageDeclaration packageDecl) {
234: return matchesClass(expr,
235: createWithinExpressionContext(packageDecl));
236: }
237:
238: public static String getSignature(IMethod method)
239: throws JavaModelException {
240: IType dType = method.getDeclaringType();
241: String[] pTypes = method.getParameterTypes().clone();
242: String rType = method.getReturnType();
243: StringBuffer sb = new StringBuffer("(");
244:
245: rType = Signature.getTypeErasure(rType);
246:
247: for (int i = 0; i < pTypes.length; i++) {
248: String erasedSig = Signature.getTypeErasure(pTypes[i]);
249: if (erasedSig.charAt(0) == 'T') {
250: erasedSig = "Ljava.lang.Object;";
251: } else if (erasedSig.charAt(0) == '['
252: && erasedSig.charAt(1) == 'T') {
253: erasedSig = "[Ljava.lang.Object;";
254: }
255: JdtUtils.resolveTypeName(erasedSig, dType, sb);
256: }
257: sb.append(')');
258: if (rType.charAt(0) == 'T') {
259: rType = "Ljava.lang.Object;";
260: } else if (rType.charAt(0) == '[' && rType.charAt(1) == 'T') {
261: rType = "[Ljava.lang.Object;";
262: }
263: JdtUtils.resolveTypeName(rType, dType, sb);
264:
265: String result = sb.toString().replace('.', '/');
266:
267: return result;
268: }
269:
270: public static String getFullName(IMethod method) {
271: IType declaringType = method.getDeclaringType();
272: return getFullyQualifiedName(declaringType) + "."
273: + method.getElementName();
274: }
275:
276: public static boolean isVarargs(IMethod method) {
277: try {
278: return Flags.isVarargs(method.getFlags());
279: } catch (JavaModelException jme) {
280: return false;
281: }
282: }
283:
284: /**
285: * Returns a full method signature, compatible with the forms required
286: * by the DSO config format.
287: */
288: public static String getJavadocSignature(IMethod method)
289: throws JavaModelException {
290: StringBuffer sb = new StringBuffer();
291: IType declaringType = method.getDeclaringType();
292: boolean isVararg = isVarargs(method);
293: String[] params = method.getParameterTypes().clone();
294: int lastParam = params.length - 1;
295: int dim;
296:
297: try {
298: String returnType = method.getReturnType();
299:
300: dim = Signature.getArrayCount(returnType);
301: returnType = Signature.getTypeErasure(returnType);
302: sb.append(JdtUtils.getResolvedTypeFileName(returnType,
303: declaringType));
304: while (dim > 0) {
305: sb.append("[]");
306: dim--;
307: }
308: } catch (JavaModelException jme) {
309: sb.append("*");
310: }
311:
312: sb.append(" ");
313: sb.append(getFullyQualifiedName(declaringType));
314: sb.append(".");
315: sb.append(method.isConstructor() ? "__INIT__" : method
316: .getElementName());
317: sb.append("(");
318:
319: for (int i = 0; i < params.length; i++) {
320: if (i != 0) {
321: sb.append(", ");
322: }
323:
324: String erasedSig = Signature.getTypeErasure(params[i]);
325: sb.append(JdtUtils.getResolvedTypeFileName(erasedSig,
326: declaringType));
327: dim = Signature.getArrayCount(erasedSig);
328:
329: if (i == lastParam && isVararg) {
330: dim--;
331: }
332: while (dim > 0) {
333: sb.append("[]");
334: dim--;
335: }
336: if (i == lastParam && isVararg) {
337: sb.append("...");
338: }
339: }
340:
341: sb.append(")");
342:
343: return sb.toString();
344: }
345:
346: public MethodInfo getMethodInfo(IMethod method) {
347: MethodInfo info = null;
348:
349: if (method != null) {
350: try {
351: info = m_classInfoFactory.getMethodInfo(method);
352: } catch (JavaModelException jme) {/**/
353: } catch (NullPointerException npe) {/**/
354: }
355: }
356:
357: return info;
358: }
359:
360: public FieldInfo getFieldInfo(IField field) {
361: return (field != null) ? m_classInfoFactory.getFieldInfo(field)
362: : null;
363: }
364:
365: public MethodInfo getMethodInfo(MethodDeclaration methodDecl) {
366: return getMethodInfo(methodDecl2IMethod(methodDecl));
367: }
368:
369: public static IMethod methodDecl2IMethod(
370: MethodDeclaration methodDecl) {
371: IMethodBinding binding = methodDecl.resolveBinding();
372: IJavaElement elem = binding != null ? binding.getJavaElement()
373: : null;
374:
375: if (elem instanceof IMethod) {
376: return (IMethod) elem;
377: }
378:
379: return null;
380: }
381:
382: public static String getExecutionPattern(IJavaElement element) {
383: if (element instanceof IMethod) {
384: return getExecutionPattern((IMethod) element);
385: } else if (element instanceof IType) {
386: return getExecutionPattern((IType) element);
387: } else if (element instanceof IPackageFragment) {
388: return getExecutionPattern((IPackageFragment) element);
389: } else if (element instanceof ICompilationUnit) {
390: return getExecutionPattern(((ICompilationUnit) element)
391: .findPrimaryType());
392: } else if (element instanceof IPackageDeclaration) {
393: return getExecutionPattern((IPackageDeclaration) element);
394: }
395: return null;
396: }
397:
398: public static String getExecutionPattern(IMethod method) {
399: try {
400: if (!method.getOpenable().isOpen()) {
401: method.getOpenable().open(null);
402: }
403: return getJavadocSignature(method);
404: } catch (JavaModelException jme) {
405: IType type = method.getDeclaringType();
406: String typeName = getFullyQualifiedName(type);
407:
408: return "* " + typeName + "." + method.getElementName()
409: + "(..)";
410: }
411: }
412:
413: public static String getExecutionPattern(IType type) {
414: return "* " + getWithinPattern(type) + "(..)";
415: }
416:
417: public static String getWithinPattern(IType type) {
418: return getFullyQualifiedName(type) + ".*";
419: }
420:
421: public static String getExecutionPattern(IPackageFragment fragment) {
422: return "* " + getWithinPattern(fragment) + "(..)";
423: }
424:
425: public static String getExecutionPattern(
426: IPackageDeclaration packageDecl) {
427: return "* " + getWithinPattern(packageDecl) + "(..)";
428: }
429:
430: public static String getWithinPattern(IPackageFragment fragment) {
431: return fragment.getElementName() + "..*";
432: }
433:
434: public static String getWithinPattern(
435: IPackageDeclaration packageDecl) {
436: return packageDecl.getElementName() + "..*";
437: }
438: }
|