mirror of
https://github.com/alibaba/arthas.git
synced 2024-04-21 10:21:39 +00:00
support ArthasEnvironment. #986
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
package com.taobao.arthas.core.config;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import com.taobao.arthas.core.env.Environment;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc 2020-01-10
|
||||
*
|
||||
*/
|
||||
public class BinderUtils {
|
||||
|
||||
public static void inject(Environment environment, Object instance) {
|
||||
inject(environment, null, null, instance);
|
||||
}
|
||||
|
||||
public static void inject(Environment environment, String prefix, Object instance) {
|
||||
inject(environment, null, prefix, instance);
|
||||
}
|
||||
|
||||
public static void inject(Environment environment, String parentPrefix, String prefix, Object instance) {
|
||||
Class<? extends Object> type = instance.getClass();
|
||||
try {
|
||||
Config annotation = type.getAnnotation(Config.class);
|
||||
|
||||
if (prefix == null) {
|
||||
prefix = "";
|
||||
}
|
||||
|
||||
if (annotation == null) {
|
||||
prefix = parentPrefix + '.' + prefix;
|
||||
} else {
|
||||
prefix = annotation.prefix();
|
||||
if (prefix != null) {
|
||||
if (parentPrefix != null && parentPrefix.length() > 0) {
|
||||
prefix = parentPrefix + '.' + prefix;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Method[] declaredMethods = type.getDeclaredMethods();
|
||||
if (declaredMethods != null) {
|
||||
// 获取到所有setter方法,再提取出field。根据前缀从 properties里取出值,再尝试用setter方法注入到对象里
|
||||
for (Method method : declaredMethods) {
|
||||
String methodName = method.getName();
|
||||
Class<?>[] parameterTypes = method.getParameterTypes();
|
||||
|
||||
if (parameterTypes != null && parameterTypes.length == 1 && methodName.startsWith("set")
|
||||
&& methodName.length() > "set".length()) {
|
||||
|
||||
String field = getFieldNameFromSetterMethod(methodName);
|
||||
Object reslovedValue = environment.getProperty(prefix + '.' + field, parameterTypes[0]);
|
||||
if (reslovedValue != null) {
|
||||
method.invoke(instance, new Object[] { reslovedValue });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("inject error. prefix: " + prefix + ", instance: " + instance, e);
|
||||
}
|
||||
|
||||
// process @NestedConfig
|
||||
Field[] fields = type.getDeclaredFields();
|
||||
if (fields != null) {
|
||||
for (Field field : fields) {
|
||||
NestedConfig nestedConfig = field.getAnnotation(NestedConfig.class);
|
||||
if (nestedConfig != null) {
|
||||
String prefixForField = field.getName();
|
||||
if (parentPrefix != null && prefix.length() > 0) {
|
||||
prefixForField = prefix + '.' + prefixForField;
|
||||
}
|
||||
|
||||
field.setAccessible(true);
|
||||
try {
|
||||
Object fieldValue = field.get(instance);
|
||||
if (fieldValue == null) {
|
||||
fieldValue = field.getType().newInstance();
|
||||
}
|
||||
inject(environment, prefix, prefixForField, fieldValue);
|
||||
|
||||
field.set(instance, fieldValue);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("process @NestedConfig error, field: " + field + ", prefix: "
|
||||
+ prefix + ", instance: " + instance, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 从setter方法获取到field的String。比如 setHost, 则获取到的是host。
|
||||
*
|
||||
* @param methodName
|
||||
* @return
|
||||
*/
|
||||
private static String getFieldNameFromSetterMethod(String methodName) {
|
||||
String field = methodName.substring("set".length());
|
||||
String startPart = field.substring(0, 1).toLowerCase();
|
||||
String endPart = field.substring(1);
|
||||
|
||||
field = startPart + endPart;
|
||||
return field;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.taobao.arthas.core.config;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc 2019-08-05
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface Config {
|
||||
|
||||
String prefix() default "";
|
||||
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import static java.lang.reflect.Modifier.isStatic;
|
||||
* @author vlinux
|
||||
* @author hengyunabc 2018-11-12
|
||||
*/
|
||||
@Config(prefix = "arthas")
|
||||
public class Configure {
|
||||
public static final long DEFAULT_SESSION_TIMEOUT_SECONDS = ShellServerOptions.DEFAULT_SESSION_TIMEOUT/1000;
|
||||
private String ip;
|
||||
@@ -117,9 +118,6 @@ public class Configure {
|
||||
this.statUrl = statUrl;
|
||||
}
|
||||
|
||||
// 对象的编码解码器
|
||||
private final static FeatureCodec codec = new FeatureCodec(';', '=');
|
||||
|
||||
/**
|
||||
* 序列化成字符串
|
||||
*
|
||||
@@ -148,7 +146,7 @@ public class Configure {
|
||||
|
||||
}
|
||||
|
||||
return codec.toString(map);
|
||||
return FeatureCodec.DEFAULT_COMMANDLINE_CODEC.toString(map);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,7 +157,7 @@ public class Configure {
|
||||
*/
|
||||
public static Configure toConfigure(String toString) throws IllegalAccessException {
|
||||
final Configure configure = new Configure();
|
||||
final Map<String, String> map = codec.toMap(toString);
|
||||
final Map<String, String> map = FeatureCodec.DEFAULT_COMMANDLINE_CODEC.toMap(toString);
|
||||
|
||||
for (Map.Entry<String, String> entry : map.entrySet()) {
|
||||
final Field field = ArthasReflectUtils.getField(Configure.class, entry.getKey());
|
||||
|
||||
@@ -16,6 +16,8 @@ import static com.taobao.arthas.core.util.StringUtils.isBlank;
|
||||
* Created by dukun on 15/3/31.
|
||||
*/
|
||||
public class FeatureCodec {
|
||||
// 对象的编码解码器
|
||||
public final static FeatureCodec DEFAULT_COMMANDLINE_CODEC = new FeatureCodec(';', '=');
|
||||
|
||||
/**
|
||||
* KV片段分割符<br/>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.taobao.arthas.core.config;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc 2019-08-05
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
public @interface NestedConfig {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package com.taobao.arthas.core.config;
|
||||
|
||||
public class SecondConfig {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package com.taobao.arthas.core.config;
|
||||
|
||||
|
||||
@Config
|
||||
public class TestConfig {
|
||||
|
||||
@NestedConfig
|
||||
SecondConfig secondConfig;
|
||||
}
|
||||
@@ -19,6 +19,9 @@ package com.taobao.arthas.core.env;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import com.taobao.arthas.core.env.convert.ConfigurableConversionService;
|
||||
import com.taobao.arthas.core.env.convert.DefaultConversionService;
|
||||
|
||||
/**
|
||||
* Abstract base class for resolving properties against any underlying source.
|
||||
*
|
||||
|
||||
@@ -27,6 +27,13 @@ public class ArthasEnvironment implements Environment {
|
||||
new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given property source object with highest precedence.
|
||||
*/
|
||||
public void addFirst(PropertySource<?> propertySource) {
|
||||
this.propertySources.addFirst(propertySource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the given property source object with lowest precedence.
|
||||
*/
|
||||
|
||||
+2
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.taobao.arthas.core.env;
|
||||
|
||||
import com.taobao.arthas.core.env.convert.ConfigurableConversionService;
|
||||
|
||||
/**
|
||||
* Configuration interface to be implemented by most if not all
|
||||
* {@link PropertyResolver} types. Provides facilities for accessing and
|
||||
|
||||
+4
-2
@@ -14,7 +14,9 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.taobao.arthas.core.env;
|
||||
package com.taobao.arthas.core.env.convert;
|
||||
|
||||
import com.taobao.arthas.core.env.ConversionService;
|
||||
|
||||
/**
|
||||
* Configuration interface to be implemented by most if not all
|
||||
@@ -28,7 +30,7 @@ package com.taobao.arthas.core.env;
|
||||
*
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
* @see org.springframework.core.env.ConfigurablePropertyResolver#getConversionService()
|
||||
* @see com.taobao.arthas.core.env.springframework.core.env.ConfigurablePropertyResolver#getConversionService()
|
||||
* @see org.springframework.core.env.ConfigurableEnvironment
|
||||
* @see org.springframework.context.ConfigurableApplicationContext#getEnvironment()
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2002-2015 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 com.taobao.arthas.core.env.convert;
|
||||
|
||||
/**
|
||||
* A converter converts a source object of type S to a target of type T.
|
||||
* Implementations of this interface are thread-safe and can be shared.
|
||||
*
|
||||
* <p>Implementations may additionally implement {@link ConditionalConverter}.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
* @param <S> The source type
|
||||
* @param <T> The target type
|
||||
*/
|
||||
public interface Converter<S, T> {
|
||||
|
||||
/**
|
||||
* Convert the source of type S to target type T.
|
||||
* @param source the source object to convert, which must be an instance of S (never {@code null})
|
||||
* @return the converted object, which must be an instance of T (potentially {@code null})
|
||||
* @throws IllegalArgumentException if the source could not be converted to the desired target type
|
||||
*/
|
||||
T convert(S source, Class<T> targetType);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package com.taobao.arthas.core.env.convert;
|
||||
|
||||
/**
|
||||
* Holder for a source-to-target class pair.
|
||||
*/
|
||||
public final class ConvertiblePair {
|
||||
|
||||
private final Class<?> sourceType;
|
||||
|
||||
private final Class<?> targetType;
|
||||
|
||||
/**
|
||||
* Create a new source-to-target pair.
|
||||
*
|
||||
* @param sourceType the source type
|
||||
* @param targetType the target type
|
||||
*/
|
||||
public ConvertiblePair(Class<?> sourceType, Class<?> targetType) {
|
||||
this.sourceType = sourceType;
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
public Class<?> getSourceType() {
|
||||
return this.sourceType;
|
||||
}
|
||||
|
||||
public Class<?> getTargetType() {
|
||||
return this.targetType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null || obj.getClass() != ConvertiblePair.class) {
|
||||
return false;
|
||||
}
|
||||
ConvertiblePair other = (ConvertiblePair) obj;
|
||||
return this.sourceType.equals(other.sourceType) && this.targetType.equals(other.targetType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return this.sourceType.hashCode() * 31 + this.targetType.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return this.sourceType.getName() + " -> " + this.targetType.getName();
|
||||
}
|
||||
}
|
||||
+110
-4
@@ -1,17 +1,123 @@
|
||||
package com.taobao.arthas.core.env;
|
||||
package com.taobao.arthas.core.env.convert;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public class DefaultConversionService implements ConfigurableConversionService {
|
||||
|
||||
private static ConcurrentHashMap<ConvertiblePair, Converter> converters = new ConcurrentHashMap<ConvertiblePair, Converter>();
|
||||
|
||||
public DefaultConversionService() {
|
||||
addDefaultConverter();
|
||||
|
||||
}
|
||||
|
||||
private void addDefaultConverter() {
|
||||
converters.put(new ConvertiblePair(String.class, Integer.class), new StringToIntegerConverter());
|
||||
converters.put(new ConvertiblePair(String.class, Long.class), new StringToLongConverter());
|
||||
|
||||
converters.put(new ConvertiblePair(String.class, Boolean.class), new StringToBooleanConverter());
|
||||
|
||||
converters.put(new ConvertiblePair(String.class, InetAddress.class), new StringToInetAddressConverter());
|
||||
|
||||
converters.put(new ConvertiblePair(String.class, Enum.class), new StringToEnumConverter());
|
||||
|
||||
converters.put(new ConvertiblePair(String.class, Arrays.class), new StringToArrayConverter(this));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConvert(Class<?> sourceType, Class<?> targetType) {
|
||||
// TODO Auto-generated method stub
|
||||
return true;
|
||||
if (sourceType == targetType) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (targetType.isPrimitive()) {
|
||||
targetType = objectiveClass(targetType);
|
||||
}
|
||||
|
||||
if (converters.containsKey(new ConvertiblePair(sourceType, targetType))) {
|
||||
return true;
|
||||
}
|
||||
if (targetType.isEnum()) {
|
||||
if (converters.containsKey(new ConvertiblePair(sourceType, Enum.class))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (targetType.isArray()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T convert(Object source, Class<T> targetType) {
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
if (targetType.isPrimitive()) {
|
||||
targetType = (Class<T>) objectiveClass(targetType);
|
||||
}
|
||||
|
||||
Converter converter = converters.get(new ConvertiblePair(source.getClass(), targetType));
|
||||
|
||||
if (converter == null && targetType.isArray()) {
|
||||
converter = converters.get(new ConvertiblePair(source.getClass(), Arrays.class));
|
||||
}
|
||||
|
||||
if (converter == null && targetType.isEnum()) {
|
||||
converter = converters.get(new ConvertiblePair(source.getClass(), Enum.class));
|
||||
}
|
||||
if (converter != null) {
|
||||
return (T) converter.convert(source, targetType);
|
||||
}
|
||||
|
||||
return (T) source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array class of the given class.
|
||||
*
|
||||
* @param klass to get an array class of
|
||||
* @param <C> the targeted class
|
||||
* @return an array class of the given class
|
||||
*/
|
||||
public static <C> Class<C[]> arrayClass(Class<C> klass) {
|
||||
return (Class<C[]>) Array.newInstance(klass, 0).getClass();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the class that extends {@link Object} that represent the given class.
|
||||
*
|
||||
* @param klass to get the object class of
|
||||
* @return the class that extends Object class and represent the given class
|
||||
*/
|
||||
public static Class<?> objectiveClass(Class<?> klass) {
|
||||
Class<?> component = klass.getComponentType();
|
||||
if (component != null) {
|
||||
if (component.isPrimitive() || component.isArray())
|
||||
return arrayClass(objectiveClass(component));
|
||||
} else if (klass.isPrimitive()) {
|
||||
if (klass == char.class)
|
||||
return Character.class;
|
||||
if (klass == int.class)
|
||||
return Integer.class;
|
||||
if (klass == boolean.class)
|
||||
return Boolean.class;
|
||||
if (klass == byte.class)
|
||||
return Byte.class;
|
||||
if (klass == double.class)
|
||||
return Double.class;
|
||||
if (klass == float.class)
|
||||
return Float.class;
|
||||
if (klass == long.class)
|
||||
return Long.class;
|
||||
if (klass == short.class)
|
||||
return Short.class;
|
||||
}
|
||||
|
||||
return klass;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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 com.taobao.arthas.core.env.convert;
|
||||
|
||||
/**
|
||||
* Simply calls {@link Object#toString()} to convert a source Object to a String.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @since 3.0
|
||||
*/
|
||||
final class ObjectToStringConverter implements Converter<Object, String> {
|
||||
|
||||
public String convert(Object source, Class<String> targetType) {
|
||||
return source.toString();
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
|
||||
package com.taobao.arthas.core.env.convert;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
|
||||
import com.taobao.arthas.core.env.ConversionService;
|
||||
import com.taobao.arthas.core.util.StringUtils;
|
||||
|
||||
final class StringToArrayConverter<T> implements Converter<String, T[]> {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
public StringToArrayConverter(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T[] convert(String source, Class<T[]> targetType) {
|
||||
String[] strings = StringUtils.tokenizeToStringArray(source, ",");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
T[] values = (T[]) Array.newInstance(targetType.getComponentType(), strings.length);
|
||||
for (int i = 0; i < strings.length; ++i) {
|
||||
@SuppressWarnings("unchecked")
|
||||
T value = (T) conversionService.convert(strings[i], targetType.getComponentType());
|
||||
|
||||
values[i] = value;
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
}
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2002-2011 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 com.taobao.arthas.core.env.convert;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Converts String to a Boolean.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.0
|
||||
*/
|
||||
final class StringToBooleanConverter implements Converter<String, Boolean> {
|
||||
|
||||
private static final Set<String> trueValues = new HashSet<String>(4);
|
||||
|
||||
private static final Set<String> falseValues = new HashSet<String>(4);
|
||||
|
||||
static {
|
||||
trueValues.add("true");
|
||||
trueValues.add("on");
|
||||
trueValues.add("yes");
|
||||
trueValues.add("1");
|
||||
|
||||
falseValues.add("false");
|
||||
falseValues.add("off");
|
||||
falseValues.add("no");
|
||||
falseValues.add("0");
|
||||
}
|
||||
|
||||
public Boolean convert(String source, Class<Boolean> targetType) {
|
||||
String value = source.trim();
|
||||
if ("".equals(value)) {
|
||||
return null;
|
||||
}
|
||||
value = value.toLowerCase();
|
||||
if (trueValues.contains(value)) {
|
||||
return Boolean.TRUE;
|
||||
}
|
||||
else if (falseValues.contains(value)) {
|
||||
return Boolean.FALSE;
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Invalid boolean value '" + source + "'");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
|
||||
package com.taobao.arthas.core.env.convert;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
final class StringToEnumConverter<T extends Enum> implements Converter<String, T> {
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public T convert(String source, Class<T> targetType) {
|
||||
return (T) Enum.valueOf(targetType, source);
|
||||
}
|
||||
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
package com.taobao.arthas.core.env.convert;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
public class StringToInetAddressConverter implements Converter<String, InetAddress> {
|
||||
|
||||
@Override
|
||||
public InetAddress convert(String source, Class<InetAddress> targetType) {
|
||||
try {
|
||||
return InetAddress.getByName(source);
|
||||
} catch (UnknownHostException e) {
|
||||
throw new IllegalArgumentException("Invalid InetAddress value '" + source + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
|
||||
package com.taobao.arthas.core.env.convert;
|
||||
|
||||
final class StringToIntegerConverter implements Converter<String, Integer> {
|
||||
@Override
|
||||
public Integer convert(String source, Class<Integer> targetType) {
|
||||
return Integer.parseInt(source);
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
|
||||
package com.taobao.arthas.core.env.convert;
|
||||
|
||||
final class StringToLongConverter implements Converter<String, Long> {
|
||||
@Override
|
||||
public Long convert(String source, Class<Long> targetType) {
|
||||
return Long.parseLong(source);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package com.taobao.arthas.core.server;
|
||||
|
||||
import com.taobao.arthas.core.config.Configure;
|
||||
import com.taobao.arthas.core.config.FeatureCodec;
|
||||
import com.taobao.arthas.core.env.ArthasEnvironment;
|
||||
import com.taobao.arthas.core.env.MapPropertySource;
|
||||
import com.alibaba.arthas.tunnel.client.TunnelClient;
|
||||
import com.taobao.arthas.common.PidUtils;
|
||||
import com.taobao.arthas.core.advisor.AdviceWeaver;
|
||||
@@ -30,6 +33,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
@@ -45,6 +49,8 @@ public class ArthasBootstrap {
|
||||
private static Logger logger = LogUtil.getArthasLogger();
|
||||
private static ArthasBootstrap arthasBootstrap;
|
||||
|
||||
private ArthasEnvironment arthasEnvironment;
|
||||
|
||||
private AtomicBoolean isBindRef = new AtomicBoolean(false);
|
||||
private Instrumentation instrumentation;
|
||||
private Thread shutdown;
|
||||
@@ -95,7 +101,21 @@ public class ArthasBootstrap {
|
||||
|
||||
public void bind(String args) throws Throwable {
|
||||
initSpy();
|
||||
|
||||
if( arthasEnvironment == null) {
|
||||
arthasEnvironment = new ArthasEnvironment();
|
||||
}
|
||||
Configure configure = Configure.toConfigure(args);
|
||||
Map<String, String> argsMap = FeatureCodec.DEFAULT_COMMANDLINE_CODEC.toMap(args);
|
||||
// 给配置全加上前缀
|
||||
Map<String, Object> mapWithPrefix = new HashMap<String, Object>(argsMap.size());
|
||||
for(Entry<String, String> entry : argsMap.entrySet()) {
|
||||
mapWithPrefix.put("arthas." + entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
MapPropertySource mapPropertySource = new MapPropertySource("args", mapWithPrefix);
|
||||
arthasEnvironment.addFirst(mapPropertySource);
|
||||
|
||||
bind(configure);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user