gu.simplemq.MQPropertiesHelper Maven / Gradle / Ivy
The newest version!
package gu.simplemq;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.*;
import static gu.simplemq.utils.TypeConversionSupport.stringValueOf;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.EnumMap;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import com.google.common.base.Predicates;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.net.HostAndPort;
import gu.simplemq.utils.URISupport;
/**
* @author guyadong
*
*/
public abstract class MQPropertiesHelper implements Constant {
private static final ThreadLocal locationType = new ThreadLocal<>();
protected MQConstProvider constProvider = getConstProvider();
protected MQPropertiesHelper() {}
public abstract MQConstProvider getConstProvider() ;
public MQProperties makeMQProperties(Properties defaults){
return new MQPropertiesImpl(defaults);
}
public MQPropertiesHelper with(MQLocationType type){
if(type != null){
locationType.set(type);
}else{
locationType.remove();
}
return this;
}
/**
* 从Map中返回指定的连接参数值(字符串)
* @param props 为{@code null}返回{@code null}
* @param keys 连接参数名,会以此数组顺序为优先序返回参数值
* @return 参数值字符串,没有返回{@code null}
*/
@SuppressWarnings("rawtypes")
private static String connInfoOf(Map props, String... keys){
if(null == props){
return null;
}
if(keys != null){
for(String key : Sets.newLinkedHashSet(Iterables.filter(Arrays.asList(keys),Predicates.notNull()))){
String temp = stringValueOf(props,key);
if (!Strings.isNullOrEmpty(temp)) {
return temp;
}
}
}
return null;
}
@SuppressWarnings("rawtypes")
public String usernameOf(Map props){
return connInfoOf(props,MQ_USERNAME,constProvider.getMainUserName());
}
@SuppressWarnings("rawtypes")
public String passwordOf(Map props){
return connInfoOf(props,MQ_PASSWORD,constProvider.getMainPassword());
}
@SuppressWarnings("rawtypes")
public String clientidOf(Map props){
return connInfoOf(props,MQ_CLIENTID,constProvider.getMainClientID());
}
/**
* 从Map中返回服务地址(URI)
* @param props
* @return 服务地址(URI)实例,没有返回{@code null}
*/
@SuppressWarnings("rawtypes")
public URI getLocation(Map props){
try {
String temp = firstNonNull(locationType.get(), MQLocationType.DEFAULT)
.locationStringOf(props, true, constProvider.getOptionalLocationNames());
if(temp != null){
return new MQLocation(temp).getUri();
}
return null;
} finally {
locationType.remove();
}
}
/**
* 从Map中返回服务地址(URI)字符串
* @param props
* @return 服务地址(URI)字符串,没有返回{@code null}
*/
@SuppressWarnings("rawtypes")
public String getLocationAsString(Map props){
URI uri = getLocation(props);
return uri == null ? null : uri.toString();
}
/**
* 对参数(props)中的服务地址归一化
* 优先使用{@code ACON_BROKER_URL}提供的地址,
* 如果没有则调用 {@link ActivemqProperties#getLocationAsString(Map, MQLocationType)}获取地址
* (为{@code null}则使用默认值{@code DEFAULT_BROKER_BIND_URL}),
* 最后将{@code MQTT_serverURI}设置为该值,
* 返回时删除props中的其他可代表服务地址的值{@code MQ_URI,MQ_HOST,MQ_PORT,PROVIDER_URL}
* @param props
* @return always props,确保{@code ACON_BROKER_URL}有定义
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
M normalizeLocation(M props){
if(null != props){
String s = stringValueOf(props, constProvider.getMainLocationName());
if (Strings.isNullOrEmpty(s)) {
props.put(constProvider.getMainLocationName(),
firstNonNull(getLocationAsString(props), constProvider.getDefaultMQLocation()));
}
props.remove(MQ_QUEUE_URI);
props.remove(MQ_QUEUE_HOST);
props.remove(MQ_QUEUE_PORT);
props.remove(MQ_PUBSUB_URI);
props.remove(MQ_PUBSUB_HOST);
props.remove(MQ_PUBSUB_PORT);
props.remove(MQ_URI);
props.remove(MQ_HOST);
props.remove(MQ_PORT);
for(String name:constProvider.getOptionalLocationNames()){
if(!constProvider.getMainLocationName().equals(name)){
props.remove(name);
}
}
}
return props;
}
@SuppressWarnings({ "rawtypes", "unchecked" })
private M normalizeKey(M props,String nativeKey,String generalKey){
if(null != props){
if(nativeKey != null && generalKey != null && !generalKey.equals(nativeKey)){
String s = stringValueOf(props, nativeKey);
if (Strings.isNullOrEmpty(s)) {
s = stringValueOf(props,generalKey);
if(!Strings.isNullOrEmpty(s)){
props.put(nativeKey, s);
}
}
props.remove(generalKey);
}
}
return props;
}
/**
* 对参数(props)中的连接参数归一化
* @param props
* @return always props
*/
@SuppressWarnings({ "rawtypes" })
public M normalizeProps(M props){
normalizeLocation(props);
normalizeKey(props,constProvider.getMainUserName(),MQ_USERNAME);
normalizeKey(props,constProvider.getMainPassword(),MQ_PASSWORD);
normalizeKey(props,constProvider.getMainClientID(),MQ_CLIENTID);
normalizeKey(props,constProvider.getMainTimeout(),MQ_TIMEOUT);
return props;
}
/**
* 根据{@code props}提供的参数创建一组完整的初始化参数
* @param props
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public MQProperties initParameters(Map props){
// 初始化时复制一份缺省参数
MQProperties params = asMQProperties(constProvider.getDefaultMQProperties());
if(null != props){
// 过滤掉所有为null的参数,避免将缺省参数覆盖为null
Map filtered = Maps.filterValues(asMQProperties(props), Predicates.notNull());
// 缺省参数与输入参数合并
params.putAll(filtered);
URI uri = getLocation(params);
String userinfo = uri.getUserInfo();
if(userinfo != null && userinfo.indexOf(':') >= 0){
// 如果URI中以${username}:${password}格式定义了用户名和密码,则优先使用之
String[] u = userinfo.split(":");
if(!Strings.isNullOrEmpty(u[0])){
String keyUsername = firstNonNull(constProvider.getMainUserName(), MQ_USERNAME);
params.setProperty(keyUsername, u[0]);
}
if(!Strings.isNullOrEmpty(u[1])){
String keyPassword = firstNonNull(constProvider.getMainPassword(), MQ_PASSWORD);
params.setProperty(keyPassword, u[1]);
}
try {
// 删除URI中的userinfo信息
uri = URISupport.changeUserinfo(uri, null);
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
}
params.initURI(new MQLocation(uri).toString());
}
return normalizeProps(params);
}
@SuppressWarnings("rawtypes")
public MQProperties asMQProperties(Map props){
if(props instanceof MQProperties){
return (MQProperties)props;
}
return new MQPropertiesImpl().init(props);
}
/**
* 将类型为{@link Properties}的参数转换为{@code HashMap},
* key为枚举变量名
* @param props
* @return HashMap实例,props为{@code null}时返回空实例
*/
public HashMap asMqParameters2(Properties props){
if(props == null){
props = new Properties();
}
HashMap map = Maps.newHashMap();
for(Enumeration> itor = props.propertyNames();itor.hasMoreElements();){
String key = (String) itor.nextElement();
map.put(key, props.get(key).toString());
}
return map;
}
/**
* 将指定的 {@link Map} 对象转为{@link EnumMap}
* @param keyType 枚举类型
* @param props
* @param removeIfSet 是否从props删除枚举类型的key
* @param strippedPrefix 需要剥离key的前缀
* @return {@link EnumMap}对象
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public >
EnumMap asEnumMap(Class keyType, Map props , boolean removeIfSet, String strippedPrefix){
EnumMap map = new EnumMap<>(keyType);
if(props != null){
for(Iterator itor = props.keySet().iterator();itor.hasNext();){
try {
Object key = itor.next();
Object value = props.get(key);
if(keyType.isInstance(key)){
map.put((E) key, value);
}else{
String name = key.toString();
if (strippedPrefix != null && name.startsWith(strippedPrefix)) {
name = name.substring(strippedPrefix.length());
}
E ekey = Enum.valueOf(keyType, name);
map.put(ekey, value);
}
if(removeIfSet){
itor.remove();
}
} catch (Throwable e) {
}
}
}
return map;
}
@SuppressWarnings("rawtypes")
public HostAndPort getHostAndPort(Map parameters){
checkArgument(null != parameters,"parameters is null");
URI uri = getLocation(parameters);
checkArgument(uri != null, "NOT DEFINED LOCATION FOR MQLocationType:%s",locationType.get());
return HostAndPort.fromParts(uri.getHost(), uri.getPort());
}
/**
* 根据连接参数创建一个{@link URI}对象
* @param parameters
*/
@SuppressWarnings("rawtypes")
public URI getCanonicalURI(Map parameters){
MQProperties props = initParameters(parameters);
return new MQLocation(props.getProperty(constProvider.getMainLocationName())).getUri();
}
/**
* 根据连接参数创建一个{@link URI}对象
* @param parameters
*/
@SuppressWarnings("rawtypes")
public URI getLocationlURI(Map parameters){
MQProperties props = initParameters(parameters);
return new MQLocation(props.getProperty(constProvider.getMainLocationName())).asLocation();
}
/**
* 测试接参数是否有效,无效抛出异常
* @param input
* @param timeoutMills 超时参数(毫秒),为{@code null}使用默认值
* @throws Exception 无法连接
*/
public abstract void checkConnect(Properties input, Integer timeoutMills) throws Exception;
/**
* 测试接参数是否有效
* @param props
* @param timeoutMills 超时参数(毫秒),为{@code null}使用默认值
* @return 连接失败返回{@code false}
*/
public abstract boolean testConnect(Properties props,Integer timeoutMills);
protected class MQLocation extends BaseMQURI{
public MQLocation(String uri) {
super(uri);
}
public MQLocation(URI uri) {
super(uri);
}
@Override
protected MQConstProvider getConstProvider() {
return constProvider;
}
}
@SuppressWarnings("serial")
protected class MQPropertiesImpl extends MQProperties{
MQPropertiesImpl() {
super();
}
MQPropertiesImpl(Properties defaults) {
super(defaults);
}
@Override
public MQPropertiesHelper getPropertiesHelper() {
return MQPropertiesHelper.this;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy