svnno****@sourc*****
svnno****@sourc*****
2009年 10月 9日 (金) 12:59:48 JST
Revision: 3737 http://sourceforge.jp/projects/jiemamy/svn/view?view=rev&revision=3737 Author: ashigeru Date: 2009-10-09 12:59:48 +0900 (Fri, 09 Oct 2009) Log Message: ----------- Javadocとテストを整理。 いくつか対処できていない項目についてタスクタグを付与。 Modified Paths: -------------- leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/FactoryEnhancer.java leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/InterfaceEnhancer.java leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/helper/EnhanceManipulator.java leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/helper/EnhanceTargetProductCollector.java leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/InterfaceEnhancerTest.java Added Paths: ----------- leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/SimpleInterfaceFactoryConflict.java leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/SimpleInterfaceFactoryOverride.java Modified: leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/FactoryEnhancer.java =================================================================== --- leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/FactoryEnhancer.java 2009-10-09 01:07:22 UTC (rev 3736) +++ leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/FactoryEnhancer.java 2009-10-09 03:59:48 UTC (rev 3737) @@ -333,10 +333,16 @@ * Javaの言語仕様では、クラスインスタンス生成時にパラメータ化型を利用する場合、 * その実型引数は型式であってはならない(ワイルドカードが使えない)。 */ - return createFactory(getEnhanced()); + return createMetaFactory(getEnhanced()); } - private static <F>ReflectionFactory<F> createFactory(Class<F> aClass) { + /** + * メタファクトリのインスタンスを作成する。 + * @param <F> メタファクトリが生成するファクトリの種類 + * @param aClass メタファクトリが生成するファクトリのクラス + * @return 生成したメタファクトリ + */ + private static <F>ReflectionFactory<F> createMetaFactory(Class<F> aClass) { return new ReflectionFactory<F>(aClass); } @@ -354,7 +360,7 @@ AccessibilityValidator.validate(enhance); Map<CtClass, CtClass> targetProducts = - prepareProducts(enhance); + createProductMap(enhance); Map<CtClass, AspectList<CtMethod>> allProductAspects = EnhanceManipulator.weavePointcutIntoAllProducts(enhanceManager, targetProducts); AspectList<CtConstructor> factoryAspects = @@ -365,7 +371,19 @@ return installedFactory.asSubclass(factoryInterface); } - private Map<CtClass, CtClass> prepareProducts(CtClass enhance) throws EnhanceException { + /** + * 指定の(拡張された)ファクトリに対し、必要なプロダクトクラスを拡張したクラスを生成して返す。 + * <p> + * 拡張されたプロダクトクラスは、親クラスにもとのプロダクトクラスを持ち、 + * 全ての(公開)コンストラクタが移譲コンストラクタとして宣言されている。 + * ただし、返されるマップに含まれるプロダクトクラスは、メソッド呼び出しのポイントカットが存在するものに限られる。 + * つまり、該当するジョインポイントが存在しないクラスは、このメソッド呼び出しの戻り値に含まれない。 + * </p> + * @param enhance 対象の拡張されたファクトリクラス + * @return 拡張対象となった本来のプロダクトクラスと、それに対応する拡張プロダクトクラスのペア一覧 + * @throws EnhanceException 拡張プロダクトクラスの生成に失敗した場合 + */ + private Map<CtClass, CtClass> createProductMap(CtClass enhance) throws EnhanceException { assert enhance != null; List<CtClass> targets = EnhanceTargetProductCollector.collect(enhance, enhanceManager); Map<CtClass, CtClass> result = newMap(); Modified: leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/InterfaceEnhancer.java =================================================================== --- leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/InterfaceEnhancer.java 2009-10-09 01:07:22 UTC (rev 3736) +++ leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/InterfaceEnhancer.java 2009-10-09 03:59:48 UTC (rev 3737) @@ -26,6 +26,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.text.MessageFormat; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -90,6 +91,12 @@ * また、{@code final}で指定されていてはならず、引数をとらない公開コンストラクタを提供する必要がある。 * </li> * </ul> + * <p> + * なお、{@code v0.2.0}の時点ではファクトリ、およびプロダクトのco-variant return typeなどに正しく対応できていない。 + * JDK5.0で対応されたブリッジメソッドが導入されるようなメソッドをファクトリおよびプロダクトに作成した場合の挙動は保証されない。 + * たとえば、メソッドオーバーライド時の戻り値型にサブタイプを指定したり、 + * 引数に型変数を直接指定するメソッドを持つインターフェースを継承する場合などには注意が必要である。 + * </p> * @version 0.2.0 * @since 0.2.0 * @author Suguru ARAKAWA @@ -204,6 +211,44 @@ this.converter = new JavassistConverter(factoryInterface); } + /** + * インスタンスを生成する。 + * <p> + * このコンストラクタは引数{@code enhances}を{@link List}型に変換した後に、 + * {@link #InterfaceEnhancer(Class, Class, List)}にすべての引数を委譲して実行する。 + * </p> + * @param factoryInterface 実装を生成する対象のファクトリインターフェース + * @param productSuperClass それぞれのプロダクトが実装する親クラス + * @param enhances 拡張を定義するオブジェクトの一覧 + * @throws NullPointerException + * 引数{@code enhances}に{@code null}が指定された場合 + * @throws IllegalArgumentException + * {@link #InterfaceEnhancer(Class, Class, List)}で同様の例外が発生した場合 + * @throws NullPointerException + * {@link #InterfaceEnhancer(Class, Class, List)}で同様の例外が発生した場合 + * @see #InterfaceEnhancer(Class, Class, List) + */ + public InterfaceEnhancer(Class<T> factoryInterface, Class<?> productSuperClass, Enhance... enhances) { + this(factoryInterface, productSuperClass, checkToList(enhances, "enhances")); //$NON-NLS-1$ + } + + private static <T>List<T> checkToList(T[] values, String name) { + if (values == null) { + throw new NullPointerException(name); + } + return Arrays.asList(values); + } + + /** + * ファクトリインターフェースが満たすべき制約を検証する。 + * <p> + * ただし、ここではファクトリメソッドに関する検査は行わない。 + * これについては、{@link #computeProductInterfaces(Class)}の内部で行われる。 + * </p> + * @param anInterface 対象のファクトリインターフェース + * @throws IllegalArgumentException 引数がファクトリインターフェースとしてのいずれかの制約を満たさない場合 + * @see InterfaceEnhancer + */ private static void checkFactoryInterfaceConstraint(Class<?> anInterface) { assert anInterface != null; int modifiers = anInterface.getModifiers(); @@ -219,6 +264,12 @@ } } + /** + * ファクトリインターフェースの親クラスが満たすべき制約を検証する。 + * @param aClass 対象のクラス + * @throws IllegalArgumentException 引数がファクトリインターフェースの親クラスとしてのいずれかの制約を満たさない場合 + * @see InterfaceEnhancer + */ private void checkProductSuperClassConstraint(Class<?> aClass) { assert aClass != null; if (ReflectionUtil.isNormalClass(aClass) == false) { @@ -252,6 +303,40 @@ } } + /** + * 生成したファクトリをインスタンスかするためのメタファクトリを返す。 + * @throws EnhanceException ファクトリの拡張に失敗した場合 + */ + @Override + protected Factory<? extends T> createFactory() throws EnhanceException { + /* + * わざわざ別メソッドにしているのは、getEnhance()が返すクラスが + * ? extends T であり、これをキャプチャして名前のある型変数にする必要があるため。 + * Javaの言語仕様では、クラスインスタンス生成時にパラメータ化型を利用する場合、 + * その実型引数は型式であってはならない(ワイルドカードが使えない)。 + */ + return createMetaFactory(getImplemtation()); + } + + private synchronized Class<? extends T> getImplemtation() throws EnhanceException { + if (factoryImplementation == null) { + this.factoryImplementation = createImplementation(); + + // prune javassist information + enhanceManager = null; + converter = null; + } + return this.factoryImplementation; + } + + /** + * 指定のファクトリインターフェースが利用する、プロダクトインターフェースの一覧を返す。 + * @param factoryInterface 対象のファクトリインターフェース + * @return 対応するプロダクトインターフェースの一覧 + * @throws IllegalArgumentException 引数のファクトリインターフェースが参照するいずれかのファクトリメソッドが、 + * 制約を満たさないプロダクトインターフェースを戻り値に持つ場合 + * @see InterfaceEnhancer + */ private static Set<Class<?>> computeProductInterfaces(Class<?> factoryInterface) { assert factoryInterface != null; Set<Class<?>> results = new HashSet<Class<?>>(); @@ -278,6 +363,11 @@ return Collections.unmodifiableSet(results); } + /** + * このクラスのインスタンス生成時に指定された、ファクトリインターフェースを実装したクラスオブジェクトを生成して返す。 + * @return 生成したクラスオブジェクト + * @throws EnhanceException ファクトリインターフェースの実装や、クラスオブジェクトの生成に失敗した場合 + */ private Class<? extends T> createImplementation() throws EnhanceException { assert enhanceManager != null; assert converter != null; @@ -285,10 +375,12 @@ Map<CtClass, CtClass> targetProducts = createProductMap(); CtClass implementation = createFactory(targetProducts); - AccessibilityValidator.validate(implementation); Map<CtClass, AspectList<CtMethod>> allProductAspects = weavePointcutIntoAllProducts(enhanceManager, targetProducts); + + AccessibilityValidator.validate(implementation); + AspectList<CtConstructor> factoryAspects = weavePointcutIntoFactory(implementation, targetProducts, allProductAspects); Class<?> installedFactory = @@ -297,18 +389,15 @@ return installedFactory.asSubclass(factoryInterface); } - private AspectList<CtConstructor> weavePointcutIntoFactory( - CtClass implementation, - Map<CtClass, CtClass> targetProducts, - Map<CtClass, AspectList<CtMethod>> allProductAspects) throws EnhanceException { - assert implementation != null; - assert targetProducts != null; - assert allProductAspects != null; - - LOG.trace("Weaving pointcuts: {}", implementation.getName()); - return NewInstanceEnhancer.enhance(implementation, enhanceManager, targetProducts, allProductAspects); - } - + /** + * プロダクトインターフェースの一覧に対応する、プロダクトクラスの一覧を生成して返す。 + * <p> + * このメソッドが生成する各プロダクトクラスは、特にコンストラクタやメソッドが生成されていない状態である。 + * 親クラスと親インターフェースのみが、プロダクトクラスの規約に従って設定される。 + * </p> + * @return プロダクトインターフェースと、対応するプロダクトクラスのペア一覧 + * @throws EnhanceException プロダクトクラスの生成に失敗した場合 + */ private Map<CtClass, CtClass> createProductMap() throws EnhanceException { LOG.trace("Creating each product map: {}", productInterfaces); Map<CtClass, CtClass> results = new HashMap<CtClass, CtClass>(); @@ -322,40 +411,60 @@ return results; } - private CtClass createFactory(Map<CtClass, CtClass> targetProducts) throws EnhanceException { - assert targetProducts != null; + /** + * ファクトリインターフェースに対するファクトリクラスの実装を生成して返す。 + * <p> + * 引数に指定したプロダクトインターフェースとプロダクトクラスのマッピングは、 + * ファクトリインターフェースがファクトリメソッドを実装する際に使用する。 + * ファクトリメソッドを実装する際には、次の順で作業が行われるはずである。 + * </p> + * <ul> + * <li> ファクトリメソッドに対応したコンストラクタを、該当のファクトリクラス上に生成する </li> + * <li> ファクトリメソッドに対応したメソッドを、ファクトリクラス上に生成する </li> + * <li> ファクトリクラス上のファクトリメソッドが、ファクトリクラス上の対応するコンストラクタを起動してその値を返すように実装する </li> + * </ul> + * <p> + * この時点では、まだ{@link Enhance}は利用しない。 + * </p> + * @param targetProductMap {@link #createProductMap()}で生成したプロダクトマップ。 + * それぞれの実装に対し、ファクトリメソッドに対応したコンストラクタが自動生成される + * @return 生成したファクトリクラス + * @throws EnhanceException ファクトリクラスの生成や、プロダクトクラス上のコンストラクタ生成に失敗した場合 + */ + private CtClass createFactory(Map<CtClass, CtClass> targetProductMap) throws EnhanceException { + assert targetProductMap != null; CtClass factory = converter.loadCtClass(factoryInterface); - CtClass factoryImpl = createFactoryImplementation(factory, targetProducts); + CtClass factoryImpl = createFactoryImplementation(factory, targetProductMap); return factoryImpl; } - private synchronized Class<? extends T> getImplemtation() throws EnhanceException { - if (factoryImplementation == null) { - this.factoryImplementation = createImplementation(); - - // prune javassist information - enhanceManager = null; - converter = null; - } - return this.factoryImplementation; + /** + * ファクトリクラスで行われるプロダクトインスタンスの生成に対し、{@link Enhance}による拡張を挿入する。 + * @param implementation 対象のファクトリクラス + * @param targetProductMap {@link #createProductMap()}で生成したプロダクトマップ + * @param allProductAspects それぞれのプロダクトクラスに追加したアスペクトの一覧 + * @return ファクトリクラスのプロダクトインスタンス生成に対する、アスペクトの一覧 + * @throws EnhanceException ファクトリクラスの拡張に失敗した場合 + */ + private AspectList<CtConstructor> weavePointcutIntoFactory( + CtClass implementation, + Map<CtClass, CtClass> targetProductMap, + Map<CtClass, AspectList<CtMethod>> allProductAspects) throws EnhanceException { + assert implementation != null; + assert targetProductMap != null; + assert allProductAspects != null; + + LOG.trace("Weaving pointcuts: {}", implementation.getName()); + return NewInstanceEnhancer.enhance(implementation, enhanceManager, targetProductMap, allProductAspects); } /** - * 生成したファクトリをインスタンスかするためのメタファクトリを返す。 - * @throws EnhanceException ファクトリの拡張に失敗した場合 + * メタファクトリのインスタンスを作成する。 + * @param <F> メタファクトリが生成するファクトリの種類 + * @param aClass メタファクトリが生成するファクトリのクラス + * @return 生成したメタファクトリ */ - @Override - protected Factory<? extends T> createFactory() throws EnhanceException { - /* - * わざわざ別メソッドにしているのは、getEnhance()が返すクラスが - * ? extends T であり、これをキャプチャして名前のある型変数にする必要があるため。 - * Javaの言語仕様では、クラスインスタンス生成時にパラメータ化型を利用する場合、 - * その実型引数は型式であってはならない(ワイルドカードが使えない)。 - */ - return createFactory(getImplemtation()); - } - - private static <F>ReflectionFactory<F> createFactory(Class<F> aClass) { + private static <F>Factory<F> createMetaFactory(Class<F> aClass) { return new ReflectionFactory<F>(aClass); } } Modified: leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/helper/EnhanceManipulator.java =================================================================== --- leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/helper/EnhanceManipulator.java 2009-10-09 01:07:22 UTC (rev 3736) +++ leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/helper/EnhanceManipulator.java 2009-10-09 03:59:48 UTC (rev 3737) @@ -36,6 +36,7 @@ import javassist.CtMember; import javassist.CtMethod; import javassist.NotFoundException; +import javassist.bytecode.Descriptor; import javassist.expr.NewExpr; import org.slf4j.Logger; @@ -43,11 +44,11 @@ import org.jiemamy.utils.enhancer.EnhanceException; import org.jiemamy.utils.enhancer.InvocationHandler; +import org.jiemamy.utils.enhancer.InvocationPointcut; /** * エンハンスを行う際の定型的なクラス書き換えを行うためのライブラリ。 * @version 0.2.0 - * @since 0.2.0 * @author Suguru ARAKAWA (Gluegent, Inc.) */ public class EnhanceManipulator { @@ -168,8 +169,8 @@ LOG.debug("A factory implementation: {} implements {}", implementation.getName(), factoryInterface.getName()); - // 二回計算してるので遅いが、たぶん重要じゃない - for (NameAndDescriptor identity : collectInterfaceMethods(factoryInterface)) { + // FIXME ブリッジメソッドを作成する + for (NameAndParameter identity : collectInterfaceMethods(factoryInterface)) { implementFactoryMethod(implementation, identity.method, targetProducts); } return implementation; @@ -371,40 +372,72 @@ return implementation; } - private static Set<NameAndDescriptor> collectInterfaceMethods(CtClass anInterface) throws EnhanceException { + /** + * 指定のインターフェースが公開するインターフェースメソッドの一覧を返す。 + * <p> + * インターフェースメソッドがオーバーライドされている場合、そのうち一つだけを返す。 + * ただし、現時点ではオーバーライド時の共変戻り値型による戻り値の変更を許していない。 + * これは将来のバージョンで改善されるかもしれない。 + * </p> + * @param anInterface 対象のインターフェース + * @return 対象のインターフェースに含まれる公開メソッドの一覧 + * @throws EnhanceException メソッドの計算に失敗した場合 + * @since 0.2.0 + */ + private static Set<NameAndParameter> collectInterfaceMethods(CtClass anInterface) throws EnhanceException { assert anInterface != null; assert anInterface.isInterface(); - Set<NameAndDescriptor> results = new HashSet<NameAndDescriptor>(); + Map<NameAndParameter, NameAndParameter> results = new HashMap<NameAndParameter, NameAndParameter>(); LinkedList<CtClass> work = new LinkedList<CtClass>(); work.addFirst(anInterface); Set<String> saw = new HashSet<String>(); while (work.isEmpty() == false) { - CtClass target = work.removeFirst(); - if (saw.contains(target.getName())) { + CtClass targetInterface = work.removeFirst(); + if (saw.contains(targetInterface.getName())) { continue; } - saw.add(target.getName()); - for (CtMethod method : target.getDeclaredMethods()) { - NameAndDescriptor identity = new NameAndDescriptor(method); - if (results.contains(identity) == false) { - results.add(identity); + saw.add(targetInterface.getName()); + try { + for (CtMethod method : targetInterface.getDeclaredMethods()) { + NameAndParameter target = new NameAndParameter(method); + + // オーバーライド性のあるものが既に追加されているか + NameAndParameter override = results.get(target); + if (override == null) { + // オーバーライドしていなければそのまま追加 + results.put(target, target); + } else if (target.method.getSignature().equals(override.method.getSignature())) { + // まずはシグネチャの一致で高速に判定する + // シグネチャが一致すれば co-variant return type によるオーバーライド戻り値の変更をやってない + // そのため、多重定義は不要 + } else { + // FIXME 今のところ、co-variant return typeには未対応 + throw new EnhanceException( + MessageFormat.format( + "Co-variant return type is not supported, ({0}#{1}{2} <-> {3}#{4}{5})", + override.method.getDeclaringClass().getName(), + override.method.getName(), + override.method.getSignature(), + target.method.getDeclaringClass().getName(), + target.method.getName(), + target.method.getSignature()), + null); + } } - } - try { - for (CtClass superInterface : target.getInterfaces()) { + for (CtClass superInterface : targetInterface.getInterfaces()) { work.addFirst(superInterface); } } catch (NotFoundException e) { throw new EnhanceException( MessageFormat.format( "Cannot resolve super interfaces for {0}", - target.getName()), + targetInterface.getName()), e); } } - return results; + return new HashSet<NameAndParameter>(results.values()); } /** @@ -833,7 +866,8 @@ /** * 単一のプロダクトクラスにアスペクト用のフックを織り込む。 * <p> - * {@code enhance <: base} + * {@code base}は{@link InvocationPointcut#isTarget(CtClass, CtBehavior)}の第一引数に利用される(であろう)型で、 + * {@code enhance}のスーパータイプである必要がある。 * </p> * @param enhanceManager エンハンスに関する情報を一意に管理するオブジェクト * @param base 拡張される前のプロダクトクラス定義 @@ -854,7 +888,6 @@ List<Aspect<CtMethod>> results = new ArrayList<Aspect<CtMethod>>(); CtField holder = null; int enhanceIndex = 0; - // TODO getMethodsの挙動 where base.isInterface() for (CtMethod method : base.getMethods()) { if (enhanceManager.isLegalJoinpoint(method) == false) { continue; @@ -935,10 +968,15 @@ if (allProductAspects == null) { throw new NullPointerException("allProductAspects is null"); //$NON-NLS-1$ } + + LOG.trace("Installing: {}", targetFactory.getName()); Map<CtClass, CtClass> restProducts = loadAndInitializeProducts(converter, targetProducts, allProductAspects); - for (CtClass klass : restProducts.values()) { - converter.toClass(klass); + for (CtClass enhanced : restProducts.values()) { + LOG.debug("Installing an enhanced product: {}", enhanced.getName()); + converter.toClass(enhanced); } + + LOG.debug("Installing the enhanced factory: {}", targetFactory.getName()); Class<?> result = converter.toClass(targetFactory); if (factoryAspects != null) { registerAdviceTable(result, converter.toConstructorAspects(factoryAspects)); @@ -966,7 +1004,6 @@ JavassistConverter converter, Map<CtClass, CtClass> productsToBeEnhanced, Map<CtClass, AspectList<CtMethod>> allProductAspects) throws EnhanceException { - assert productsToBeEnhanced != null; assert allProductAspects != null; @@ -976,6 +1013,7 @@ CtClass orig = entry.getKey(); AspectList<CtMethod> aspects = entry.getValue(); CtClass enhanced = rest.remove(orig); + LOG.debug("Installing an enhanced product: {}", enhanced.getName()); AdviceTable table = converter.toMethodAspects(aspects); registerAdviceTable(converter.toClass(enhanced), table); } @@ -1020,23 +1058,24 @@ * @version $Id$ * @author Suguru ARAKAWA */ - private static class NameAndDescriptor { + private static class NameAndParameter { final CtMethod method; final String name; - final String descriptor; + final String parameter; /** * インスタンスを生成する。 * @param method 対象のメソッド */ - public NameAndDescriptor(CtMethod method) { + public NameAndParameter(CtMethod method) { assert method != null; name = method.getName(); - descriptor = method.getSignature(); + String paramAndReturn = method.getSignature(); + parameter = Descriptor.getParamDescriptor(paramAndReturn); this.method = method; } @@ -1044,7 +1083,7 @@ public int hashCode() { final int prime = 31; int result = 1; - result = prime * result + descriptor.hashCode(); + result = prime * result + parameter.hashCode(); result = prime * result + name.hashCode(); return result; } @@ -1060,8 +1099,8 @@ if (getClass() != obj.getClass()) { return false; } - NameAndDescriptor other = (NameAndDescriptor) obj; - if (descriptor.equals(other.descriptor) == false) { + NameAndParameter other = (NameAndParameter) obj; + if (parameter.equals(other.parameter) == false) { return false; } if (name.equals(other.name) == false) { @@ -1072,7 +1111,10 @@ } + /** + * インスタンス生成の禁止。 + */ private EnhanceManipulator() { - super(); + throw new AssertionError(); } } Modified: leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/helper/EnhanceTargetProductCollector.java =================================================================== --- leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/helper/EnhanceTargetProductCollector.java 2009-10-09 01:07:22 UTC (rev 3736) +++ leto/factory-enhancer/trunk/src/main/java/org/jiemamy/utils/enhancer/helper/EnhanceTargetProductCollector.java 2009-10-09 03:59:48 UTC (rev 3737) @@ -52,7 +52,6 @@ * @throws NullPointerException 引数に{@code null}が指定された場合 */ public static List<CtClass> collect(CtClass target, EnhanceManager enhanceManager) throws EnhanceException { - if (target == null) { throw new NullPointerException("target"); //$NON-NLS-1$ } @@ -65,8 +64,10 @@ target.instrument(inspector); return inspector.results; } catch (CannotCompileException e) { - throw new EnhanceException(MessageFormat - .format("Cannot collect target products from {0}", target.getName()), e); + throw new EnhanceException(MessageFormat.format( + "Cannot collect target products from {0}", + target.getName()), + e); } } Modified: leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/InterfaceEnhancerTest.java =================================================================== --- leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/InterfaceEnhancerTest.java 2009-10-09 01:07:22 UTC (rev 3736) +++ leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/InterfaceEnhancerTest.java 2009-10-09 03:59:48 UTC (rev 3737) @@ -24,9 +24,7 @@ import static org.junit.Assert.fail; import java.lang.reflect.InvocationTargetException; -import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Properties; @@ -34,6 +32,7 @@ import javassist.CtClass; import javassist.CtConstructor; +import org.junit.Ignore; import org.junit.Test; import org.jiemamy.utils.enhancer.aspect.StringResultPointcut; @@ -254,6 +253,78 @@ } /** + * Test method for {@link org.jiemamy.utils.enhancer.AbstractEnhancer#getFactory()}. + * FIXME implement co-variant return type + * @throws Exception if occur + */ + @Ignore + @Test + public void testGetFactory_OverrideWithReturnSubType() throws Exception { + Enhance enhance = new Enhance(new StringResultPointcut(), new InvocationHandler() { + + public Object handle(Invocation invocation) { + if (invocation.getInvoker() instanceof InterfaceProductEx) { + return "inherited"; + } + if (invocation.getInvoker() instanceof InterfaceProduct) { + return "base"; + } + throw new AssertionError(); + } + }); + InterfaceEnhancer<SimpleInterfaceFactoryOverride> enhancer = + new InterfaceEnhancer<SimpleInterfaceFactoryOverride>( + SimpleInterfaceFactoryOverride.class, + Object.class, + enhances(enhance)); + Factory<? extends SimpleInterfaceFactoryOverride> metaFactory = enhancer.getFactory(); + SimpleInterfaceFactoryOverride factory = metaFactory.newInstance(); + + InterfaceProductEx productEx = factory.newProduct(); + assertThat(productEx.getMessage(), is("inherited")); + assertThat(productEx.getMessageEx(), is("inherited")); + + InterfaceProduct product = productEx; + assertThat(product.getMessage(), is("inherited")); + } + + /** + * Test method for {@link org.jiemamy.utils.enhancer.AbstractEnhancer#getFactory()}. + * FIXME implement co-variant return type + * @throws Exception if occur + */ + @Ignore + @Test + public void testGetFactory_OverrideConflictReturnSubType() throws Exception { + Enhance enhance = new Enhance(new StringResultPointcut(), new InvocationHandler() { + + public Object handle(Invocation invocation) { + if (invocation.getInvoker() instanceof InterfaceProductEx) { + return "inherited"; + } + if (invocation.getInvoker() instanceof InterfaceProduct) { + return "base"; + } + throw new AssertionError(); + } + }); + InterfaceEnhancer<SimpleInterfaceFactoryConflict> enhancer = + new InterfaceEnhancer<SimpleInterfaceFactoryConflict>( + SimpleInterfaceFactoryConflict.class, + Object.class, + enhances(enhance)); + Factory<? extends SimpleInterfaceFactoryConflict> metaFactory = enhancer.getFactory(); + SimpleInterfaceFactoryConflict factory = metaFactory.newInstance(); + + InterfaceProductEx productEx = factory.newProduct(); + assertThat(productEx.getMessage(), is("inherited")); + assertThat(productEx.getMessageEx(), is("inherited")); + + InterfaceProduct product = ((SimpleInterfaceFactory) factory).newProduct(); + assertThat(product.getMessage(), is("inherited")); + } + + /** * Test method for {@link InterfaceEnhancer#InterfaceEnhancer(java.lang.Class, java.lang.Class, java.util.List)}. */ @Test(expected = IllegalArgumentException.class) @@ -374,7 +445,7 @@ enhances()); } - private static List<Enhance> enhances(Enhance... enhances) { - return Arrays.asList(enhances); + private static Enhance[] enhances(Enhance... enhances) { + return enhances; } } Added: leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/SimpleInterfaceFactoryConflict.java =================================================================== --- leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/SimpleInterfaceFactoryConflict.java (rev 0) +++ leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/SimpleInterfaceFactoryConflict.java 2009-10-09 03:59:48 UTC (rev 3737) @@ -0,0 +1,28 @@ +/* + * Copyright 2007-2009 Jiemamy Project and the Others. + * Created on 2009/10/04 + * + * This file is part of Jiemamy. + * + * 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.jiemamy.utils.enhancer; + +/** + * 単純なインターフェースファクトリ。 + * @version $Id$ + * @author Suguru ARAKAWA + */ +public interface SimpleInterfaceFactoryConflict extends SimpleInterfaceFactoryOverride, SimpleInterfaceFactory { + +} Property changes on: leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/SimpleInterfaceFactoryConflict.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Added: leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/SimpleInterfaceFactoryOverride.java =================================================================== --- leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/SimpleInterfaceFactoryOverride.java (rev 0) +++ leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/SimpleInterfaceFactoryOverride.java 2009-10-09 03:59:48 UTC (rev 3737) @@ -0,0 +1,32 @@ +/* + * Copyright 2007-2009 Jiemamy Project and the Others. + * Created on 2009/10/04 + * + * This file is part of Jiemamy. + * + * 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.jiemamy.utils.enhancer; + +/** + * 単純なインターフェースファクトリ。 + * @version $Id$ + * @author Suguru ARAKAWA + */ +public interface SimpleInterfaceFactoryOverride extends SimpleInterfaceFactory { + + /** + * @return {@link InterfaceProductEx} + */ + InterfaceProductEx newProduct(); +} Property changes on: leto/factory-enhancer/trunk/src/test/java/org/jiemamy/utils/enhancer/SimpleInterfaceFactoryOverride.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native