/* * Copyright 2007-2009 the original author or authors. * * 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.paoding.rose.web.impl.mapping; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import net.paoding.rose.web.annotation.ReqMethod; import net.paoding.rose.web.impl.thread.Engine; import net.paoding.rose.web.impl.thread.LinkedEngine; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * * * @author 王志亮 [qieqie.wang@gmail.com] * */ public class EngineGroupImpl implements EngineGroup { private static final Log logger = LogFactory.getLog(EngineGroup.class); /** ARRAY_SIZE 代表用于存放 Engine 的数组的大小 */ private static final int ARRAY_SIZE = ReqMethod.ALL.parse().size(); private static final LinkedEngine[] emptyEngines = new LinkedEngine[0]; /** * 该资源支持的操作逻辑,如果不支持某种操作对应位置的元素为长度为0的engines数组 * <p> * 处理指定http method的逻辑存放于该本数组的指定的、唯一位置,即 {@link ReqMethod#ordinal()} * */ private final LinkedEngine[][] engines; private int engineCount; private transient String toStringCache; private transient List<ReqMethod> allowedMethodsCache; //----------------------------------- /** * @param simpleName 资源相对于上级的资源的名称 */ public EngineGroupImpl() { LinkedEngine[][] engines = new LinkedEngine[ARRAY_SIZE][]; Arrays.fill(engines, emptyEngines); this.engines = engines; } /** * 添加一个 {@link Engine} ;如果所给的 method 是 {@link ReqMethod#ALL},则优先级最低。 * * @param method * @param engine */ public void addEngine(ReqMethod method, LinkedEngine engine) { for (ReqMethod md : method.parse()) { LinkedEngine[] methodEngines = engines[md.ordinal()]; if (methodEngines.length == 0) { methodEngines = new LinkedEngine[] { engine }; } else { methodEngines = Arrays.copyOf(methodEngines, methodEngines.length + 1); methodEngines[methodEngines.length - 1] = engine; } engines[md.ordinal()] = methodEngines; engineCount++; } clearCache(); } @Override public int size() { return engineCount; } /** * 返回处理这个资源的处理逻辑,如果该资源不支持该操作方法返回长度为0的数组。 * * @param method 除 {@link ReqMethod#ALL} 外的其他 {@link ReqMethod} * 实例;可以为null * @return */ @Override public LinkedEngine[] getEngines(ReqMethod method) { if (method == null) { return emptyEngines; } if (method == ReqMethod.ALL) { throw new IllegalArgumentException("method"); } return engines[method.ordinal()]; } /** * 本资源是否支持此操作? * * @param method * @return */ public boolean isMethodAllowed(ReqMethod method) { return method != null && engines[method.ordinal()].length > 0; } public List<ReqMethod> getAllowedMethods() { if (allowedMethodsCache == null) { List<ReqMethod> allowedMethods = new ArrayList<ReqMethod>(); for (ReqMethod method : ReqMethod.ALL.parse()) { Engine[] methodEngines = this.engines[method.ordinal()]; if (methodEngines.length > 0) { allowedMethods.add(method); } } allowedMethodsCache = Collections.unmodifiableList(allowedMethods); } return allowedMethodsCache; } private boolean destroyed = false; /** * 销毁该资源 */ public void destroy() { if (!destroyed) { return; } destroyed = true; for (Engine[] methodEngines : engines) { for (Engine engine : methodEngines) { try { engine.destroy(); } catch (Throwable e) { logger.error("", e); } } } } @Override public String toString() { if (this.toStringCache == null) { StringBuilder sb = new StringBuilder(); sb.append("["); int oriLen = sb.length(); for (ReqMethod method : getAllowedMethods()) { sb.append(method.toString()).append(", "); } if (sb.length() > oriLen) { sb.setLength(sb.length() - 2); } sb.append("]"); this.toStringCache = sb.toString(); } return this.toStringCache; } private void clearCache() { allowedMethodsCache = null; toStringCache = null; } }