//
// This file is part of the prose package.
//
// The contents of this file are subject to the Mozilla Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// The Original Code is prose.
//
// The Initial Developer of the Original Code is Angela Nicoara. Portions
// created by Angela Nicoara are Copyright (C) 2004 Angela Nicoara.
// All Rights Reserved.
//
// Contributor(s):
// $Id: MethodRedefineCut.java,v 1.3 2008/11/18 11:36:07 anicoara Exp $
// =====================================================================
//
package ch.ethz.prose.crosscut;
import java.lang.reflect.Method;
import ch.ethz.jvmai.MethodRedefineJoinPoint;
import ch.ethz.prose.engine.JoinPointRequest;
import ch.ethz.prose.filter.ANDingPointCutter;
import ch.ethz.prose.filter.PointCutter;
/**
* A crosscut that represents method redefinitions.
*
* @version $Revision: 1.3 $
* @author Angela Nicoara
*/
public abstract class MethodRedefineCut extends MethodCut {
private static final long serialVersionUID = 3760844579762419253L;
// transient to force deserialized cuts to get reinitialized
transient private boolean isRedefineCutInitialized = false;
protected MethodRedefineCut() throws MissingInformationException {
super();
initState();
}
public void insertionAction(boolean beforeInsertion) {
super.insertionAction(beforeInsertion);
// we might provide an initstate here for the case
// this crosscut is deserialized and the
// static initializer or the constructor are not properly
// called
initState();
}
private void initState() throws MissingInformationException {
if (isRedefineCutInitialized) return;
isRedefineCutInitialized=true;
mcutSpecializer = new MethodRedefineCutSpecializer(adviceSignature);
}
/**
* Generate method redefine requests for each declared method in <code>theClass</code>
* that matches this crosscut.
*
* @param theClass class whose methods are checked
* @return matching collection of join point requests
*/
protected CrosscutRequest doCreateRequest(Class theClass) {
CrosscutRequest result = new CrosscutRequest();
Method[] methArray = null;
try {
methArray = theClass.getDeclaredMethods();
} catch (NoClassDefFoundError e) {
return result;
}
for (int i = 0; i < methArray.length; i++) {
Class[] params = methArray[i].getParameterTypes();
JoinPointRequest crtRequest;
crtRequest = requestFactory.createJoinPointRequest(MethodRedefineJoinPoint.KIND, methArray[i]);
if (mcutSpecializer.isSpecialRequest(crtRequest))
result.add(crtRequest);
}
return result;
}
public PointCutter equivalentSpecializer() {
initState();
if (getSpecializer() == null)
return mcutSpecializer;
else
return new ANDingPointCutter(mcutSpecializer,(PointCutter)getSpecializer());
}
protected PointCutter pointCutter() {
throw new RuntimeException("there's no PointCutter for " + this.getClass().getName() );
}
/**
* Invokes the redefined Method.
* <P>
* This always invokes the original method, if it was
* redefined multiple times other redefinition advices
* are ignored.
* <P>
* <CODE>proceed*(...)</CODE> may only be used in the advice body (<CODE>METHOD_ARGS()</CODE>).
*/
// The proceed method for various return types are only required for JDK < 1.5.
// The Varargs feature of JDK 1.5 allows together with its In- and Outboxing
// capabilities to use only one method:
//final static protected Object proceed(Object...objects) { // JDK 1.5 Varargs, don't use it with older JDK versions
final static protected void proceed() { // for JDK < 1.5 (upwards compatible)
// Calls to this method must be redirected to the real
// method by the advice weaver. So this method may never
// be invoked
throw new RuntimeException("Oops 'proceed()' may not be invoked directly");
}
final static protected Object proceedObject() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected int proceedInt() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected long proceedLong() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected float proceedFloat() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected double proceedDouble() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected byte proceedByte() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected char proceedChar() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected boolean proceedBoolean() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected Object[] proceedObjectArray() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected int[] proceedIntArray() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected long[] proceedLongArray() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected float[] proceedFloatArray() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected double[] proceedDoubleArray() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected byte[] proceedByteArray() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected char[] proceedCharArray() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
final static protected boolean[] proceedBooleanArray() // for JDK < 1.5 (upwards compatible)
{ throw new RuntimeException("Oops 'proceed()' may not be invoked directly"); } // for JDK < 1.5 (upwards compatible)
public String toString() {
return " Crosscut: 'MethodRedefineCut' \n" + " Advice:" + toStringSignature + "\n" + " PointCutter: " + getSpecializer() + "\n";
}
}