/*
* Copyright 2004-2015 the Seasar Foundation and the Others.
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package org.seasar.framework.aop.intertype;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.Modifier;
import javassist.NotFoundException;
import org.seasar.framework.aop.InterType;
import org.seasar.framework.exception.CannotCompileRuntimeException;
import org.seasar.framework.exception.NotFoundRuntimeException;
import org.seasar.framework.util.ClassPoolUtil;
/**
* {@link InterType}の抽象クラスです。
*/
public abstract class AbstractInterType implements InterType {
/**
* Componentアノテーションです。
*/
public static final String COMPONENT = "instance = prototype";
/**
* ターゲットクラスです。
*/
protected Class targetClass;
/**
* エンハンスされたクラスです。
*/
protected CtClass enhancedClass;
/**
* クラスプールです。
*/
protected ClassPool classPool;
public void introduce(final Class targetClass, final CtClass enhancedClass) {
this.targetClass = targetClass;
this.enhancedClass = enhancedClass;
this.classPool = enhancedClass.getClassPool();
try {
introduce();
} catch (final CannotCompileException e) {
throw new CannotCompileRuntimeException(e);
} catch (final NotFoundException e) {
throw new NotFoundRuntimeException(e);
} finally {
this.targetClass = null;
this.enhancedClass = null;
this.classPool = null;
}
}
/**
* クラス構造を変更します。
*
* @throws CannotCompileException
* コンパイルできない場合
* @throws NotFoundException
* 何かが見つからない場合
*/
protected abstract void introduce() throws CannotCompileException,
NotFoundException;
/**
* ターゲットクラスを返します。
*
* @return
*/
protected Class getTargetClass() {
return targetClass;
}
/**
* エンハンスされたクラスを返します。
*
* @return エンハンスされたクラス
*/
protected CtClass getEnhancedClass() {
return enhancedClass;
}
/**
* クラスプールを返します。
*
* @return クラスプール
*/
protected ClassPool getClassPool() {
return classPool;
}
/**
* インターフェースを追加します。
*
* @param clazz
* インターフェース
*/
protected void addInterface(final Class clazz) {
enhancedClass.addInterface(toCtClass(clazz));
}
/**
* フィールドを追加します。
*
* @param type
* フィールドの型
* @param name
* フィールド名
*/
protected void addField(final Class type, final String name) {
addField(Modifier.PRIVATE, type, name);
}
/**
* フィールドを追加します。
*
* @param type
* フィールドの型
* @param name
* フィールド名
* @param init
* 初期化情報
*/
protected void addField(final Class type, final String name,
final String init) {
addField(Modifier.PRIVATE, type, name, init);
}
/**
* 静的フィールドを追加します。
*
* @param type
* フィールドの型
* @param name
* フィールド名
*/
protected void addStaticField(final Class type, final String name) {
addStaticField(Modifier.PRIVATE, type, name);
}
/**
* 静的フィールドを追加します。
*
* @param type
* フィールドの型
* @param name
* フィールド名
* @param init
* 初期化情報
*/
protected void addStaticField(final Class type, final String name,
final String init) {
addStaticField(Modifier.PRIVATE, type, name, init);
}
/**
* 定数を追加します。
*
* @param type
* フィールドの型
* @param name
* フィールド名
* @param init
* 初期化情報
*/
protected void addConstant(final Class type, final String name,
final String init) {
addStaticField(Modifier.PUBLIC | Modifier.FINAL, type, name, init);
}
/**
* 静的フィールドを追加します。
*
* @param modifiers
* アクセス修飾子
* @param type
* フィールドの型
* @param name
* フィールド名
*/
protected void addStaticField(final int modifiers, final Class type,
final String name) {
addField(Modifier.STATIC | modifiers, type, name);
}
/**
* 静的フィールドを追加します。
*
* @param modifiers
* アクセス修飾子
* @param type
* フィールドの型
* @param name
* フィールド名
* @param init
* 初期化情報
*/
protected void addStaticField(final int modifiers, final Class type,
final String name, final String init) {
addField(Modifier.STATIC | modifiers, type, name, init);
}
/**
* 静的フィールドを追加します。
*
* @param modifiers
* アクセス修飾子
* @param type
* フィールドの型
* @param name
* フィールド名
* @param init
* 初期化情報
*/
protected void addStaticField(final int modifiers, final Class type,
final String name, final CtField.Initializer init) {
addField(Modifier.STATIC | modifiers, type, name, init);
}
/**
* フィールドを追加します。
*
* @param modifiers
* アクセス修飾子
* @param type
* フィールドの型
* @param name
* フィールド名
*/
protected void addField(final int modifiers, final Class type,
final String name) {
try {
final CtField field = new CtField(toCtClass(type), name,
enhancedClass);
field.setModifiers(modifiers);
enhancedClass.addField(field);
} catch (final CannotCompileException e) {
throw new CannotCompileRuntimeException(e);
}
}
/**
* フィールドを追加します。
*
* @param src
* ソース
*/
protected void addField(final String src) {
try {
enhancedClass.addField(CtField.make(src, enhancedClass));
} catch (final CannotCompileException e) {
throw new CannotCompileRuntimeException(e);
}
}
/**
* フィールドを追加します。
*
* @param modifiers
* アクセス修飾子
* @param type
* フィールドの型
* @param name
* フィールド名
* @param init
* 初期化情報
*/
protected void addField(final int modifiers, final Class type,
final String name, final String init) {
try {
final CtField field = new CtField(toCtClass(type), name,
enhancedClass);
field.setModifiers(modifiers);
enhancedClass.addField(field, init);
} catch (final CannotCompileException e) {
throw new CannotCompileRuntimeException(e);
}
}
/**
* フィールドを追加します。
*
* @param modifiers
* アクセス修飾子
* @param type
* フィールド型
* @param name
* フィールド名
* @param init
* 初期化情報
*/
protected void addField(final int modifiers, final Class type,
final String name, final CtField.Initializer init) {
try {
final CtField field = new CtField(toCtClass(type), name,
enhancedClass);
field.setModifiers(modifiers);
enhancedClass.addField(field, init);
} catch (final CannotCompileException e) {
throw new CannotCompileRuntimeException(e);
}
}
/**
* メソッドを追加します。
*
* @param name
* メソッド名
* @param src
* ソース
*/
protected void addMethod(final String name, final String src) {
addMethod(Modifier.PUBLIC, void.class, name, null, null, src);
}
/**
* メソッドを追加します。
*
* @param name
* メソッド名
* @param paramTypes
* パラメータの型の配列
* @param src
* ソース
*/
protected void addMethod(final String name, final Class[] paramTypes,
final String src) {
addMethod(Modifier.PUBLIC, void.class, name, paramTypes, null, src);
}
/**
* メソッドを追加します。
*
* @param name
* メソッド名
* @param paramTypes
* パラメータの型の配列
* @param exceptionTypes
* 例外クラスの配列
* @param src
* ソース
*/
protected void addMethod(final String name, final Class[] paramTypes,
Class[] exceptionTypes, final String src) {
addMethod(Modifier.PUBLIC, void.class, name, paramTypes,
exceptionTypes, src);
}
/**
* メソッドを追加します。
*
* @param returnType
* 戻り値の型
* @param name
* メソッド名
* @param src
* ソース
*/
protected void addMethod(final Class returnType, final String name,
final String src) {
addMethod(Modifier.PUBLIC, returnType, name, null, null, src);
}
/**
* メソッドを追加します。
*
* @param returnType
* 戻り値の型
* @param name
* メソッド名
* @param paramTypes
* パラメータの型の配列
* @param src
* ソース
*/
protected void addMethod(final Class returnType, final String name,
final Class[] paramTypes, final String src) {
addMethod(Modifier.PUBLIC, returnType, name, paramTypes, null, src);
}
/**
* メソッドを追加します。
*
* @param returnType
* 戻り値の型
* @param name
* メソッド名
* @param paramTypes
* パラメータの型の配列
* @param exceptionTypes
* 例外の型の配列
* @param src
* ソース
*/
protected void addMethod(final Class returnType, final String name,
final Class[] paramTypes, Class[] exceptionTypes, final String src) {
addMethod(Modifier.PUBLIC, returnType, name, paramTypes,
exceptionTypes, src);
}
/**
* 静的メソッドを追加します。
*
* @param name
* メソッド名
* @param src
* ソース
*/
protected void addStaticMethod(final String name, final String src) {
addMethod(Modifier.PUBLIC | Modifier.STATIC, void.class, name, null,
null, src);
}
/**
* 静的メソッドを追加します。
*
* @param name
* メソッド名
* @param paramTypes
* パラメータの型の配列
* @param src
* ソース
*/
protected void addStaticMethod(final String name, final Class[] paramTypes,
final String src) {
addMethod(Modifier.PUBLIC | Modifier.STATIC, void.class, name,
paramTypes, null, src);
}
/**
* 静的メソッドを追加します。
*
* @param name
* メソッド名
* @param paramTypes
* パラメータの型の配列
* @param exceptionTypes
* 例外の型の配列
* @param src
* ソース
*/
protected void addStaticMethod(final String name, final Class[] paramTypes,
Class[] exceptionTypes, final String src) {
addMethod(Modifier.PUBLIC | Modifier.STATIC, void.class, name,
paramTypes, exceptionTypes, src);
}
/**
* 静的メソッドを追加します。
*
* @param returnType
* 戻り値の型
* @param name
* メソッド名
* @param src
* ソース
*/
protected void addStaticMethod(final Class returnType, final String name,
final String src) {
addMethod(Modifier.PUBLIC | Modifier.STATIC, returnType, name, null,
null, src);
}
/**
* 静的メソッドを追加します。
*
* @param returnType
* 戻り値の型
* @param name
* メソッド名
* @param paramTypes
* パラメータの型の配列
* @param src
* ソース
*/
protected void addStaticMethod(final Class returnType, final String name,
final Class[] paramTypes, final String src) {
addMethod(Modifier.PUBLIC | Modifier.STATIC, returnType, name,
paramTypes, null, src);
}
/**
* 静的メソッドを追加します。
*
* @param returnType
* 戻り値の型
* @param name
* メソッド名
* @param paramTypes
* パラメータの型の配列
* @param exceptionTypes
* 例外の型の配列
* @param src
* ソース
*/
protected void addStaticMethod(final Class returnType, final String name,
final Class[] paramTypes, Class[] exceptionTypes, final String src) {
addMethod(Modifier.PUBLIC | Modifier.STATIC, returnType, name,
paramTypes, exceptionTypes, src);
}
/**
* メソッドを追加します。
*
* @param modifiers
* アクセス修飾子
* @param returnType
* 戻り値の型
* @param name
* メソッド名
* @param paramTypes
* パラメータの型の配列
* @param exceptionTypes
* 例外の型の配列
* @param src
* ソース
*/
protected void addMethod(final int modifiers, final Class returnType,
final String name, final Class[] paramTypes,
Class[] exceptionTypes, final String src) {
try {
final CtMethod ctMethod = CtNewMethod.make(modifiers,
toCtClass(returnType), name, toCtClassArray(paramTypes),
toCtClassArray(exceptionTypes), src, enhancedClass);
enhancedClass.addMethod(ctMethod);
} catch (final CannotCompileException e) {
throw new CannotCompileRuntimeException(e);
}
}
/**
* メソッドを追加します。
*
* @param src
* ソース
*/
protected void addMethod(final String src) {
try {
enhancedClass.addMethod(CtNewMethod.make(src, enhancedClass));
} catch (final CannotCompileException e) {
throw new CannotCompileRuntimeException(e);
}
}
/**
* コンパイル時のクラスに変換します。
*
* @param clazz
* 元のクラス
* @return コンパイル時のクラス
*/
protected CtClass toCtClass(final Class clazz) {
return ClassPoolUtil.toCtClass(classPool, clazz);
}
/**
* コンパイル時のクラスの配列に変換します。
*
* @param classes
* 元のクラスの配列
* @return コンパイル時のクラスの配列
*/
protected CtClass[] toCtClassArray(final Class[] classes) {
return ClassPoolUtil.toCtClassArray(classPool, classes);
}
}