/*
* 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.aop.interceptors;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInvocation;
import org.seasar.framework.container.ComponentDef;
import org.seasar.framework.container.ComponentNotFoundRuntimeException;
import org.seasar.framework.container.ContainerConstants;
import org.seasar.framework.container.S2Container;
import org.seasar.framework.container.assembler.AbstractBindingTypeDef;
import org.seasar.framework.container.util.BindingUtil;
import org.seasar.framework.message.MessageFormatter;
import org.seasar.framework.util.StringUtil;
/**
* getterメソッドに適用されて、S2コンテナからルックアップしたコンポーネントを返すインターセプタです。
*
* @author koichik
* @see AbstractBindingTypeDef
*/
public class DependencyLookupInterceptor extends AbstractInterceptor {
private static final long serialVersionUID = 1L;
public Object invoke(final MethodInvocation invocation) throws Throwable {
final Method method = invocation.getMethod();
final String methodName = method.getName();
final Class propType = method.getReturnType();
if (!methodName.startsWith("get")
|| method.getParameterTypes().length != 0 || propType == null) {
throw new IllegalStateException(MessageFormatter.getSimpleMessage(
"ESSR0103", new Object[] { method }));
}
final S2Container container = getComponentDef(invocation)
.getContainer();
final String propName = StringUtil
.decapitalize(methodName.substring(3));
// Seasar2.4の型による自動バインディング相当のルックアップ
if (container.hasComponentDef(propType)) {
final ComponentDef cd = container.getComponentDef(propType);
if (isAutoBindable(propName, propType, cd)) {
return cd.getComponent();
}
}
// 名前による自動バインディング相当のルックアップ
if (container.hasComponentDef(propName)) {
final ComponentDef cd = container.getComponentDef(propName);
final Object component = cd.getComponent();
if (propType.isInstance(component)) {
return component;
}
}
// 型による自動バインディング相当のルックアップ
if (BindingUtil.isAutoBindable(propType)) {
if (container.hasComponentDef(propType)) {
final ComponentDef cd = container.getComponentDef(propType);
return cd.getComponent();
}
}
// 配列の要素型による自動バインディング相当のルックアップ
if (BindingUtil.isAutoBindableArray(propType)) {
Class clazz = propType.getComponentType();
Object[] components = container.findAllComponents(clazz);
if (components.length > 0) {
return components;
}
}
throw new ComponentNotFoundRuntimeException(propName);
}
/**
* プロパティにコンポーネントを自動バインディング可能なら<code>true</code>を返します。
*
* @param propertyName
* プロパティ名
* @param propertyType
* プロパティの型
* @param cd
* コンポーネント定義
* @return プロパティにコンポーネントを自動バインディング可能なら<code>true</code>
*/
protected boolean isAutoBindable(final String propertyName,
final Class propertyType, final ComponentDef cd) {
return cd.getComponentName() != null
&& (cd.getComponentName().equalsIgnoreCase(propertyName) || StringUtil
.endsWithIgnoreCase(cd.getComponentName(),
ContainerConstants.PACKAGE_SEP + propertyName));
}
}