All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.hasor.mvc.support.MappingDefine Maven / Gradle / Ivy

There is a newer version: 0.0.5
Show newest version
/*
 * Copyright 2008-2009 the original 赵永春([email protected]).
 *
 * 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 net.hasor.mvc.support;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.hasor.core.AppContext;
import net.hasor.core.BindInfo;
import net.hasor.core.Hasor;
import net.hasor.core.Provider;
import net.hasor.mvc.Call;
import net.hasor.mvc.CallStrategy;
import net.hasor.mvc.MappingInfo;
import net.hasor.mvc.ModelController;
import net.hasor.mvc.api.HttpMethod;
import net.hasor.mvc.api.MappingTo;
import org.more.UndefinedException;
import org.more.builder.ReflectionToStringBuilder;
import org.more.builder.ToStringStyle;
import org.more.util.StringUtils;
/**
 * 线程安全
 * @version : 2013-6-5
 * @author 赵永春 ([email protected])
 */
class MappingDefine implements MappingInfo {
    private String                    bindID;
    private Provider targetProvider;
    private Method                    targetMethod;
    private Class[]                targetParamTypes;
    private Annotation[][]            targetParamAnno;
    private Annotation[]              targetMethodAnno;
    private String                    mappingTo;
    private String                    mappingToMatches;
    private String[]                  httpMethod;
    private CallStrategy              callStrategy;
    private AtomicBoolean             inited = new AtomicBoolean(false);
    //
    protected MappingDefine(String bindID, Method targetMethod) {
        MappingTo pathAnno = targetMethod.getAnnotation(MappingTo.class);
        if (pathAnno == null) {
            throw new UndefinedException("is not a valid Mapping Service.");
        }
        String servicePath = pathAnno.value();
        if (StringUtils.isBlank(servicePath)) {
            throw new NullPointerException("Service path is empty.");
        }
        if (!servicePath.matches("/.+")) {
            throw new IllegalStateException("Service path format error");
        }
        //
        this.bindID = bindID;
        this.targetMethod = targetMethod;
        this.targetParamTypes = targetMethod.getParameterTypes();
        this.targetParamAnno = targetMethod.getParameterAnnotations();
        this.targetMethodAnno = targetMethod.getAnnotations();
        this.mappingTo = servicePath;
        this.mappingToMatches = servicePath.replaceAll("\\{\\w{1,}\\}", "([^/]{1,})");
        //
        /*HttpMethod*/
        Annotation[] annos = targetMethod.getAnnotations();
        ArrayList allHttpMethod = new ArrayList();
        if (annos != null) {
            for (Annotation anno : annos) {
                HttpMethod httpMethodAnno = anno.annotationType().getAnnotation(HttpMethod.class);
                if (httpMethodAnno != null) {
                    String bindMethod = httpMethodAnno.value();
                    if (StringUtils.isBlank(bindMethod) == false)
                        allHttpMethod.add(bindMethod);
                }
            }
        }
        if (allHttpMethod.isEmpty())
            allHttpMethod.add("ANY");
        this.httpMethod = allHttpMethod.toArray(new String[allHttpMethod.size()]);
    }
    /**@return 获取映射的地址*/
    public String getMappingTo() {
        return this.mappingTo;
    }
    public String getMappingToMatches() {
        return this.mappingToMatches;
    }
    /**
     * 测试路径是否匹配
     * @param requestPath 要测试的路径。
     * @return 返回测试结果。
     */
    public boolean matchingMapping(String requestPath) {
        Hasor.assertIsNotNull(requestPath, "requestPath is null.");
        return requestPath.matches(this.mappingToMatches);
    }
    public String[] getHttpMethod() {
        return this.httpMethod;
    }
    /**判断Restful实例是否支持这个 请求方法。*/
    public boolean matchingMethod(String httpMethod) {
        for (String m : this.httpMethod) {
            if (StringUtils.equalsIgnoreCase(httpMethod, m)) {
                return true;
            } else if (StringUtils.equalsIgnoreCase(m, "ANY")) {
                return true;
            }
        }
        return false;
    }
    //
    //
    //
    /**
     * 执行初始化
     * @param appContext appContext
     */
    protected void init(AppContext appContext) {
        if (!this.inited.compareAndSet(false, true)) {
            return;/*避免被初始化多次*/
        }
        Hasor.assertIsNotNull(appContext, "appContext is null.");
        BindInfo controllerInfo = appContext.getBindInfo(this.bindID);
        this.targetProvider = appContext.getProvider(controllerInfo);
    }
    /**
     * 调用目标
     * @param call 执行策略
     * @param params 执行控制器时用到的参数。
     * @return 返回调用结果
     * @throws Throwable 异常抛出
     */
    public final Object invoke(final HttpInfo httpInfo, CallStrategy callStrategy, Map params) throws Throwable {
        Hasor.assertIsNotNull(callStrategy);
        final ModelController mc = this.targetProvider.get();
        final Map atParams = (params == null) ? new HashMap() : params;
        final Call call = new Call() {
            public Set getParamKeys() {
                return atParams.keySet();
            }
            public Object getParam(String key) {
                return atParams.get(key);
            }
            public Method getMethod() {
                return targetMethod;
            }
            public Class[] getParameterTypes() {
                return targetParamTypes;
            }
            public Annotation[][] getMethodParamAnnos() {
                return targetParamAnno;
            }
            public Annotation[] getAnnotations() {
                return targetMethodAnno;
            }
            public ModelController getTarget() {
                return mc;
            }
            public MappingInfo getMappingInfo() {
                return MappingDefine.this;
            }
            public Object call(Object... objects) throws Throwable {
                try {
                    return targetMethod.invoke(mc, objects);
                } catch (InvocationTargetException e) {
                    throw e.getTargetException();
                }
            }
            public HttpServletRequest getHttpRequest() {
                return httpInfo.getHttpRequest();
            }
            public HttpServletResponse getHttpResponse() {
                return httpInfo.getHttpResponse();
            }
        };
        //
        return callStrategy.exeCall(call);
    }
    public String toString() {
        return ReflectionToStringBuilder.toString(this, ToStringStyle.SHORT_PREFIX_STYLE);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy