svnno****@sourc*****
svnno****@sourc*****
2009年 10月 4日 (日) 15:55:17 JST
Revision: 3698 http://sourceforge.jp/projects/jiemamy/svn/view?view=rev&revision=3698 Author: ashigeru Date: 2009-10-04 15:55:17 +0900 (Sun, 04 Oct 2009) Log Message: ----------- エンハンサがFactoryインターフェースを実装するようにした。 Modified Paths: -------------- leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/FactoryEnhancer.java leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/helper/EnhanceManipulator.java leto/factory-enhancer/branches/interface-enhancer-20091004/src/test/java/org/jiemamy/utils/enhancer/FactoryEnhancerTest.java Added Paths: ----------- leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/AbstractEnhancer.java leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/Enhancer.java Added: leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/AbstractEnhancer.java =================================================================== --- leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/AbstractEnhancer.java (rev 0) +++ leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/AbstractEnhancer.java 2009-10-04 06:55:17 UTC (rev 3698) @@ -0,0 +1,63 @@ +/* + * 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; + +import java.util.concurrent.atomic.AtomicReference; + +/** + * {@link Enhancer}の骨格実装。 + * @since 0.2.0 + * @version 0.2.0 + * @author Suguru ARAKAWA + * @param <T> エンハンスする対象の種類 + */ +public abstract class AbstractEnhancer<T> implements Enhancer<T> { + + private AtomicReference<Factory<? extends T>> factoryCache = new AtomicReference<Factory<? extends T>>(); + + + /** + * エンハンスされたクラスのインスタンスを生成するファクトリを返す。 + * <p> + * この実装では、{@link #createFactory()}でファクトリを生成し、そのキャッシュを保持する。 + * </p> + * @return エンハンスされたクラスのインスタンスを生成するファクトリ + * @throws EnhanceException 拡張に失敗した場合 + */ + public Factory<? extends T> getFactory() throws EnhanceException { + Factory<? extends T> cached = factoryCache.get(); + if (cached != null) { + return cached; + } + Factory<? extends T> factory = createFactory(); + if (factoryCache.compareAndSet(null, factory)) { + return factory; + } + cached = factoryCache.get(); + assert cached != null; + return cached; + } + + /** + * 指定のクラスのインスタンスを生成するファクトリを返す。 + * @return 生成したファクトリ + * @throws EnhanceException ファクトリの生成に失敗した場合 + */ + protected abstract Factory<? extends T> createFactory() throws EnhanceException; +} Property changes on: leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/AbstractEnhancer.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Added: leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/Enhancer.java =================================================================== --- leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/Enhancer.java (rev 0) +++ leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/Enhancer.java 2009-10-04 06:55:17 UTC (rev 3698) @@ -0,0 +1,37 @@ +/* + * 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; + +/** + * エンハンスされたクラスを参照するためのインターフェース。 + * @param <T> エンハンスする対象の種類 + * @version 0.2.0 + * @since 0.2.0 + * @author Suguru ARAKAWA + */ +public interface Enhancer<T> { + + /** + * エンハンスされたクラスのインスタンスを生成するファクトリを返す。 + * @return エンハンスされたクラスのインスタンスを生成するファクトリ + * @throws EnhanceException 拡張に失敗した場合 + * @sine 0.2.0 + */ + Factory<? extends T> getFactory() throws EnhanceException; +} Property changes on: leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/Enhancer.java ___________________________________________________________________ Added: svn:mime-type + text/plain Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Modified: leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/FactoryEnhancer.java =================================================================== --- leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/FactoryEnhancer.java 2009-10-04 06:54:41 UTC (rev 3697) +++ leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/FactoryEnhancer.java 2009-10-04 06:55:17 UTC (rev 3698) @@ -48,6 +48,7 @@ import org.jiemamy.utils.enhancer.helper.EnhanceTargetProductCollector; import org.jiemamy.utils.enhancer.helper.JavassistConverter; import org.jiemamy.utils.enhancer.helper.NewInstanceEnhancer; +import org.jiemamy.utils.enhancer.reflection.ReflectionFactory; /** * ファクトリを拡張するエンハンサ。 @@ -103,11 +104,11 @@ * さらに、コンパイラによって合成された特殊なメソッド(ブリッジメソッド等)は拡張対象とならない。 * </li> * </ul> - * @version $Date$ + * @version 0.2.0 * @author Suguru ARAKAWA (Gluegent, Inc.) * @param <T> 拡張するファクトリのインターフェース型 */ -public class FactoryEnhancer<T> { +public class FactoryEnhancer<T> extends AbstractEnhancer<T> { static final Logger LOG = LoggerFactory.getLogger(FactoryEnhancer.class); @@ -299,6 +300,7 @@ * </p> * @return 拡張されたファクトリのクラスオブジェクト * @throws EnhanceException 拡張に失敗した場合 + * @see Enhancer#getFactory() */ public synchronized Class<? extends T> getEnhanced() throws EnhanceException { if (enhancedFactory == null) { @@ -310,6 +312,26 @@ } /** + * {@link #getEnhanced()}を利用して拡張されたファクトリクラスに対する、オブジェクトファクトリを返す。 + * @throws EnhanceException {@link #getEnhanced()}の実行に失敗した場合 + * @since 0.2.0 + */ + @Override + protected Factory<? extends T> createFactory() throws EnhanceException { + /* + * わざわざ別メソッドにしているのは、getEnhance()が返すクラスが + * ? extends T であり、これをキャプチャして名前のある型変数にする必要があるため。 + * Javaの言語仕様では、クラスインスタンス生成時にパラメータ化型を利用する場合、 + * その実型引数は型式であってはならない(ワイルドカードが使えない)。 + */ + return createFactory(getEnhanced()); + } + + private static <F>ReflectionFactory<F> createFactory(Class<F> aClass) { + return new ReflectionFactory<F>(aClass); + } + + /** * ファクトリクラスを拡張し、拡張したクラスを表現する{@link java.lang.Class}オブジェクトを返す。 * @return 拡張したクラスを表現する{@link java.lang.Class}オブジェクト * @throws EnhanceException 拡張に失敗した場合 @@ -492,7 +514,7 @@ * @param base 拡張される前のプロダクトクラス定義 * @param enhance 拡張対象となるプロダクトクラス定義 * @return 対象のプロダクトクラスに適用すべきアスペクトの一覧、ひとつも存在しない場合は{@code null} - * @throws EnhanceException + * @throws EnhanceException 拡張に失敗した場合 * @see #weavePointcutIntoAllProducts(Map) */ private AspectList<CtMethod> weavePointcutIntoSingleProduct(CtClass base, CtClass enhance) throws EnhanceException { Modified: leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/helper/EnhanceManipulator.java =================================================================== --- leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/helper/EnhanceManipulator.java 2009-10-04 06:54:41 UTC (rev 3697) +++ leto/factory-enhancer/branches/interface-enhancer-20091004/src/main/java/org/jiemamy/utils/enhancer/helper/EnhanceManipulator.java 2009-10-04 06:55:17 UTC (rev 3698) @@ -133,7 +133,7 @@ LOG.debug("Skip delegate constructor: {}{}", base.getName(), constructor.getSignature()); continue; } - if (constructor.getName().charAt(0) == '<') { + if (isClassInitializer(constructor)) { continue; } try { @@ -155,6 +155,16 @@ } /** + * 指定のオブジェクトが、コンストラクタではなくクラス初期化子を表現する場合にのみ{@code true}を返す。 + * @param behavior 対象のコンストラクタまたはクラス初期化子 + * @return 引数がクラス初期化子である場合に{@code true} + */ + private static boolean isClassInitializer(CtConstructor behavior) { + assert behavior != null; + return behavior.getName().charAt(0) == '<'; + } + + /** * {@code method}に指定されたメソッドを呼び出すバイパスメソッドを拡張クラス上に新しく作成して返す。 * <p> * バイパスメソッドは、拡張元のクラスが公開するメソッドを安全に呼び出すための方法を提供する。 @@ -213,7 +223,7 @@ try { CtMethod bypass = new CtMethod(method.getReturnType(), getBypassMethodName(method, index), - method.getParameterTypes(), enhance); + method.getParameterTypes(), enhance); LOG.debug("Bypass method: {}#{}{} -> {}#{}{}", new Object[] { bypass.getDeclaringClass().getName(), Modified: leto/factory-enhancer/branches/interface-enhancer-20091004/src/test/java/org/jiemamy/utils/enhancer/FactoryEnhancerTest.java =================================================================== --- leto/factory-enhancer/branches/interface-enhancer-20091004/src/test/java/org/jiemamy/utils/enhancer/FactoryEnhancerTest.java 2009-10-04 06:54:41 UTC (rev 3697) +++ leto/factory-enhancer/branches/interface-enhancer-20091004/src/test/java/org/jiemamy/utils/enhancer/FactoryEnhancerTest.java 2009-10-04 06:55:17 UTC (rev 3698) @@ -116,12 +116,13 @@ */ @Test(expected = IllegalArgumentException.class) public void testFactoryEnhancer_InterfaceIsAnnotation() throws Exception { - new FactoryEnhancer<Override>(Override.class, new Override() { + Override override = new Override() { public Class<? extends Annotation> annotationType() { return Override.class; } - }.getClass(), enhances()); + }; + new FactoryEnhancer<Override>(Override.class, override.getClass(), enhances()); } /** @@ -154,8 +155,8 @@ Enhance enhance = new Enhance(new StringParameterPointcut(), new BeforeStringInsertHandler("!")); FactoryEnhancer<SingularFactory> enhancer = new FactoryEnhancer<SingularFactory>(SingularFactory.class, SingularFactoryNoPublicProduct.class, - enhance); - SingularFactory factory = enhancer.getEnhanced().newInstance(); + enhance); + SingularFactory factory = enhancer.getFactory().newInstance(); factory.newInstance(); } @@ -237,7 +238,7 @@ assertThat(factory.newProduct1("a").getValue(), is("!a1")); assertThat(factory.newProduct2("b").getValue(), is("!b2")); assertThat(factory.newProduct3("c").getValue(), is("!c3")); - assertThat(factory.newString("s").toString(), is("!s")); + assertThat(factory.newString("s"), is("!s")); } /** @@ -312,7 +313,7 @@ assertThat(factory.newProduct1("a").getValue(), is("a1")); assertThat(factory.newProduct2("b").getValue(), is("b2")); assertThat(factory.newProduct3("c").getValue(), is("c3")); - assertThat(factory.newString("s").toString(), is("s")); + assertThat(factory.newString("s"), is("s")); } /** @@ -336,7 +337,7 @@ public void testGetEnhanced_FinalProductClass() throws Exception { Enhance enhance = new Enhance(and(or(new ClassSuffixPointcut("Product1"), new ClassSuffixPointcut("ProductFinal")), - new StringParameterPointcut()), new BeforeStringInsertHandler("!")); + new StringParameterPointcut()), new BeforeStringInsertHandler("!")); FactoryEnhancer<TargetFactory> enhancer = new FactoryEnhancer<TargetFactory>(TargetFactory.class, TargetFactoryImpl.class, enhance); Class<? extends TargetFactory> enhanced = enhancer.getEnhanced(); @@ -474,7 +475,7 @@ public void testGetEnhanced_ProductMethodArguments() throws Exception { FactoryEnhancer<TargetFactory> enhancer = new FactoryEnhancer<TargetFactory>(TargetFactory.class, TargetFactoryImpl.class, new Enhance( - new StringParameterPointcut(), new BeforeStringInsertHandler("!"))); + new StringParameterPointcut(), new BeforeStringInsertHandler("!"))); Class<? extends TargetFactory> enhanced = enhancer.getEnhanced(); TargetFactory factory = enhanced.newInstance(); TargetProduct1 p1 = factory.newProduct1(); @@ -496,7 +497,7 @@ public void testGetEnhanced_ProductMethodResults() throws Exception { FactoryEnhancer<TargetFactory> enhancer = new FactoryEnhancer<TargetFactory>(TargetFactory.class, TargetFactoryImpl.class, new Enhance( - new StringResultPointcut(), new AfterStringAppendHandler("!"))); + new StringResultPointcut(), new AfterStringAppendHandler("!"))); Class<? extends TargetFactory> enhanced = enhancer.getEnhanced(); TargetFactory factory = enhanced.newInstance(); assertThat(factory.newProduct1("a"), is(p1("a"))); @@ -508,7 +509,7 @@ assertThat(factory.newProduct3("c").getValue(), is("c3!")); // java.lang.String cannot become an enhance target - assertThat(factory.newString("s").toString(), is("s")); + assertThat(factory.newString("s"), is("s")); } /** @@ -532,10 +533,10 @@ public void testGetEnhanced_SelectedMethod() throws Exception { Enhance before = new Enhance(and(new ClassSuffixPointcut("Product2"), new StringParameterPointcut()), - new BeforeStringInsertHandler("!")); + new BeforeStringInsertHandler("!")); Enhance after = new Enhance(and(new ClassSuffixPointcut("Product3"), new StringResultPointcut()), - new AfterStringAppendHandler("!")); + new AfterStringAppendHandler("!")); FactoryEnhancer<TargetFactory> enhancer = new FactoryEnhancer<TargetFactory>(TargetFactory.class, TargetFactoryImpl.class, before, after); Class<? extends TargetFactory> enhanced = enhancer.getEnhanced(); @@ -599,7 +600,7 @@ public void testGetEnhanced_SingleConstructor() throws Exception { Enhance enhance = new Enhance(and(new ClassSuffixPointcut("Product1"), new StringParameterPointcut()), - new BeforeStringInsertHandler("!")); + new BeforeStringInsertHandler("!")); FactoryEnhancer<TargetFactory> enhancer = new FactoryEnhancer<TargetFactory>(TargetFactory.class, TargetFactoryImpl.class, enhance); Class<? extends TargetFactory> enhanced = enhancer.getEnhanced(); @@ -612,7 +613,7 @@ assertThat(factory.newProduct1("a").getValue(), is("!a1")); assertThat(factory.newProduct2("b").getValue(), is("b2")); assertThat(factory.newProduct3("c").getValue(), is("c3")); - assertThat(factory.newString("s").toString(), is("s")); + assertThat(factory.newString("s"), is("s")); } /** @@ -632,7 +633,7 @@ private TargetFactory enhancedProduct1() throws Exception { Enhance enhance = new Enhance(and(new ClassSuffixPointcut("Product1"), new StringResultPointcut()), - new AfterStringAppendHandler("!")); + new AfterStringAppendHandler("!")); FactoryEnhancer<TargetFactory> enhancer = new FactoryEnhancer<TargetFactory>(TargetFactory.class, TargetFactoryImpl.class, enhance); Class<? extends TargetFactory> enhanced = enhancer.getEnhanced();