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.ArrayList;
    20  import java.util.List;
    21
    22  import org.seasar.cubby.plugins.s2.detector.ClassDetector;
    23  import org.seasar.cubby.plugins.s2.detector.DetectClassProcessor;
    24  import org.seasar.cubby.routing.PathResolver;
    25  import org.seasar.cubby.spi.PathResolverProvider;
    26  import org.seasar.cubby.util.ActionUtils;
    27  import org.seasar.framework.convention.NamingConvention;
    28  import org.seasar.framework.util.ClassUtil;
    29  import org.seasar.framework.util.Disposable;
    30  import org.seasar.framework.util.DisposableUtil;
    31
    32  /**
    33   * S2Container 向けの {@link PathResolver} のプロバイダです。
    34   * <p>
    35   * クラスパスを走査しアクションクラスを登録します。
    36   * </p>
    37   *
    38   * @author baba
    39   */
    40  public class S2PathResolverProvider implements PathResolverProvider,
    41  		DetectClassProcessor, Disposable {
    42
    43  	public static final String pathResolver_BINDING = "bindingType=must";
    44
    45  	public static final String namingConvention_BINDING = "bindingType=must";
    46
    47  	public static final String classDetector_BINDING = "bindingType=must";
    48
    49  	/** パスに対応するアクションメソッドを解決するためのクラス。 */
    50  	private PathResolver pathResolver;
    51
    52  	/** 命名規約。 */
    53  	private NamingConvention namingConvention;
    54
    55  	/** クラスパスを走査してクラスを検出するクラス。 */
    56  	public ClassDetector classDetector;
    57
    58  	/** インスタンスが初期化済みであることを示します。 */
    59  	private boolean initialized;
    60
    61  	/** アクションクラスのリスト。 */
    62  	private final List<Class<?>> actionClasses = new ArrayList<Class<?>>();
    63
    64  	/**
    65  	 * パスに対応するアクションメソッドを解決するためのクラスを設定します。
    66  	 *
    67  	 * @param pathResolver
    68  	 *            パスに対応するアクションメソッドを解決するためのクラス
    69  	 *
    70  	 */
    71  	public void setPathResolver(final PathResolver pathResolver) {
    72  		this.pathResolver = pathResolver;
    73  	}
    74
    75  	/**
    76  	 * クラスパスを走査してクラスを検出するクラスを設定します。
    77  	 *
    78  	 * @param classDetector
    79  	 *            クラスパスを走査してクラスを検出するクラス
    80  	 */
    81  	public void setClassDetector(final ClassDetector classDetector) {
    82  		this.classDetector = classDetector;
    83  	}
    84
    85  	/**
    86  	 * 命名規約を設定します。
    87  	 *
    88  	 * @param namingConvention
    89  	 *            命名規約
    90  	 */
    91  	public void setNamingConvention(final NamingConvention namingConvention) {
    92  		this.namingConvention = namingConvention;
    93  	}
    94
    95  	/**
    96  	 * 初期化します。
    97  	 */
    98  	public void initialize() {
    99  		if (initialized) {
    100 			return;
    101 		}
    102 		classDetector.detect();
    103 		pathResolver.addAll(actionClasses);
    104
    105 		DisposableUtil.add(this);
    106 		initialized = true;
    107 	}
    108
    109 	/**
    110 	 * {@inheritDoc}
    111 	 */
    112 	public void dispose() {
    113 		actionClasses.clear();
    114 		pathResolver.clear();
    115 		initialized = false;
    116 	}
    117
    118 	/**
    119 	 * {@inheritDoc}
    120 	 * <p>
    121 	 * 指定されたパッケージ名、クラス名から導出されるクラスがアクションクラスだった場合はルーティングを登録します。
    122 	 * </p>
    123 	 */
    124 	public void processClass(final String packageName,
    125 			final String shortClassName) {
    126 		if (shortClassName.indexOf('$') != -1) {
    127 			return;
    128 		}
    129 		final String className = ClassUtil.concatName(packageName,
    130 				shortClassName);
    131 		if (!namingConvention.isTargetClassName(className)) {
    132 			return;
    133 		}
    134 		if (!className.endsWith(namingConvention.getActionSuffix())) {
    135 			return;
    136 		}
    137 		final Class<?> clazz = ClassUtil.forName(className);
    138 		if (namingConvention.isSkipClass(clazz)) {
    139 			return;
    140 		}
    141 		if (Modifier.isAbstract(clazz.getModifiers())) {
    142 			return;
    143 		}
    144 		if (!ActionUtils.isActionClass(clazz)) {
    145 			return;
    146 		}
    147 		actionClasses.add(clazz);
    148 	}
    149
    150 	/**
    151 	 * {@inheritDoc}
    152 	 */
    153 	public PathResolver getPathResolver() {
    154 		initialize();
    155 		return pathResolver;
    156 	}
    157
    158 }