/* *******************************************************************
 * Copyright (c) 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: 
 *     PARC     initial implementation 
 * ******************************************************************/

package org.aspectj.weaver;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;

import org.aspectj.bridge.ISourceLocation;
import org.aspectj.weaver.patterns.DeclareErrorOrWarning;
import org.aspectj.weaver.patterns.PerClause;
import org.aspectj.weaver.patterns.Pointcut;

Representation of a shadow munger for a declare error or warning declaration.
Author:Andy Clement
/** * Representation of a shadow munger for a declare error or warning declaration. * * @author Andy Clement */
public class Checker extends ShadowMunger { private boolean isError; // if not error then it is a warning private String message; private volatile int hashCode = -1; @SuppressWarnings("unused") private Checker() { }
Create a Checker for a declare error or declare warning.
Params:
  • deow – the declare error or declare warning for which to create the checker munger
/** * Create a Checker for a declare error or declare warning. * * @param deow the declare error or declare warning for which to create the checker munger */
public Checker(DeclareErrorOrWarning deow) { super(deow.getPointcut(), deow.getStart(), deow.getEnd(), deow.getSourceContext(), ShadowMungerDeow); this.message = deow.getMessage(); this.isError = deow.isError(); }
Only used when filling in a parameterized Checker
/** * Only used when filling in a parameterized Checker */
private Checker(Pointcut pointcut, int start, int end, ISourceContext context, String message, boolean isError) { super(pointcut, start, end, context, ShadowMungerDeow); this.message = message; this.isError = isError; } public boolean isError() { return isError; } public String getMessage(Shadow shadow) { return format(this.message, shadow); } @Override public void specializeOn(Shadow shadow) { throw new IllegalStateException("Cannot call specializeOn(...) for a Checker"); } @Override public boolean implementOn(Shadow shadow) { throw new IllegalStateException("Cannot call implementOn(...) for a Checker"); }
Determine if the Checker matches at a shadow. If it does then we can immediately report the message. Currently, there can never be a non-statically determinable match.
Params:
  • shadow – the shadow which to match against
  • world – the world through which to access message handlers
/** * Determine if the Checker matches at a shadow. If it does then we can immediately report the message. Currently, there can * never be a non-statically determinable match. * * @param shadow the shadow which to match against * @param world the world through which to access message handlers */
@Override public boolean match(Shadow shadow, World world) { if (super.match(shadow, world)) { world.reportCheckerMatch(this, shadow); } return false; } // implementation for PartialOrder.PartialComparable public int compareTo(Object other) { return 0; } @Override public boolean mustCheckExceptions() { return true; } @Override public Collection<ResolvedType> getThrownExceptions() { return Collections.emptyList(); } // FIXME this perhaps ought to take account of the other fields in advice (use super.equals?) @Override public boolean equals(Object other) { if (!(other instanceof Checker)) { return false; } Checker o = (Checker) other; return o.isError == isError && ((o.pointcut == null) ? (pointcut == null) : o.pointcut.equals(pointcut)); } @Override public int hashCode() { if (hashCode == -1) { int result = 17; result = 37 * result + (isError ? 1 : 0); result = 37 * result + ((pointcut == null) ? 0 : pointcut.hashCode()); hashCode = result; } return hashCode; }
Parameterize the Checker by parameterizing the pointcut
/** * Parameterize the Checker by parameterizing the pointcut */
@Override public ShadowMunger parameterizeWith(ResolvedType declaringType, Map<String, UnresolvedType> typeVariableMap) { Checker ret = new Checker(this.pointcut.parameterizeWith(typeVariableMap, declaringType.getWorld()), this.start, this.end, this.sourceContext, this.message, this.isError); return ret; }
Concretize this Checker by concretizing the pointcut
/** * Concretize this Checker by concretizing the pointcut */
@Override public ShadowMunger concretize(ResolvedType theAspect, World world, PerClause clause) { this.pointcut = this.pointcut.concretize(theAspect, getDeclaringType(), 0, this); this.hashCode = -1; return this; } @Override public ResolvedType getConcreteAspect() { return getDeclaringType(); } // public void write(DataOutputStream stream) throws IOException { // super.write(stream); // stream.writeBoolean(isError); // stream.writeUTF(message); // } // // public static Checker read(DataInputStream stream, World world) throws IOException { // Checker checker = new Checker(); // checker.isError = stream.readBoolean(); // checker.message = stream.readUTF(); // return checker; // } // Return the next non-escaped (with a '\') open curly private int nextCurly(String string, int pos) { do { int curlyIndex = string.indexOf('{', pos); if (curlyIndex == -1) { return -1; } if (curlyIndex == 0) { return 0; } if (string.charAt(curlyIndex - 1) != '\\') { return curlyIndex; } pos = curlyIndex + 1; } while (pos < string.length()); return -1; } private String format(String msg, Shadow shadow) { int pos = 0; int curlyIndex = nextCurly(msg, 0); if (curlyIndex == -1) { // was there an escaped one? if (msg.indexOf('{') != -1) { return msg.replace("\\{", "{"); } else { return msg; } } StringBuffer ret = new StringBuffer(); while (curlyIndex >= 0) { if (curlyIndex > 0) { ret.append(msg.substring(pos, curlyIndex).replace("\\{", "{")); } int endCurly = msg.indexOf('}', curlyIndex); if (endCurly == -1) { // wasn't closed properly - ignore it ret.append('{'); pos = curlyIndex + 1; } else { ret.append(getValue(msg.substring(curlyIndex + 1, endCurly), shadow)); } pos = endCurly + 1; curlyIndex = nextCurly(msg, pos); } ret.append(msg.substring(pos, msg.length())); return ret.toString(); }
Params:
  • buf – the buffer in which to insert the substitution
  • shadow – shadow from which to draw context info
  • c – the substitution character
/** * @param buf the buffer in which to insert the substitution * @param shadow shadow from which to draw context info * @param c the substitution character */
private String getValue(String key, Shadow shadow) { if (key.equalsIgnoreCase("joinpoint")) { return shadow.toString(); } else if (key.equalsIgnoreCase("joinpoint.kind")) { return shadow.getKind().getName(); } else if (key.equalsIgnoreCase("joinpoint.enclosingclass")) { return shadow.getEnclosingType().getName(); } else if (key.equalsIgnoreCase("joinpoint.enclosingmember.name")) { Member member = shadow.getEnclosingCodeSignature(); if (member==null) { return ""; } else { return member.getName(); } } else if (key.equalsIgnoreCase("joinpoint.enclosingmember")) { Member member = shadow.getEnclosingCodeSignature(); if (member==null) { return ""; } else { return member.toString(); } } else if (key.equalsIgnoreCase("joinpoint.signature")) { return shadow.getSignature().toString(); } else if (key.equalsIgnoreCase("joinpoint.signature.declaringtype")) { return shadow.getSignature().getDeclaringType().toString(); } else if (key.equalsIgnoreCase("joinpoint.signature.name")) { return shadow.getSignature().getName(); } else if (key.equalsIgnoreCase("joinpoint.sourcelocation.sourcefile")) { ISourceLocation loc = shadow.getSourceLocation(); if ((loc != null) && (loc.getSourceFile() != null)) { return loc.getSourceFile().toString(); } else { return "UNKNOWN"; } } else if (key.equalsIgnoreCase("joinpoint.sourcelocation.line")) { ISourceLocation loc = shadow.getSourceLocation(); if (loc != null) { return Integer.toString(loc.getLine()); } else { return "-1"; } } else if (key.equalsIgnoreCase("advice.aspecttype")) { return getDeclaringType().getName(); } else if (key.equalsIgnoreCase("advice.sourcelocation.line")) { ISourceLocation loc = getSourceLocation(); if ((loc != null) && (loc.getSourceFile() != null)) { return Integer.toString(loc.getLine()); } else { return "-1"; } } else if (key.equalsIgnoreCase("advice.sourcelocation.sourcefile")) { ISourceLocation loc = getSourceLocation(); if ((loc != null) && (loc.getSourceFile() != null)) { return loc.getSourceFile().toString(); } else { return "UNKNOWN"; } } else { return "UNKNOWN_KEY{" + key + "}"; } } }