/* * 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); } }