View Javadoc

    1   /*
    2    * Copyright 2004-2009 the Seasar Foundation and the Others.
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
    13   * either express or implied. See the License for the specific language
    14   * governing permissions and limitations under the License.
    15   */
    16  package org.seasar.cubby.plugins.s2.spi;
    17
    18  import java.lang.reflect.Modifier;
    19  import java.util.Arrays;
    20  import java.util.Collection;
    21  import java.util.LinkedHashSet;
    22  import java.util.Set;
    23
    24  import org.seasar.cubby.converter.Converter;
    25  import org.seasar.cubby.plugins.s2.detector.ClassDetector;
    26  import org.seasar.cubby.plugins.s2.detector.DetectClassProcessor;
    27  import org.seasar.cubby.spi.impl.AbstractCachedConverterProvider;
    28  import org.seasar.framework.container.S2Container;
    29  import org.seasar.framework.convention.NamingConvention;
    30  import org.seasar.framework.util.ClassUtil;
    31  import org.seasar.framework.util.Disposable;
    32  import org.seasar.framework.util.DisposableUtil;
    33
    34  /**
    35   * S2Container 向けの {@link Converter} のプロバイダです。
    36   *
    37   * @author baba
    38   */
    39  public class S2ConverterProvider extends AbstractCachedConverterProvider
    40  		implements DetectClassProcessor, Disposable {
    41
    42  	public static final String s2Container_BINDING = "bindingType=must";
    43
    44  	public static final String namingConvention_BINDING = "bindingType=must";
    45
    46  	public static final String classDetector_BINDING = "bindingType=must";
    47
    48  	/** S2 コンテナ。 */
    49  	private S2Container s2Container;
    50
    51  	/** 命名規約。 */
    52  	private NamingConvention namingConvention;
    53
    54  	/** クラスパスを走査してクラスを検出するクラス。 */
    55  	private ClassDetector classDetector;
    56
    57  	/** インスタンスが初期化済みであることを示します。 */
    58  	private boolean initialized;
    59
    60  	/** コンバータのセットです。 */
    61  	private final Set<Converter> converters = new LinkedHashSet<Converter>();
    62
    63  	/**
    64  	 * S2 コンテナを設定します。
    65  	 *
    66  	 * @param s2Container
    67  	 *            S2 コンテナ
    68  	 */
    69  	public void setS2Container(final S2Container s2Container) {
    70  		this.s2Container = s2Container;
    71  	}
    72
    73  	/**
    74  	 * 命名規約を設定します。
    75  	 *
    76  	 * @param namingConvention
    77  	 *            命名規約
    78  	 */
    79  	public void setNamingConvention(final NamingConvention namingConvention) {
    80  		this.namingConvention = namingConvention;
    81  	}
    82
    83  	/**
    84  	 * クラスパスを走査してクラスを検出するクラスを設定します。
    85  	 *
    86  	 * @param classDetector
    87  	 *            クラスパスを走査してクラスを設定します。
    88  	 */
    89  	public void setClassDetector(final ClassDetector classDetector) {
    90  		this.classDetector = classDetector;
    91  	}
    92
    93  	@Override
    94  	protected Collection<Converter> getConverters() {
    95  		return converters;
    96  	}
    97
    98  	/**
    99  	 * インスタンスを初期化します。
    100 	 */
    101 	public void initialize() {
    102 		if (initialized) {
    103 			return;
    104 		}
    105 		classDetector.detect();
    106
    107 		final Converter[] converters = (Converter[]) s2Container.getRoot()
    108 				.findAllComponents(Converter.class);
    109 		this.converters.addAll(Arrays.asList(converters));
    110 		DisposableUtil.add(this);
    111 		initialized = true;
    112 	}
    113
    114 	/**
    115 	 * キャッシュ情報等を破棄し、インスタンスを未初期化状態に戻します。
    116 	 *
    117 	 */
    118 	public void dispose() {
    119 		this.converters.clear();
    120 		super.clear();
    121 		initialized = false;
    122 	}
    123
    124 	/**
    125 	 * {@inheritDoc}
    126 	 */
    127 	@Override
    128 	public Converter getConverter(final Class<?> parameterType,
    129 			final Class<?> objectType) {
    130 		initialize();
    131 		return super.getConverter(parameterType, objectType);
    132 	}
    133
    134 	/**
    135 	 * {@inheritDoc}
    136 	 * <p>
    137 	 * 指定されたパッケージ名、クラス名から導出されるクラスがコンバータだった場合はファクトリにコンバータを登録します。
    138 	 * </p>
    139 	 */
    140 	public void processClass(final String packageName,
    141 			final String shortClassName) {
    142 		if (shortClassName.indexOf('$') != -1) {
    143 			return;
    144 		}
    145 		final String className = ClassUtil.concatName(packageName,
    146 				shortClassName);
    147 		if (!namingConvention.isTargetClassName(className)) {
    148 			return;
    149 		}
    150 		if (!className.endsWith(namingConvention.getConverterSuffix())) {
    151 			return;
    152 		}
    153 		final Class<?> clazz = ClassUtil.forName(className);
    154 		if (namingConvention.isSkipClass(clazz)) {
    155 			return;
    156 		}
    157 		if ((clazz.getModifiers() & Modifier.ABSTRACT) != 0) {
    158 			return;
    159 		}
    160 		if (!Converter.class.isAssignableFrom(clazz)) {
    161 			return;
    162 		}
    163 		final Converter converter = (Converter) s2Container.getRoot()
    164 				.getComponent(clazz);
    165 		this.converters.add(converter);
    166 	}
    167
    168 }