/* * 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.container.factory; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.seasar.framework.aop.annotation.Interceptor; import org.seasar.framework.beans.BeanDesc; import org.seasar.framework.beans.PropertyDesc; import org.seasar.framework.container.AutoBindingDef; import org.seasar.framework.container.ComponentDef; import org.seasar.framework.container.InstanceDef; import org.seasar.framework.container.PropertyDef; import org.seasar.framework.container.factory.aspect.AspectAnnotationAspectDefBuilder; import org.seasar.framework.container.factory.aspect.EJB3AnnotationAspectDefBuilder; import org.seasar.framework.container.factory.aspect.MetaAnnotationAspectDefBuilder; import org.seasar.framework.container.factory.component.EJB3ComponentDefBuilder; import org.seasar.framework.container.factory.component.PojoComponentDefBuilder; import org.seasar.framework.container.factory.destroymethod.S2DestroyMethodDefBuilder; import org.seasar.framework.container.factory.initmethod.EJB3InitMethodDefBuilder; import org.seasar.framework.container.factory.initmethod.S2InitMethodDefBuilder; import org.seasar.framework.container.factory.intertype.EJB3IntertypeDefBuilder; import org.seasar.framework.container.factory.intertype.S2IntertypeDefBuilder; import org.seasar.framework.container.factory.property.BindingPropertyDefBuilder; import org.seasar.framework.container.factory.property.EJBPropertyDefBuilder; import org.seasar.framework.container.factory.property.PersistenceContextPropertyDefBuilder; import org.seasar.framework.container.factory.property.PersistenceUnitPropertyDefBuilder; import org.seasar.framework.container.factory.property.ResourcePropertyDefBuilder; import org.seasar.framework.util.Disposable; import org.seasar.framework.util.DisposableUtil; /** * クラスに指定されたTigerアノテーションからコンポーネント定義を作成する実装クラスです。 * * @author higa */ public class TigerAnnotationHandler extends ConstantAnnotationHandler { /** イニシャライズ済みなら<code>true</code> */ protected static boolean initialized; /** EJB3が有効なら<code>true</code> */ protected static final boolean enableEJB3; static { boolean enable = false; try { Class.forName("javax.ejb.Stateless"); // geronimo-ejb_3.0_spec-1.0.jar Class.forName("javax.interceptor.Interceptors"); // geronimo-interceptor_3.0_spec-1.0.jar enable = true; } catch (final Throwable ignore) { } enableEJB3 = enable; } /** JPAが有効なら<code>true</code> */ protected static final boolean enableJPA; static { boolean enable = false; try { Class.forName("javax.persistence.PersistenceContext"); // geronimo-jpa_3.0_spec-1.0.jar enable = true; } catch (final Throwable ignore) { } enableJPA = enable; } /** Common Annotationsが有効なら<code>true</code> */ protected static final boolean enableCommonAnnotations; static { boolean enable = false; try { Class.forName("javax.annotation.Resource"); // geronimo-annotation_1.0_spec-1.0.jar enable = true; } catch (final Throwable ignore) { } enableCommonAnnotations = enable; } /** {@link ComponentDefBuilder}の配列 */ protected static final List<ComponentDefBuilder> componentDefBuilders = Collections .synchronizedList(new ArrayList<ComponentDefBuilder>()); /** {@link PropertyDefBuilder}の配列 */ protected static final List<PropertyDefBuilder> propertyDefBuilders = Collections .synchronizedList(new ArrayList<PropertyDefBuilder>()); /** {@link AspectDefBuilder}の配列 */ protected static final List<AspectDefBuilder> aspectDefBuilders = Collections .synchronizedList(new ArrayList<AspectDefBuilder>()); /** {@link IntertypeDefBuilder}の配列 */ protected static final List<IntertypeDefBuilder> intertypeDefBuilders = Collections .synchronizedList(new ArrayList<IntertypeDefBuilder>()); /** {@link InitMethodDefBuilder}の配列 */ protected static final List<InitMethodDefBuilder> initMethodDefBuilders = Collections .synchronizedList(new ArrayList<InitMethodDefBuilder>()); /** {@link DestroyMethodDefBuilder}の配列 */ protected static final List<DestroyMethodDefBuilder> destroyMethodDefBuilders = Collections .synchronizedList(new ArrayList<DestroyMethodDefBuilder>()); static { initialize(); } /** * インスタンスの状態を初期化します。 */ public static void initialize() { if (initialized) { return; } loadDefaultComponentDefBuilder(); loadDefaultPropertyDefBuilder(); loadDefaultAspectDefBuilder(); loadDefaultIntertypeDefBuilder(); loadDefaultInitMethodDefBuilder(); loadDefaultDestroyMethodDefBuilder(); DisposableUtil.add(new Disposable() { public void dispose() { TigerAnnotationHandler.dispose(); } }); initialized = true; } /** * インスタンスの状態を破棄します。 */ public static void dispose() { clearComponentDefBuilder(); clearPropertyDefBuilder(); clearAspectDefBuilder(); clearIntertypeDefBuilder(); clearInitMethodDefBuilder(); clearDestroyMethodDefBuilder(); initialized = false; } /** * デフォルトの{@link ComponentDefBuilder}を追加します。 */ public static void loadDefaultComponentDefBuilder() { if (enableEJB3) { componentDefBuilders.add(new EJB3ComponentDefBuilder()); } componentDefBuilders.add(new PojoComponentDefBuilder()); } /** * {@link ComponentDefBuilder}を追加します。 * * @param builder * {@link ComponentDefBuilder} */ public static void addComponentDefBuilder(final ComponentDefBuilder builder) { componentDefBuilders.add(builder); } /** * {@link ComponentDefBuilder}を削除します。 * * @param builder * {@link ComponentDefBuilder} */ public static void removeComponentDefBuilder( final ComponentDefBuilder builder) { componentDefBuilders.remove(builder); } /** * {@link ComponentDefBuilder}をクリアします。 */ public static void clearComponentDefBuilder() { componentDefBuilders.clear(); } /** * デフォルトの{@link PropertyDefBuilder}を追加します。 */ public static void loadDefaultPropertyDefBuilder() { clearPropertyDefBuilder(); propertyDefBuilders.add(new BindingPropertyDefBuilder()); if (enableEJB3) { propertyDefBuilders.add(new EJBPropertyDefBuilder()); } if (enableJPA) { propertyDefBuilders.add(new PersistenceContextPropertyDefBuilder()); propertyDefBuilders.add(new PersistenceUnitPropertyDefBuilder()); } if (enableCommonAnnotations) { propertyDefBuilders.add(new ResourcePropertyDefBuilder()); } } /** * {@link PropertyDefBuilder}を追加します。 * * @param builder * {@link PropertyDefBuilder} */ public static void addPropertyDefBuilder(final PropertyDefBuilder builder) { propertyDefBuilders.add(builder); } /** * {@link PropertyDefBuilder}を削除します。 * * @param builder * {@link PropertyDefBuilder} */ public static void removePropertyDefBuilder(final PropertyDefBuilder builder) { propertyDefBuilders.remove(builder); } /** * {@link PropertyDefBuilder}をクリアします。 */ public static void clearPropertyDefBuilder() { propertyDefBuilders.clear(); } /** * デフォルトの{@link AspectDefBuilder}を追加します。 */ public static void loadDefaultAspectDefBuilder() { if (enableEJB3) { aspectDefBuilders.add(new EJB3AnnotationAspectDefBuilder()); } aspectDefBuilders.add(new AspectAnnotationAspectDefBuilder()); aspectDefBuilders.add(new MetaAnnotationAspectDefBuilder( Interceptor.class, "Interceptor")); } /** * {@link AspectDefBuilder}を追加します。 * * @param builder * {@link AspectDefBuilder} */ public static void addAspectDefBuilder(final AspectDefBuilder builder) { aspectDefBuilders.add(builder); } /** * {@link AspectDefBuilder}を削除します。 * * @param builder * {@link AspectDefBuilder} */ public static void removeAspectDefBuilder(final AspectDefBuilder builder) { aspectDefBuilders.remove(builder); } /** * {@link AspectDefBuilder}をクリアします。 */ public static void clearAspectDefBuilder() { aspectDefBuilders.clear(); } /** * デフォルトの{@link IntertypeDefBuilder}を追加します。 */ public static void loadDefaultIntertypeDefBuilder() { if (enableEJB3) { intertypeDefBuilders.add(new EJB3IntertypeDefBuilder()); } intertypeDefBuilders.add(new S2IntertypeDefBuilder()); } /** * {@link IntertypeDefBuilder}を追加します。 * * @param builder * {@link IntertypeDefBuilder} */ public static void addIntertypeDefBuilder(final IntertypeDefBuilder builder) { intertypeDefBuilders.add(builder); } /** * {@link IntertypeDefBuilder}を削除します。 * * @param builder * {@link IntertypeDefBuilder} */ public static void removeIntertypeDefBuilder( final IntertypeDefBuilder builder) { intertypeDefBuilders.remove(builder); } /** * {@link IntertypeDefBuilder}をクリアします。 */ public static void clearIntertypeDefBuilder() { intertypeDefBuilders.clear(); } /** * デフォルトの{@link InitMethodDefBuilder}を追加します。 */ public static void loadDefaultInitMethodDefBuilder() { if (enableEJB3) { initMethodDefBuilders.add(new EJB3InitMethodDefBuilder()); } initMethodDefBuilders.add(new S2InitMethodDefBuilder()); } /** * {@link InitMethodDefBuilder}を追加します。 * * @param builder * {@link InitMethodDefBuilder} */ public static void addInitMethodDefBuilder( final InitMethodDefBuilder builder) { initMethodDefBuilders.add(builder); } /** * {@link InitMethodDefBuilder}を削除します。 * * @param builder * {@link InitMethodDefBuilder} */ public static void removeInitMethodDefBuilder( final InitMethodDefBuilder builder) { initMethodDefBuilders.remove(builder); } /** * {@link InitMethodDefBuilder}をクリアします。 */ public static void clearInitMethodDefBuilder() { initMethodDefBuilders.clear(); } /** * デフォルトの{@link DestroyMethodDefBuilder}を追加します。 */ public static void loadDefaultDestroyMethodDefBuilder() { destroyMethodDefBuilders.add(new S2DestroyMethodDefBuilder()); } /** * {@link DestroyMethodDefBuilder}を追加します。 * * @param builder * {@link DestroyMethodDefBuilder} */ public static void addDestroyMethodDefBuilder( final DestroyMethodDefBuilder builder) { destroyMethodDefBuilders.add(builder); } /** * {@link DestroyMethodDefBuilder}を削除します。 * * @param builder * {@link DestroyMethodDefBuilder} */ public static void removeDestroyMethodDefBuilder( final DestroyMethodDefBuilder builder) { destroyMethodDefBuilders.remove(builder); } /** * {@link DestroyMethodDefBuilder}をクリアします。 */ public static void clearDestroyMethodDefBuilder() { destroyMethodDefBuilders.clear(); } @SuppressWarnings("unchecked") @Override public ComponentDef createComponentDef(final Class componentClass, final InstanceDef defaultInstanceDef, final AutoBindingDef defaultAutoBindingDef, final boolean defaultExternalBinding) { initialize(); for (final ComponentDefBuilder builder : componentDefBuilders) { final ComponentDef componentDef = builder.createComponentDef(this, componentClass, defaultInstanceDef, defaultAutoBindingDef, defaultExternalBinding); if (componentDef != null) { return componentDef; } } return super.createComponentDef(componentClass, defaultInstanceDef, defaultAutoBindingDef, defaultExternalBinding); } @Override public PropertyDef createPropertyDef(final BeanDesc beanDesc, PropertyDesc propertyDesc) { if (propertyDesc.isWritable()) { for (final PropertyDefBuilder builder : propertyDefBuilders) { final PropertyDef propertyDef = builder.createPropertyDef(this, beanDesc, propertyDesc); if (propertyDef != null) { return propertyDef; } } } return super.createPropertyDef(beanDesc, propertyDesc); } @Override public PropertyDef createPropertyDef(final BeanDesc beanDesc, final Field field) { for (final PropertyDefBuilder builder : propertyDefBuilders) { final PropertyDef propertyDef = builder.createPropertyDef(this, beanDesc, field); if (propertyDef != null) { return propertyDef; } } return super.createPropertyDef(beanDesc, field); } @Override public void appendAspect(final ComponentDef componentDef) { for (final AspectDefBuilder builder : aspectDefBuilders) { builder.appendAspectDef(this, componentDef); } super.appendAspect(componentDef); } @Override public void appendInterType(final ComponentDef componentDef) { for (final IntertypeDefBuilder builder : intertypeDefBuilders) { builder.appendIntertypeDef(this, componentDef); } super.appendInterType(componentDef); } @Override public void appendInitMethod(final ComponentDef componentDef) { Class<?> componentClass = componentDef.getComponentClass(); if (componentClass == null) { return; } for (final InitMethodDefBuilder builder : initMethodDefBuilders) { builder.appendInitMethodDef(this, componentDef); } super.appendInitMethod(componentDef); } @Override public void appendDestroyMethod(final ComponentDef componentDef) { Class<?> componentClass = componentDef.getComponentClass(); if (componentClass == null) { return; } for (final DestroyMethodDefBuilder builder : destroyMethodDefBuilders) { builder.appendDestroyMethodDef(this, componentDef); } super.appendDestroyMethod(componentDef); } }