/* * Copyright 2009-2016 Weibo, Inc. * * 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 com.weibo.api.motan.protocol.support; import java.util.ArrayList; import java.util.Collections; import java.util.List; import org.apache.commons.lang3.StringUtils; import com.weibo.api.motan.common.MotanConstants; import com.weibo.api.motan.common.URLParamType; import com.weibo.api.motan.core.extension.Activation; import com.weibo.api.motan.core.extension.ActivationComparator; import com.weibo.api.motan.core.extension.ExtensionLoader; import com.weibo.api.motan.core.extension.SpiMeta; import com.weibo.api.motan.exception.MotanErrorMsgConstant; import com.weibo.api.motan.exception.MotanFrameworkException; import com.weibo.api.motan.filter.AccessLogFilter; import com.weibo.api.motan.filter.Filter; import com.weibo.api.motan.rpc.Exporter; import com.weibo.api.motan.rpc.Protocol; import com.weibo.api.motan.rpc.Provider; import com.weibo.api.motan.rpc.Referer; import com.weibo.api.motan.rpc.Request; import com.weibo.api.motan.rpc.Response; import com.weibo.api.motan.rpc.URL; /** * * Decorate the protocol, to add more features. * * @author fishermen * @version V1.0 created at: 2013-5-30 */ public class ProtocolFilterDecorator implements Protocol { private Protocol protocol; public ProtocolFilterDecorator(Protocol protocol) { if (protocol == null) { throw new MotanFrameworkException("Protocol is null when construct ProtocolFilterDecorator", MotanErrorMsgConstant.FRAMEWORK_INIT_ERROR); } this.protocol = protocol; } @Override public <T> Exporter<T> export(Provider<T> provider, URL url) { return protocol.export(decorateWithFilter(provider, url), url); } @Override public <T> Referer<T> refer(Class<T> clz, URL url, URL serviceUrl) { return decorateWithFilter(protocol.refer(clz, url, serviceUrl), url); } public void destroy() { protocol.destroy(); } private <T> Referer<T> decorateWithFilter(Referer<T> referer, URL url) { List<Filter> filters = getFilters(url, MotanConstants.NODE_TYPE_REFERER); Referer<T> lastRef = referer; for (Filter filter : filters) { final Filter f = filter; final Referer<T> lf = lastRef; lastRef = new Referer<T>() { @Override public Response call(Request request) { Activation activation = f.getClass().getAnnotation(Activation.class); if (activation != null && !activation.retry() && request.getRetries() != 0) { return lf.call(request); } return f.filter(lf, request); } @Override public String desc() { return lf.desc(); } @Override public void destroy() { lf.destroy(); } @Override public Class<T> getInterface() { return lf.getInterface(); } @Override public URL getUrl() { return lf.getUrl(); } @Override public void init() { lf.init(); } @Override public boolean isAvailable() { return lf.isAvailable(); } @Override public int activeRefererCount() { return lf.activeRefererCount(); } @Override public URL getServiceUrl() { return lf.getServiceUrl(); } }; } return lastRef; } private <T> Provider<T> decorateWithFilter(Provider<T> provider, URL url) { List<Filter> filters = getFilters(url, MotanConstants.NODE_TYPE_SERVICE); if (filters == null || filters.size() == 0) { return provider; } Provider<T> lastProvider = provider; for (Filter filter : filters) { final Filter f = filter; final Provider<T> lp = lastProvider; lastProvider = new Provider<T>() { @Override public Response call(Request request) { return f.filter(lp, request); } @Override public String desc() { return lp.desc(); } @Override public void destroy() { lp.destroy(); } @Override public Class<T> getInterface() { return lp.getInterface(); } @Override public URL getUrl() { return lp.getUrl(); } @Override public void init() { lp.init(); } @Override public boolean isAvailable() { return lp.isAvailable(); } }; } return lastProvider; } /** * <pre> * 获取方式: * 1)先获取默认的filter列表; * 2)根据filter配置获取新的filters,并和默认的filter列表合并; * 3)再根据一些其他配置判断是否需要增加其他filter,如根据accessLog进行判断,是否需要增加accesslog * </pre> * * @param url * @param key * @return */ private List<Filter> getFilters(URL url, String key) { // load default filters List<Filter> filters = new ArrayList<Filter>(); List<Filter> defaultFilters = ExtensionLoader.getExtensionLoader(Filter.class).getExtensions(key); if (defaultFilters != null && defaultFilters.size() > 0) { filters.addAll(defaultFilters); } // add filters via "filter" config String filterStr = url.getParameter(URLParamType.filter.getName()); if (StringUtils.isNotBlank(filterStr)) { String[] filterNames = MotanConstants.COMMA_SPLIT_PATTERN.split(filterStr); for (String fn : filterNames) { addIfAbsent(filters, fn); } } // add filter via other configs, like accessLog and so on boolean accessLog = url.getBooleanParameter(URLParamType.accessLog.getName(), URLParamType.accessLog.getBooleanValue()); if (accessLog) { addIfAbsent(filters, AccessLogFilter.class.getAnnotation(SpiMeta.class).name()); } // sort the filters Collections.sort(filters, new ActivationComparator<Filter>()); Collections.reverse(filters); return filters; } private void addIfAbsent(List<Filter> filters, String extensionName) { if (StringUtils.isBlank(extensionName)) { return; } Filter extFilter = ExtensionLoader.getExtensionLoader(Filter.class).getExtension(extensionName); if (extFilter == null) { return; } boolean exists = false; for (Filter f : filters) { if (f.getClass() == extFilter.getClass()) { exists = true; break; } } if (!exists) { filters.add(extFilter); } } }