/*
* Copyright 2008-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.hasor.rsf.container;
import net.hasor.core.*;
import net.hasor.rsf.*;
import net.hasor.rsf.address.AddressPool;
import net.hasor.rsf.address.RouteTypeEnum;
import net.hasor.rsf.domain.ProtocolStatus;
import net.hasor.rsf.domain.RsfEvent;
import net.hasor.rsf.domain.RsfException;
import net.hasor.rsf.domain.RsfServiceType;
import net.hasor.rsf.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
/**
*
* @version : 2015年12月6日
* @author 赵永春(zyc@hasor.net)
*/
public class RsfBeanContainer {
protected Logger logger = LoggerFactory.getLogger(getClass());
private final static Provider[] EMPTY_FILTER = new Provider[0];
private final ConcurrentMap<String, ServiceDefine<?>> serviceMap;
private final ConcurrentMap<String, ConcurrentMap<String, String>> aliasNameMap;
private final List<FilterDefine> filterList;
private final Object filterLock;
private final AddressPool addressPool;
private final ConcurrentMap<String, Provider<RsfFilter>[]> filterCache;
//
public RsfBeanContainer(AddressPool addressPool) {
this.serviceMap = new ConcurrentHashMap<String, ServiceDefine<?>>();
this.aliasNameMap = new ConcurrentHashMap<String, ConcurrentMap<String, String>>();
this.filterList = new ArrayList<FilterDefine>();
this.filterLock = new Object();
this.addressPool = addressPool;
this.filterCache = new ConcurrentHashMap<String, Provider<RsfFilter>[]>();
}
/**
* 计算指定服务上配置的过滤器。{@link RsfFilter}按照配置方式分为共有和私有。
* 共有Filter的生效范围是所有Service,私有Filter的生效范围仅Service。
* 每一个Filter在配置的时候都需要指定ID,根据ID私有Filter可以覆盖共有Filter的配置。
* @param serviceID 服务ID
*/
public Provider<RsfFilter>[] getFilterProviders(String serviceID) {
ServiceDefine<?> info = this.serviceMap.get(serviceID);
if (info == null) {
return EMPTY_FILTER;
}
Provider<RsfFilter>[] result = filterCache.get(serviceID);
if (result == null) {
List<String> cacheIds = new LinkedList<String>();
Map<String, FilterDefine> cacheFilters = new HashMap<String, FilterDefine>();
//2.计算最终结果。
List<FilterDefine> publicList = this.filterList;
if (!publicList.isEmpty()) {
for (FilterDefine filter : publicList) {
String filterID = filter.filterID();
cacheFilters.put(filterID, filter);
cacheIds.add(filterID);
}
}
List<FilterDefine> snapshotsList = info.getFilterSnapshots();
if (snapshotsList != null && !snapshotsList.isEmpty()) {
for (FilterDefine filter : snapshotsList) {
String filterID = filter.filterID();
cacheFilters.put(filterID, filter);//保存或覆盖已有。
if (cacheIds.contains(filterID)) {
cacheIds.remove(filterID);//如果全局Filter已经定义了这个ID,那么从已有顺序中删除,在尾部追加私有Filter。
}
cacheIds.add(filterID);
}
}
//3.产出最终结果(过滤器链前端是public,后段是private)。
List<Provider<RsfFilter>> filterArrays = new ArrayList<Provider<RsfFilter>>(cacheIds.size());
for (String filterID : cacheIds) {
FilterDefine define = cacheFilters.get(filterID);
filterArrays.add(define);
}
result = (Provider<RsfFilter>[]) filterArrays.toArray(new Provider[filterArrays.size()]);
this.filterCache.put(serviceID, result);
}
return result;
}
/**
* 根据服务id获取服务对象。如果服务未定义或者服务未声明提供者,则返回null。
* @param rsfBindInfo 服务ID。
* @return 服务提供者
*/
public <T> Provider<T> getProvider(RsfBindInfo<T> rsfBindInfo) {
ServiceDefine<?> info = this.serviceMap.get(rsfBindInfo.getBindID());
if (info == null)
return null;
Provider<?> target = info.getCustomerProvider();
if (target != null) {
return (Provider<T>) target;
}
return null;
}
/**
* 根据服务id获取服务元信息。
* @param serviceID 服务ID。
*/
public RsfBindInfo<?> getRsfBindInfo(String serviceID) {
ServiceDefine<?> info = this.serviceMap.get(serviceID);
if (info == null)
return null;
return info.getDomain();
}
/**
* 根据服务id获取服务元信息。
* @param aliasType 名字分类。
* @param aliasName 别名。
*/
public RsfBindInfo<?> getRsfBindInfo(String aliasType, String aliasName) {
ConcurrentMap<String, String> aliasNameMaps = this.aliasNameMap.get(aliasType);
if (aliasNameMaps == null) {
return null;
}
String serviceID = aliasNameMaps.get(aliasName);
if (serviceID == null) {
return null;
}
return this.serviceMap.get(serviceID);
}
/**
* 根据类型获取服务元信息。如果类型上配置了{@link RsfService @RsfService}注解,则使用该注解的配置信息。
* 否则将使用RSF默认配置下的Group、Version。
* @param serviceType 服务类型。
*/
public <T> RsfBindInfo<T> getRsfBindInfo(Class<T> serviceType) {
RsfSettings rsfSettings = this.addressPool.getRsfEnvironment().getSettings();
String serviceGroup = rsfSettings.getDefaultGroup();
String serviceName = serviceType.getName();
String serviceVersion = rsfSettings.getDefaultVersion();
//覆盖
RsfService serviceInfo = serviceType.getAnnotation(RsfService.class);
if (serviceInfo != null) {
if (!StringUtils.isBlank(serviceInfo.group())) {
serviceGroup = serviceInfo.group();
}
if (!StringUtils.isBlank(serviceInfo.name())) {
serviceName = serviceInfo.name();
}
if (!StringUtils.isBlank(serviceInfo.version())) {
serviceVersion = serviceInfo.version();
}
}
return (RsfBindInfo<T>) getRsfBindInfo(serviceGroup, serviceName, serviceVersion);
}
/**
* 根据服务坐标获取服务元信息。
* @param group 组别
* @param name 服务名
* @param version 服务版本
*/
public RsfBindInfo<?> getRsfBindInfo(String group, String name, String version) {
String serviceID = "[" + group + "]" + name + "-" + version;//String.format("[%s]%s-%s", group, name, version);
return this.getRsfBindInfo(serviceID);
}
/**获取所有已经注册的服务名称。*/
public List<String> getServiceIDs() {
return new ArrayList<String>(this.serviceMap.keySet());
}
/**根据别名系统获取所有已经注册的服务名称。*/
public List<String> getServiceIDs(String category) {
ConcurrentMap<String, String> aliasNameMaps = this.aliasNameMap.get(category);
if (aliasNameMaps == null) {
return Collections.EMPTY_LIST;
}
return new ArrayList<String>(aliasNameMaps.keySet());
}
/**获取环境对象。*/
public RsfEnvironment getEnvironment() {
return this.addressPool.getRsfEnvironment();
}
//
/* ----------------------------------------------------------------------------------------- */
//
/**创建{@link RsfApiBinder}。*/
public RsfPublisher createPublisher(final RsfBeanContainer container, final RsfContext rsfContext) {
return new ContextRsfBindBuilder() {
@Override
protected RsfBeanContainer getContainer() {
return container;
}
@Override
protected RsfContext getRsfContext() {
return rsfContext;
}
};
}
/**
* 添加一个全局服务过滤器。
* @param define 过滤器对象。
*/
public void publishFilter(FilterDefine define) {
String filterID = Hasor.assertIsNotNull(define.filterID());
synchronized (this.filterLock) {
for (FilterDefine filter : this.filterList) {
if (filterID.equals(filter.filterID())) {
throw new IllegalStateException("repeate filterID :" + filterID);
}
}
this.filterList.add(define);
this.filterCache.clear();
}
}
/**
* 发布服务
* @param serviceDefine 服务定义。
*/
public synchronized <T> boolean publishService(ServiceDefine<T> serviceDefine) {
String serviceID = serviceDefine.getDomain().getBindID();
if (this.serviceMap.containsKey(serviceID)) {
String serviceType = this.serviceMap.get(serviceID).getDomain().getServiceType().name();
String logMessage = "a " + serviceType + " of the same name already exists , serviceID -> " + serviceID;
this.logger.error(logMessage);
throw new IllegalStateException(logMessage);
}
this.logger.info("service to public, id= {}", serviceID);
ServiceDefine<?> info = this.serviceMap.putIfAbsent(serviceID, serviceDefine);
//
EventContext eventContext = this.addressPool.getRsfEnvironment().getEventContext();
if (RsfServiceType.Provider == serviceDefine.getServiceType()) {
//服务提供者
if (serviceDefine.getCustomerProvider() == null) {
throw new RsfException(ProtocolStatus.Forbidden, "Provider Not set the implementation class.");
}
try {
eventContext.fireSyncEvent(RsfEvent.Rsf_ProviderService, serviceDefine);
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
} else {
//服务消费者
try {
eventContext.fireSyncEvent(RsfEvent.Rsf_ConsumerService, serviceDefine);
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
}
// .收录别名
Set<String> aliasTypes = serviceDefine.getAliasTypes();
for (String aliasType : aliasTypes) {
ConcurrentMap<String, String> aliasMap = this.aliasNameMap.get(aliasType);
if (aliasMap == null) {
aliasMap = new ConcurrentHashMap<String, String>();
this.aliasNameMap.putIfAbsent(aliasType, aliasMap);
}
String aliasName = serviceDefine.getAliasName(aliasType);
if (StringUtils.isBlank(aliasName)) {
continue;
}
aliasMap.putIfAbsent(aliasName, serviceID);
}
//
// .追加地址
this.addressPool.appendStaticAddress(serviceID, serviceDefine.getAddressSet());
// .更新流控
String flowControl = serviceDefine.getFlowControl();
if (StringUtils.isNotBlank(flowControl)) {
this.addressPool.updateFlowControl(serviceID, flowControl);
}
// .更新路由
Map<RouteTypeEnum, String> scriptMap = serviceDefine.getRouteScript();
if (scriptMap != null && !scriptMap.isEmpty()) {
for (Map.Entry<RouteTypeEnum, String> routeEnt : scriptMap.entrySet()) {
this.addressPool.updateRoute(serviceID, routeEnt.getKey(), routeEnt.getValue());
}
}
//
return true;
}
/**
* 回收发布的服务
* @param serviceID 服务定义。
*/
public synchronized boolean recoverService(String serviceID) {
if (this.serviceMap.containsKey(serviceID)) {
//
// .发布删除消息( 1.Center解除注册、2.地址本回收)
EventContext eventContext = this.getEnvironment().getEventContext();
RsfBindInfo<?> rsfBindInfo = this.serviceMap.get(serviceID);
try {
eventContext.fireSyncEvent(RsfEvent.Rsf_DeleteService, rsfBindInfo);
} catch (Throwable e) {
logger.error(e.getMessage(), e);
}
//
// .回收服务
this.serviceMap.remove(serviceID);
//
for (Map.Entry<String, ConcurrentMap<String, String>> aliasEntry : this.aliasNameMap.entrySet()) {
ConcurrentMap<String, String> aliasSet = aliasEntry.getValue();
ArrayList<String> toRemove = new ArrayList<String>();
for (Map.Entry<String, String> entry : aliasSet.entrySet()) {
if (serviceID.equals(entry.getValue())) {
toRemove.add(entry.getKey());
}
}
//
for (String key : toRemove) {
aliasSet.remove(key);
}
}
//
return true;
}
return false;
}
//
/* ----------------------------------------------------------------------------------------- */
//
/**
* 发布的服务
* @param appContext 用于查找服务的容器上下文。
*/
public void lookUp(AppContext appContext) {
List<BindInfo<FilterDefine>> filterList = appContext.findBindingRegister(FilterDefine.class);
for (BindInfo<FilterDefine> defile : filterList) {
FilterDefine fd = appContext.getInstance(defile);
if (fd != null) {
this.publishFilter(fd);
}
}
List<BindInfo<ServiceDefine>> serviceList = appContext.findBindingRegister(ServiceDefine.class);
for (BindInfo<ServiceDefine> defile : serviceList) {
ServiceDefine sd = appContext.getInstance(defile);
if (sd != null) {
this.publishService(sd);
}
}
//
this.logger.info("lookUp finish.");
}
}