wildfire chat server source initial submit
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2016 ikidou
|
||||
*
|
||||
* 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 ikidou.reflect;
|
||||
|
||||
import ikidou.reflect.exception.TypeException;
|
||||
import ikidou.reflect.typeimpl.ParameterizedTypeImpl;
|
||||
import ikidou.reflect.typeimpl.WildcardTypeImpl;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TypeBuilder {
|
||||
private final TypeBuilder parent;
|
||||
private final Class raw;
|
||||
private final List<Type> args = new ArrayList<>();
|
||||
|
||||
|
||||
private TypeBuilder(Class raw, TypeBuilder parent) {
|
||||
assert raw != null;
|
||||
this.raw = raw;
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
public static TypeBuilder newInstance(Class raw) {
|
||||
return new TypeBuilder(raw, null);
|
||||
}
|
||||
|
||||
private static TypeBuilder newInstance(Class raw, TypeBuilder parent) {
|
||||
return new TypeBuilder(raw, parent);
|
||||
}
|
||||
|
||||
|
||||
public TypeBuilder beginSubType(Class raw) {
|
||||
return newInstance(raw, this);
|
||||
}
|
||||
|
||||
public TypeBuilder endSubType() {
|
||||
if (parent == null) {
|
||||
throw new TypeException("expect beginSubType() before endSubType()");
|
||||
}
|
||||
|
||||
parent.addTypeParam(getType());
|
||||
|
||||
return parent;
|
||||
}
|
||||
|
||||
public TypeBuilder addTypeParam(Class clazz) {
|
||||
return addTypeParam((Type) clazz);
|
||||
}
|
||||
|
||||
public TypeBuilder addTypeParamExtends(Class... classes) {
|
||||
if (classes == null) {
|
||||
throw new NullPointerException("addTypeParamExtends() expect not null Class");
|
||||
}
|
||||
|
||||
WildcardTypeImpl wildcardType = new WildcardTypeImpl(null, classes);
|
||||
|
||||
return addTypeParam(wildcardType);
|
||||
}
|
||||
|
||||
public TypeBuilder addTypeParamSuper(Class... classes) {
|
||||
if (classes == null) {
|
||||
throw new NullPointerException("addTypeParamSuper() expect not null Class");
|
||||
}
|
||||
|
||||
WildcardTypeImpl wildcardType = new WildcardTypeImpl(classes, null);
|
||||
|
||||
return addTypeParam(wildcardType);
|
||||
}
|
||||
|
||||
public TypeBuilder addTypeParam(Type type) {
|
||||
if (type == null) {
|
||||
throw new NullPointerException("addTypeParam expect not null Type");
|
||||
}
|
||||
|
||||
args.add(type);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public Type build() {
|
||||
if (parent != null) {
|
||||
throw new TypeException("expect endSubType() before build()");
|
||||
}
|
||||
|
||||
return getType();
|
||||
}
|
||||
|
||||
private Type getType() {
|
||||
if (args.isEmpty()) {
|
||||
return raw;
|
||||
}
|
||||
return new ParameterizedTypeImpl(raw, args.toArray(new Type[args.size()]), null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2016 ikidou
|
||||
*
|
||||
* 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 ikidou.reflect;
|
||||
|
||||
import ikidou.reflect.exception.TypeException;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public abstract class TypeToken<T> {
|
||||
private final Type type;
|
||||
|
||||
public TypeToken() {
|
||||
Type superclass = getClass().getGenericSuperclass();
|
||||
if (superclass instanceof Class) {
|
||||
throw new TypeException("No generics found!");
|
||||
}
|
||||
ParameterizedType type = (ParameterizedType) superclass;
|
||||
this.type = type.getActualTypeArguments()[0];
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2016 ikidou
|
||||
*
|
||||
* 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 ikidou.reflect.exception;
|
||||
|
||||
public class TypeException extends RuntimeException {
|
||||
public TypeException() {
|
||||
}
|
||||
|
||||
public TypeException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public TypeException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public TypeException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public TypeException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 2016 ikidou
|
||||
*
|
||||
* 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 ikidou.reflect.typeimpl;
|
||||
|
||||
import ikidou.reflect.exception.TypeException;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.TypeVariable;
|
||||
import java.util.Arrays;
|
||||
|
||||
@SuppressWarnings("SpellCheckingInspection")
|
||||
public class ParameterizedTypeImpl implements ParameterizedType {
|
||||
private final Class raw;
|
||||
private final Type[] args;
|
||||
private final Type owner;
|
||||
|
||||
public ParameterizedTypeImpl(Class raw, Type[] args, Type owner) {
|
||||
this.raw = raw;
|
||||
this.args = args != null ? args : new Type[0];
|
||||
this.owner = owner;
|
||||
checkArgs();
|
||||
}
|
||||
|
||||
private void checkArgs() {
|
||||
if (raw == null) {
|
||||
throw new TypeException("raw class can't be null");
|
||||
}
|
||||
TypeVariable[] typeParameters = raw.getTypeParameters();
|
||||
if (args.length != 0 && typeParameters.length != args.length) {
|
||||
throw new TypeException(raw.getName() + " expect " + typeParameters.length + " arg(s), got " + args.length);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getActualTypeArguments() {
|
||||
return args;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getRawType() {
|
||||
return raw;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getOwnerType() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(raw.getName());
|
||||
if (args.length != 0) {
|
||||
sb.append('<');
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
if (i != 0) {
|
||||
sb.append(", ");
|
||||
}
|
||||
Type type = args[i];
|
||||
if (type instanceof Class) {
|
||||
Class clazz = (Class) type;
|
||||
|
||||
if (clazz.isArray()) {
|
||||
int count = 0;
|
||||
do {
|
||||
count++;
|
||||
clazz = clazz.getComponentType();
|
||||
} while (clazz.isArray());
|
||||
|
||||
sb.append(clazz.getName());
|
||||
|
||||
for (int j = count; j > 0; j--) {
|
||||
sb.append("[]");
|
||||
}
|
||||
} else {
|
||||
sb.append(clazz.getName());
|
||||
}
|
||||
} else {
|
||||
sb.append(args[i].toString());
|
||||
}
|
||||
}
|
||||
sb.append('>');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ParameterizedTypeImpl that = (ParameterizedTypeImpl) o;
|
||||
|
||||
if (!raw.equals(that.raw)) return false;
|
||||
// Probably incorrect - comparing Object[] arrays with Arrays.equals
|
||||
if (!Arrays.equals(args, that.args)) return false;
|
||||
return owner != null ? owner.equals(that.owner) : that.owner == null;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = raw.hashCode();
|
||||
result = 31 * result + Arrays.hashCode(args);
|
||||
result = 31 * result + (owner != null ? owner.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright 2016 ikidou
|
||||
*
|
||||
* 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 ikidou.reflect.typeimpl;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.WildcardType;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class WildcardTypeImpl implements WildcardType {
|
||||
private final Class[] upper;
|
||||
private final Class[] lower;
|
||||
|
||||
public WildcardTypeImpl(Class[] lower, Class[] upper) {
|
||||
this.lower = lower != null ? lower : new Class[0];
|
||||
this.upper = upper != null ? upper : new Class[0];
|
||||
|
||||
checkArgs();
|
||||
}
|
||||
|
||||
private void checkArgs() {
|
||||
if (lower.length == 0 && upper.length == 0) {
|
||||
throw new IllegalArgumentException("lower or upper can't be null");
|
||||
}
|
||||
|
||||
checkArgs(lower);
|
||||
checkArgs(upper);
|
||||
}
|
||||
|
||||
private void checkArgs(Class[] args) {
|
||||
for (int i = 1; i < args.length; i++) {
|
||||
Class clazz = args[i];
|
||||
if (!clazz.isInterface()) {
|
||||
throw new IllegalArgumentException(clazz.getName() + " not a interface!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getUpperBounds() {
|
||||
return upper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type[] getLowerBounds() {
|
||||
return lower;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (upper.length > 0) {
|
||||
if (upper[0] == Object.class) {
|
||||
return "?";
|
||||
}
|
||||
return getTypeString("? extends ", upper);
|
||||
} else {
|
||||
return getTypeString("? super ", lower);
|
||||
}
|
||||
}
|
||||
|
||||
private String getTypeString(String prefix, Class[] type) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(prefix);
|
||||
|
||||
for (int i = 0; i < type.length; i++) {
|
||||
if (i != 0) {
|
||||
sb.append(" & ");
|
||||
}
|
||||
sb.append(type[i].getName());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
WildcardTypeImpl that = (WildcardTypeImpl) o;
|
||||
|
||||
return Arrays.equals(upper, that.upper) && Arrays.equals(lower, that.lower);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = Arrays.hashCode(upper);
|
||||
result = 31 * result + Arrays.hashCode(lower);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package net.xmeter;
|
||||
|
||||
public interface Constants {
|
||||
public static final String SERVER = "mqtt.server";
|
||||
public static final String MQTT_VERSION = "mqtt.version";
|
||||
public static final String PORT = "mqtt.port";
|
||||
public static final String CONN_TIMEOUT = "mqtt.conn_timeout";
|
||||
|
||||
public static final String PROTOCOL = "mqtt.protocol";
|
||||
|
||||
public static final String USER_NAME_AUTH = "mqtt.user_name";
|
||||
public static final String USER_NAME_PREFIX = "mqtt.user_name_prefix";
|
||||
|
||||
public static final String CONN_KEEP_TIME = "mqtt.keep_time";
|
||||
public static final String CONN_CLIENT_ID_PREFIX = "mqtt.client_id_prefix";
|
||||
public static final String CONN_CLIENT_ID_SUFFIX = "mqtt.client_id_suffix";
|
||||
|
||||
public static final String CONN_ATTAMPT_MAX = "mqtt.conn_attampt_max";
|
||||
public static final String CONN_KEEP_ALIVE = "mqtt.conn_keep_alive";
|
||||
public static final String CONN_RECONN_ATTAMPT_MAX = "mqtt.reconn_attampt_max";
|
||||
public static final String CONN_SHARE_CONNECTION = "mqtt.conn_share";
|
||||
|
||||
public static final String MESSAGE_TYPE = "mqtt.message_type";
|
||||
public static final String MESSAGE_FIX_LENGTH = "mqtt.message_type_fixed_length";
|
||||
public static final String MESSAGE_TO_BE_SENT = "mqtt.message_to_sent";
|
||||
|
||||
public static final String TOPIC_NAME = "mqtt.topic_name";
|
||||
public static final String QOS_LEVEL = "mqtt.qos_level";
|
||||
public static final String ADD_TIMESTAMP = "mqtt.add_timestamp";
|
||||
|
||||
public static final String SAMPLE_CONDITION_VALUE = "mqtt.sample_condition_value";
|
||||
public static final String SAMPLE_CONDITION = "mqtt.sample_condition";
|
||||
|
||||
public static final String TIME_STAMP_SEP_FLAG = "ts_sep_flag";
|
||||
|
||||
public static final String DEBUG_RESPONSE = "mqtt.debug_response";
|
||||
|
||||
public static final int QOS_0 = 0;
|
||||
public static final int QOS_1 = 1;
|
||||
public static final int QOS_2 = 2;
|
||||
|
||||
public static final String MESSAGE_TYPE_RANDOM_STR_WITH_FIX_LEN = "Random string with fixed length";
|
||||
public static final String MESSAGE_TYPE_HEX_STRING = "Hex string";
|
||||
public static final String MESSAGE_TYPE_STRING = "String";
|
||||
|
||||
public static final String MQTT_VERSION_3_1_1 = "3.1.1";
|
||||
public static final String MQTT_VERSION_3_1 = "3.1";
|
||||
|
||||
public static final String SAMPLE_ON_CONDITION_OPTION1 = "specified elapsed time (ms)";
|
||||
public static final String SAMPLE_ON_CONDITION_OPTION2 = "number of received messages";
|
||||
|
||||
public static final int MAX_CLIENT_ID_LENGTH = 23;
|
||||
|
||||
public static final String DEFAULT_SERVER = "127.0.0.1";
|
||||
public static final String DEFAULT_MQTT_VERSION = "3.1";
|
||||
public static final String DEFAULT_PORT = "8080";
|
||||
public static final String DEFAULT_CONN_TIME_OUT = "10";
|
||||
public static final String DEFAULT_PROTOCOL = "TCP";
|
||||
public static final boolean DEFAULT_CONNECTION_SHARE = true;
|
||||
|
||||
public static final String JMETER_VARIABLE_PREFIX = "${";
|
||||
|
||||
public static final String DEFAULT_TOPIC_NAME = "test_topic";
|
||||
|
||||
public static final String DEFAULT_TARGET = "test_user";
|
||||
|
||||
public static final String CONV_TYPE_SINGLE = "Single";
|
||||
public static final String CONV_TYPE_GROUP = "Group";
|
||||
|
||||
public static final String DEFAULT_CONN_PREFIX_FOR_CONN = "conn_";
|
||||
public static final String DEFAULT_CONN_PREFIX_FOR_PUB = "pub_";
|
||||
|
||||
public static final String DEFAULT_CONN_KEEP_ALIVE = "300";
|
||||
public static final String DEFAULT_CONN_KEEP_TIME = "1800";
|
||||
public static final String DEFAULT_CONN_ATTAMPT_MAX = "0";
|
||||
public static final String DEFAULT_CONN_RECONN_ATTAMPT_MAX = "0";
|
||||
|
||||
public static final String DEFAULT_SAMPLE_VALUE_COUNT = "1";
|
||||
public static final String DEFAULT_SAMPLE_VALUE_ELAPSED_TIME_SEC = "1000";
|
||||
|
||||
public static final boolean DEFAULT_ADD_TIMESTAMP = false;
|
||||
public static final String DEFAULT_MESSAGE_FIX_LENGTH = "1024";
|
||||
|
||||
public static final boolean DEFAULT_ADD_CLIENT_ID_SUFFIX = true;
|
||||
|
||||
public static final String TARGET = "wildfire.target";
|
||||
|
||||
public static final String CONV_TYPE = "wildfire.conv_type";
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
package net.xmeter;
|
||||
|
||||
public class IMResult<T> {
|
||||
public enum IMResultCode {
|
||||
//General error
|
||||
IMRESULT_CODE_SUCCESS(0, "success"),
|
||||
IMRESULT_CODE_SECRECT_KEY_MISMATCH(1, "secrect key mismatch"),
|
||||
IMRESULT_CODE_INVALID_DATA(2, "invalid data"),
|
||||
IMRESULT_CODE_NODE_NOT_EXIST(3, "node not exist"),
|
||||
IMRESULT_CODE_SERVER_ERROR(4, "server error"),
|
||||
IMRESULT_CODE_NOT_MODIFIED(5, "not modified"),
|
||||
|
||||
|
||||
//Auth error
|
||||
IMRESULT_CODE_TOKEN_ERROR(6, "token error"),
|
||||
IMRESULT_CODE_USER_FORBIDDEN(8, "user forbidden"),
|
||||
|
||||
//Message error
|
||||
IMRESULT_CODE_NOT_IN_GROUP(9, "not in group"),
|
||||
IMRESULT_CODE_INVALID_MESSAGE(10, "invalid message"),
|
||||
|
||||
//Group error
|
||||
IMRESULT_CODE_GROUP_ALREADY_EXIST(11, "group aleady exist"),
|
||||
|
||||
|
||||
//user error
|
||||
IMRESULT_CODE_PASSWORD_INCORRECT(15, "password incorrect"),
|
||||
|
||||
//user error
|
||||
IMRESULT_CODE_FRIEND_ALREADY_REQUEST(16, "already send request"),
|
||||
IMRESULT_CODE_FRIEND_REQUEST_BLOCKED(18, "friend request blocked"),
|
||||
IMRESULT_CODE_FRIEND_REQUEST_OVERTIME(19, "friend request overtime"),
|
||||
|
||||
IMRESULT_CODE_NOT_IN_CHATROOM(20, "not in chatroom"),
|
||||
|
||||
IMRESULT_CODE_CLIENT_COUNT_OUT_OF_LIMIT(245, "client count out of limit"),
|
||||
IMRESULT_CODE_IN_BLACK_LIST(246, "user in balck list"),
|
||||
IMRESULT_CODE_FORBIDDEN_SEND_MSG(247, "forbidden send msg globally"),
|
||||
IMRESULT_CODE_NOT_RIGHT(248, "no right to operate"),
|
||||
IMRESULT_CODE_TIMEOUT(249, "timeout"),
|
||||
IMRESULT_CODE_OVER_FREQUENCY(250, "over frequency"),
|
||||
INVALID_PARAMETER(251, "Invalid parameter"),
|
||||
IMRESULT_CODE_NOT_EXIST(253, "not exist"),
|
||||
IMRESULT_CODE_NOT_IMPLEMENT(254, "not implement"),
|
||||
|
||||
|
||||
IMRESULT_CODE_ASYNC_HANDLER(255, "异步执行,服务器内部逻辑需要此代码,为正常情况,不能返回客户端"),;
|
||||
|
||||
public int code;
|
||||
public String msg;
|
||||
|
||||
IMResultCode(int code, String msg) {
|
||||
this.code = code;
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public static IMResultCode fromCode(int code) {
|
||||
for (IMResultCode errorCode : IMResultCode.values()) {
|
||||
if(errorCode.code == code) {
|
||||
return errorCode;
|
||||
}
|
||||
}
|
||||
return IMRESULT_CODE_SERVER_ERROR;
|
||||
}
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public int code;
|
||||
public String msg;
|
||||
public T result;
|
||||
|
||||
public int getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public String getMsg() {
|
||||
return msg;
|
||||
}
|
||||
|
||||
public void setMsg(String msg) {
|
||||
this.msg = msg;
|
||||
}
|
||||
|
||||
public T getResult() {
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setResult(T result) {
|
||||
this.result = result;
|
||||
}
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
package net.xmeter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SubBean {
|
||||
private int receivedMessageSize = 0;
|
||||
private int receivedCount = 0;
|
||||
private double avgElapsedTime = 0f;
|
||||
|
||||
private List<String> contents = new ArrayList<String>();
|
||||
|
||||
public int getReceivedMessageSize() {
|
||||
return receivedMessageSize;
|
||||
}
|
||||
|
||||
public void setReceivedMessageSize(int receivedMessageSize) {
|
||||
this.receivedMessageSize = receivedMessageSize;
|
||||
}
|
||||
|
||||
public int getReceivedCount() {
|
||||
return receivedCount;
|
||||
}
|
||||
|
||||
public void setReceivedCount(int receivedCount) {
|
||||
this.receivedCount = receivedCount;
|
||||
}
|
||||
|
||||
public double getAvgElapsedTime() {
|
||||
return avgElapsedTime;
|
||||
}
|
||||
|
||||
public void setAvgElapsedTime(double avgElapsedTime) {
|
||||
this.avgElapsedTime = avgElapsedTime;
|
||||
}
|
||||
|
||||
public List<String> getContents() {
|
||||
return contents;
|
||||
}
|
||||
|
||||
public void setContents(List<String> contents) {
|
||||
this.contents = contents;
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package net.xmeter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.UUID;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
import javax.net.ssl.TrustManager;
|
||||
import javax.net.ssl.X509TrustManager;
|
||||
|
||||
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||
import org.apache.http.ssl.SSLContexts;
|
||||
import org.apache.jmeter.services.FileServer;
|
||||
import org.apache.jorphan.logging.LoggingManager;
|
||||
import org.apache.log.Logger;
|
||||
|
||||
import net.xmeter.samplers.AbstractMQTTSampler;
|
||||
|
||||
public class Util implements Constants {
|
||||
|
||||
private static SecureRandom random = new SecureRandom();
|
||||
private static char[] seeds = "abcdefghijklmnopqrstuvwxmy0123456789".toCharArray();
|
||||
private transient static Logger logger = LoggingManager.getLoggerForClass();
|
||||
|
||||
public static String generateClientId(String prefix) {
|
||||
int leng = prefix.length();
|
||||
int postLeng = MAX_CLIENT_ID_LENGTH - leng;
|
||||
UUID uuid = UUID.randomUUID();
|
||||
String string = uuid.toString().replace("-", "");
|
||||
String post = string.substring(0, postLeng);
|
||||
return prefix + post;
|
||||
}
|
||||
|
||||
public static String generatePayload(int size) {
|
||||
StringBuffer res = new StringBuffer();
|
||||
for(int i = 0; i < size; i++) {
|
||||
res.append(seeds[random.nextInt(seeds.length - 1)]);
|
||||
}
|
||||
return res.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package net.xmeter.gui;
|
||||
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import org.apache.jmeter.gui.util.HorizontalPanel;
|
||||
import org.apache.jmeter.gui.util.VerticalPanel;
|
||||
import org.apache.jorphan.gui.JLabeledTextField;
|
||||
|
||||
import net.xmeter.Constants;
|
||||
import net.xmeter.samplers.AbstractMQTTSampler;
|
||||
|
||||
public class CommonConnUI implements ChangeListener, ActionListener, Constants{
|
||||
private final JLabeledTextField serverAddr = new JLabeledTextField("Server name or IP:");
|
||||
private final JLabeledTextField serverPort = new JLabeledTextField("Port number:", 5);
|
||||
private JCheckBox connShared = new JCheckBox("Share conn in thread");
|
||||
private final JLabeledTextField timeout = new JLabeledTextField("Timeout(s):", 5);
|
||||
|
||||
private final JLabeledTextField userNameAuth = new JLabeledTextField("User name:");
|
||||
private JCheckBox userNameSuffix = new JCheckBox("Add random suffix for user name");
|
||||
|
||||
public final JLabeledTextField connNamePrefix = new JLabeledTextField("ClientId:", 8);
|
||||
private JCheckBox connNameSuffix = new JCheckBox("Add random suffix for ClientId");
|
||||
|
||||
private final JLabeledTextField connKeepAlive = new JLabeledTextField("Keep alive(s):", 4);
|
||||
|
||||
private final JLabeledTextField connKeeptime = new JLabeledTextField("Connection keep time(s):", 4);
|
||||
|
||||
private final JLabeledTextField connAttmptMax = new JLabeledTextField("Connect attampt max:", 0);
|
||||
private final JLabeledTextField reconnAttmptMax = new JLabeledTextField("Reconnect attampt max:", 0);
|
||||
|
||||
public JPanel createConnPanel() {
|
||||
JPanel con = new HorizontalPanel();
|
||||
|
||||
JPanel connPanel = new HorizontalPanel();
|
||||
connPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "MQTT connection"));
|
||||
connPanel.add(serverAddr);
|
||||
connPanel.add(serverPort);
|
||||
connPanel.add(connShared);
|
||||
|
||||
JPanel timeoutPannel = new HorizontalPanel();
|
||||
timeoutPannel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Timeout"));
|
||||
timeoutPannel.add(timeout);
|
||||
|
||||
con.add(connPanel);
|
||||
con.add(timeoutPannel);
|
||||
return con;
|
||||
}
|
||||
|
||||
public JPanel createConnOptions() {
|
||||
JPanel optsPanelCon = new VerticalPanel();
|
||||
optsPanelCon.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Connection options"));
|
||||
|
||||
JPanel optsPanel0 = new HorizontalPanel();
|
||||
optsPanel0.add(connNamePrefix);
|
||||
optsPanel0.add(connNameSuffix);
|
||||
connNameSuffix.setSelected(true);
|
||||
optsPanelCon.add(optsPanel0);
|
||||
|
||||
JPanel optsPanel1 = new HorizontalPanel();
|
||||
optsPanel1.add(connKeepAlive);
|
||||
optsPanel1.add(connKeeptime);
|
||||
optsPanelCon.add(optsPanel1);
|
||||
|
||||
optsPanel1.add(connAttmptMax);
|
||||
optsPanel1.add(reconnAttmptMax);
|
||||
optsPanelCon.add(optsPanel1);
|
||||
|
||||
return optsPanelCon;
|
||||
}
|
||||
|
||||
public JPanel createAuthentication() {
|
||||
JPanel optsPanelCon = new VerticalPanel();
|
||||
optsPanelCon.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "User authentication"));
|
||||
|
||||
JPanel optsPanel = new HorizontalPanel();
|
||||
optsPanel.add(userNameAuth);
|
||||
optsPanel.add(userNameSuffix);
|
||||
optsPanelCon.add(optsPanel);
|
||||
|
||||
return optsPanelCon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
String action = e.getActionCommand();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
}
|
||||
|
||||
public void configure(AbstractMQTTSampler sampler) {
|
||||
serverAddr.setText(sampler.getServer());
|
||||
serverPort.setText(sampler.getPort());
|
||||
connShared.setSelected(sampler.isConnectionShare());
|
||||
if(!sampler.isConnectionShareShow()) {
|
||||
connShared.setVisible(false);
|
||||
}
|
||||
timeout.setText(sampler.getConnTimeout());
|
||||
|
||||
userNameAuth.setText(sampler.getUserNameProperty());
|
||||
userNameSuffix.setSelected(sampler.isUserNamePrefix());
|
||||
|
||||
connNamePrefix.setText(sampler.getConnPrefix());
|
||||
if(sampler.isClientIdSuffix()) {
|
||||
connNameSuffix.setSelected(true);
|
||||
} else {
|
||||
connNameSuffix.setSelected(false);
|
||||
}
|
||||
|
||||
connKeepAlive.setText(sampler.getConnKeepAlive());
|
||||
connKeeptime.setText(sampler.getConnKeepTime());
|
||||
if(!sampler.isKeepTimeShow()) {
|
||||
connKeeptime.setVisible(false);
|
||||
}
|
||||
connAttmptMax.setText(sampler.getConnAttamptMax());
|
||||
reconnAttmptMax.setText(sampler.getConnReconnAttamptMax());
|
||||
}
|
||||
|
||||
|
||||
public void setupSamplerProperties(AbstractMQTTSampler sampler) {
|
||||
sampler.setServer(serverAddr.getText());
|
||||
sampler.setPort(serverPort.getText());
|
||||
sampler.setConnectionShare(connShared.isSelected());
|
||||
sampler.setConnTimeout(timeout.getText());
|
||||
sampler.setConnectionShare(connShared.isSelected());
|
||||
|
||||
sampler.setUserNameAuth(userNameAuth.getText());
|
||||
sampler.setUserNamePrefix(userNameSuffix.isSelected());
|
||||
|
||||
sampler.setConnPrefix(connNamePrefix.getText());
|
||||
sampler.setClientIdSuffix(connNameSuffix.isSelected());
|
||||
|
||||
sampler.setConnKeepAlive(connKeepAlive.getText());
|
||||
sampler.setConnKeepTime(connKeeptime.getText());
|
||||
sampler.setConnAttamptMax(connAttmptMax.getText());
|
||||
sampler.setConnReconnAttamptMax(reconnAttmptMax.getText());
|
||||
}
|
||||
|
||||
public static int parseInt(String value) {
|
||||
if(value == null || "".equals(value.trim())) {
|
||||
return 0;
|
||||
}
|
||||
return Integer.parseInt(value);
|
||||
}
|
||||
|
||||
public void clearUI() {
|
||||
serverAddr.setText(DEFAULT_SERVER);
|
||||
serverPort.setText(DEFAULT_PORT);
|
||||
connShared.setSelected(DEFAULT_CONNECTION_SHARE);
|
||||
timeout.setText(DEFAULT_CONN_TIME_OUT);
|
||||
|
||||
|
||||
userNameAuth.setText("");
|
||||
userNameSuffix.setSelected(true);
|
||||
|
||||
connNamePrefix.setText(DEFAULT_CONN_PREFIX_FOR_CONN);
|
||||
connNameSuffix.setSelected(true);
|
||||
|
||||
connKeepAlive.setText(DEFAULT_CONN_KEEP_ALIVE);
|
||||
connKeeptime.setText(DEFAULT_CONN_KEEP_TIME);
|
||||
connAttmptMax.setText(DEFAULT_CONN_ATTAMPT_MAX);
|
||||
reconnAttmptMax.setText(DEFAULT_CONN_RECONN_ATTAMPT_MAX);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package net.xmeter.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import org.apache.jmeter.gui.util.VerticalPanel;
|
||||
import org.apache.jmeter.samplers.gui.AbstractSamplerGui;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jorphan.logging.LoggingManager;
|
||||
import org.apache.log.Logger;
|
||||
|
||||
import net.xmeter.Constants;
|
||||
import net.xmeter.samplers.ConnectionSampler;
|
||||
|
||||
public class ConnectionSamplerUI extends AbstractSamplerGui implements Constants {
|
||||
private static final Logger logger = LoggingManager.getLoggerForClass();
|
||||
private CommonConnUI connUI = new CommonConnUI();
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1666890646673145131L;
|
||||
|
||||
public ConnectionSamplerUI() {
|
||||
this.init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
logger.info("Initializing the UI.");
|
||||
logger.info("Initializing the UI2.");
|
||||
setLayout(new BorderLayout());
|
||||
setBorder(makeBorder());
|
||||
|
||||
add(makeTitlePanel(), BorderLayout.NORTH);
|
||||
JPanel mainPanel = new VerticalPanel();
|
||||
add(mainPanel, BorderLayout.CENTER);
|
||||
|
||||
mainPanel.add(connUI.createConnPanel());
|
||||
mainPanel.add(connUI.createAuthentication());
|
||||
mainPanel.add(connUI.createConnOptions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(TestElement element) {
|
||||
super.configure(element);
|
||||
ConnectionSampler sampler = (ConnectionSampler)element;
|
||||
connUI.configure(sampler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestElement createTestElement() {
|
||||
ConnectionSampler sampler = new ConnectionSampler();
|
||||
this.configureTestElement(sampler);
|
||||
connUI.setupSamplerProperties(sampler);
|
||||
return sampler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabelResource() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStaticLabel() {
|
||||
return "Wildfire Connection Sampler";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyTestElement(TestElement arg0) {
|
||||
ConnectionSampler sampler = (ConnectionSampler)arg0;
|
||||
this.configureTestElement(sampler);
|
||||
connUI.setupSamplerProperties(sampler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearGui() {
|
||||
super.clearGui();
|
||||
connUI.clearUI();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
package net.xmeter.gui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
|
||||
import javax.swing.BorderFactory;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
import net.xmeter.samplers.SendMessageSampler;
|
||||
import org.apache.jmeter.gui.util.HorizontalPanel;
|
||||
import org.apache.jmeter.gui.util.JSyntaxTextArea;
|
||||
import org.apache.jmeter.gui.util.JTextScrollPane;
|
||||
import org.apache.jmeter.gui.util.VerticalPanel;
|
||||
import org.apache.jmeter.samplers.gui.AbstractSamplerGui;
|
||||
import org.apache.jmeter.testelement.TestElement;
|
||||
import org.apache.jorphan.gui.JLabeledChoice;
|
||||
import org.apache.jorphan.gui.JLabeledTextField;
|
||||
import org.apache.jorphan.logging.LoggingManager;
|
||||
import org.apache.log.Logger;
|
||||
|
||||
import net.xmeter.Constants;
|
||||
|
||||
public class SendMessageSamplerUI extends AbstractSamplerGui implements Constants, ChangeListener {
|
||||
private static final Logger logger = LoggingManager.getLoggerForClass();
|
||||
private CommonConnUI connUI = new CommonConnUI();
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 2479085966683186422L;
|
||||
|
||||
private JLabeledChoice conversationTypeChoice;
|
||||
private final JLabeledTextField target = new JLabeledTextField("Target:");
|
||||
// private JCheckBox timestamp = new JCheckBox("Add timestamp in payload");
|
||||
|
||||
private final JSyntaxTextArea sendMessage = JSyntaxTextArea.getInstance(10, 50);
|
||||
private final JTextScrollPane messagePanel = JTextScrollPane.getInstance(sendMessage);
|
||||
// private JLabeledTextField stringLength = new JLabeledTextField("Length:");
|
||||
|
||||
public SendMessageSamplerUI() {
|
||||
init();
|
||||
}
|
||||
|
||||
private void init() {
|
||||
logger.info("Initializing the UI.");
|
||||
setLayout(new BorderLayout());
|
||||
setBorder(makeBorder());
|
||||
|
||||
add(makeTitlePanel(), BorderLayout.NORTH);
|
||||
JPanel mainPanel = new VerticalPanel();
|
||||
add(mainPanel, BorderLayout.CENTER);
|
||||
|
||||
mainPanel.add(connUI.createConnPanel());
|
||||
mainPanel.add(connUI.createAuthentication());
|
||||
mainPanel.add(connUI.createConnOptions());
|
||||
|
||||
mainPanel.add(createPubOption());
|
||||
mainPanel.add(createPayload());
|
||||
}
|
||||
|
||||
private JPanel createPubOption() {
|
||||
JPanel optsPanelCon = new VerticalPanel();
|
||||
optsPanelCon.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Send message options"));
|
||||
|
||||
conversationTypeChoice = new JLabeledChoice("ConversationType:", new String[] { CONV_TYPE_SINGLE, CONV_TYPE_GROUP }, true, false);
|
||||
conversationTypeChoice.addChangeListener(this);
|
||||
|
||||
JPanel optsPanel = new HorizontalPanel();
|
||||
optsPanel.add(conversationTypeChoice);
|
||||
optsPanel.add(target);
|
||||
// optsPanel.add(timestamp);
|
||||
optsPanelCon.add(optsPanel);
|
||||
|
||||
return optsPanelCon;
|
||||
}
|
||||
|
||||
private JPanel createPayload() {
|
||||
JPanel optsPanelCon = new VerticalPanel();
|
||||
optsPanelCon.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "Message Content"));
|
||||
|
||||
// JPanel horizon1 = new HorizontalPanel();
|
||||
//
|
||||
// stringLength.setVisible(true);
|
||||
// horizon1.add(stringLength);
|
||||
|
||||
JPanel horizon2 = new VerticalPanel();
|
||||
messagePanel.setVisible(true);
|
||||
horizon2.add(messagePanel);
|
||||
|
||||
// optsPanelCon.add(horizon1);
|
||||
optsPanelCon.add(horizon2);
|
||||
return optsPanelCon;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStaticLabel() {
|
||||
return "Wildfire Send Message Sampler";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent e) {
|
||||
// if(e.getSource() == this.messageTypes) {
|
||||
// int selectedIndex = this.messageTypes.getSelectedIndex();
|
||||
// if(selectedIndex == 0 || selectedIndex == 1) {
|
||||
// stringLength.setVisible(false);
|
||||
// messagePanel.setVisible(true);
|
||||
// } else if(selectedIndex == 2) {
|
||||
// messagePanel.setVisible(false);
|
||||
// stringLength.setVisible(true);
|
||||
// } else {
|
||||
// logger.info("Unknown message type.");
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLabelResource() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public TestElement createTestElement() {
|
||||
logger.info("createTestElement called.");
|
||||
SendMessageSampler sampler = new SendMessageSampler();
|
||||
this.setupSamplerProperties(sampler);
|
||||
connUI.setupSamplerProperties(sampler);
|
||||
return sampler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void configure(TestElement element) {
|
||||
logger.info("configure called.");
|
||||
super.configure(element);
|
||||
SendMessageSampler sampler = (SendMessageSampler) element;
|
||||
|
||||
connUI.configure(sampler);
|
||||
// if(sampler.getQOS().trim().indexOf(JMETER_VARIABLE_PREFIX) == -1){
|
||||
this.conversationTypeChoice.setSelectedIndex(0);
|
||||
// } else {
|
||||
// this.conversationTypeChoice.setText(sampler.getQOS());
|
||||
// }
|
||||
|
||||
this.target.setText(sampler.getTopic());
|
||||
// this.timestamp.setSelected(sampler.isAddTimestamp());
|
||||
// if(MESSAGE_TYPE_STRING.equalsIgnoreCase(sampler.getMessageType())) {
|
||||
// this.messageTypes.setSelectedIndex(0);
|
||||
// this.messagePanel.setVisible(true);
|
||||
// } else if(MESSAGE_TYPE_HEX_STRING.equalsIgnoreCase(sampler.getMessageType())) {
|
||||
// this.messageTypes.setSelectedIndex(1);
|
||||
// } else if(MESSAGE_TYPE_RANDOM_STR_WITH_FIX_LEN.equalsIgnoreCase(sampler.getMessageType())) {
|
||||
// this.messageTypes.setSelectedIndex(2);
|
||||
// }
|
||||
//
|
||||
// stringLength.setText(String.valueOf(sampler.getMessageLength()));
|
||||
sendMessage.setText(sampler.getMessage());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void modifyTestElement(TestElement arg0) {
|
||||
logger.info("modifyTestElement called.");
|
||||
SendMessageSampler sampler = (SendMessageSampler) arg0;
|
||||
this.setupSamplerProperties(sampler);
|
||||
connUI.setupSamplerProperties(sampler);
|
||||
}
|
||||
|
||||
private void setupSamplerProperties(SendMessageSampler sampler) {
|
||||
this.configureTestElement(sampler);
|
||||
connUI.setupSamplerProperties(sampler);
|
||||
|
||||
sampler.setTarget(this.target.getText());
|
||||
|
||||
// if(this.conversationTypeChoice.getText().indexOf(JMETER_VARIABLE_PREFIX) == -1) {
|
||||
// int qos = QOS_0;
|
||||
// try {
|
||||
// qos = Integer.parseInt(this.conversationTypeChoice.getText());
|
||||
// if (qos < QOS_0 || qos > QOS_2) {
|
||||
// qos = QOS_0;
|
||||
// logger.info("Invalid QoS value, set to default QoS value 0.");
|
||||
// }
|
||||
// } catch (Exception ex) {
|
||||
// logger.info("Invalid QoS value, set to default QoS value 0.");
|
||||
// qos = QOS_0;
|
||||
// }
|
||||
// sampler.setQOS(String.valueOf(qos));
|
||||
// } else {
|
||||
// sampler.setQOS(this.conversationTypeChoice.getText());
|
||||
// }
|
||||
|
||||
// sampler.setAddTimestamp(this.timestamp.isSelected());
|
||||
// sampler.setMessageType(this.messageTypes.getText());
|
||||
// sampler.setMessageLength(this.stringLength.getText());
|
||||
sampler.setMessage(this.sendMessage.getText());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clearGui() {
|
||||
logger.info("clearGui called.");
|
||||
super.clearGui();
|
||||
connUI.clearUI();
|
||||
connUI.connNamePrefix.setText(DEFAULT_CONN_PREFIX_FOR_PUB);
|
||||
this.target.setText(DEFAULT_TARGET);
|
||||
this.conversationTypeChoice.setText(CONV_TYPE_SINGLE);
|
||||
// this.timestamp.setSelected(false);
|
||||
|
||||
// this.messageTypes.setSelectedIndex(0);
|
||||
// this.stringLength.setText(String.valueOf(DEFAULT_MESSAGE_FIX_LENGTH));
|
||||
this.sendMessage.setText("");
|
||||
}
|
||||
}
|
||||
+361
@@ -0,0 +1,361 @@
|
||||
package net.xmeter.samplers;
|
||||
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import com.google.gson.Gson;
|
||||
import com.xiaoleilu.loServer.pojos.InputRoute;
|
||||
import com.xiaoleilu.loServer.pojos.InputGetToken;
|
||||
import com.xiaoleilu.loServer.pojos.OutputGetIMTokenData;
|
||||
import io.moquette.spi.impl.security.AES;
|
||||
import net.xmeter.IMResult;
|
||||
import net.xmeter.Util;
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.impl.client.HttpClientBuilder;
|
||||
import org.apache.jmeter.samplers.AbstractSampler;
|
||||
|
||||
import net.xmeter.Constants;
|
||||
import org.apache.jorphan.logging.LoggingManager;
|
||||
import org.apache.log.Logger;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Base64;
|
||||
|
||||
public abstract class AbstractMQTTSampler extends AbstractSampler implements Constants {
|
||||
private transient static Logger logger = LoggingManager.getLoggerForClass();
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 7163793218595455807L;
|
||||
|
||||
public String getServer() {
|
||||
return getPropertyAsString(SERVER, DEFAULT_SERVER);
|
||||
}
|
||||
|
||||
public void setServer(String server) {
|
||||
setProperty(SERVER, server);
|
||||
}
|
||||
|
||||
public String getMqttVersion() {
|
||||
return getPropertyAsString(MQTT_VERSION, DEFAULT_MQTT_VERSION);
|
||||
}
|
||||
|
||||
public String getPort() {
|
||||
return getPropertyAsString(PORT, DEFAULT_PORT);
|
||||
}
|
||||
|
||||
public void setPort(String port) {
|
||||
setProperty(PORT, port);
|
||||
}
|
||||
|
||||
public boolean isConnectionShare() {
|
||||
return getPropertyAsBoolean(CONN_SHARE_CONNECTION, DEFAULT_CONNECTION_SHARE);
|
||||
}
|
||||
|
||||
public void setConnectionShare(boolean shared) {
|
||||
setProperty(CONN_SHARE_CONNECTION, shared);
|
||||
}
|
||||
|
||||
public String getConnTimeout() {
|
||||
return getPropertyAsString(CONN_TIMEOUT, DEFAULT_CONN_TIME_OUT);
|
||||
}
|
||||
|
||||
public void setConnTimeout(String connTimeout) {
|
||||
setProperty(CONN_TIMEOUT, connTimeout);
|
||||
}
|
||||
|
||||
public String getProtocol() {
|
||||
return getPropertyAsString(PROTOCOL, DEFAULT_PROTOCOL);
|
||||
}
|
||||
|
||||
public String getConnPrefix() {
|
||||
return getPropertyAsString(CONN_CLIENT_ID_PREFIX, DEFAULT_CONN_PREFIX_FOR_CONN);
|
||||
}
|
||||
|
||||
public void setConnPrefix(String connPrefix) {
|
||||
logger.info("set connprefix:" + connPrefix);
|
||||
setProperty(CONN_CLIENT_ID_PREFIX, connPrefix);
|
||||
}
|
||||
|
||||
public String getConnKeepAlive() {
|
||||
return getPropertyAsString(CONN_KEEP_ALIVE, DEFAULT_CONN_KEEP_ALIVE);
|
||||
}
|
||||
|
||||
public void setConnKeepAlive(String connKeepAlive) {
|
||||
setProperty(CONN_KEEP_ALIVE, connKeepAlive);
|
||||
}
|
||||
|
||||
public boolean isClientIdSuffix() {
|
||||
return getPropertyAsBoolean(CONN_CLIENT_ID_SUFFIX, DEFAULT_ADD_CLIENT_ID_SUFFIX);
|
||||
}
|
||||
|
||||
public void setClientIdSuffix(boolean clientIdSuffix) {
|
||||
setProperty(CONN_CLIENT_ID_SUFFIX, clientIdSuffix);
|
||||
}
|
||||
|
||||
public String getConnKeepTime() {
|
||||
return getPropertyAsString(CONN_KEEP_TIME, DEFAULT_CONN_KEEP_TIME);
|
||||
}
|
||||
|
||||
public void setConnKeepTime(String connKeepTime) {
|
||||
setProperty(CONN_KEEP_TIME, connKeepTime);
|
||||
}
|
||||
|
||||
public String getConnAttamptMax() {
|
||||
return getPropertyAsString(CONN_ATTAMPT_MAX, DEFAULT_CONN_ATTAMPT_MAX);
|
||||
}
|
||||
|
||||
public void setConnAttamptMax(String connAttamptMax) {
|
||||
setProperty(CONN_ATTAMPT_MAX, connAttamptMax);
|
||||
}
|
||||
|
||||
public String getConnReconnAttamptMax() {
|
||||
return getPropertyAsString(CONN_RECONN_ATTAMPT_MAX, DEFAULT_CONN_RECONN_ATTAMPT_MAX);
|
||||
}
|
||||
|
||||
public void setConnReconnAttamptMax(String connReconnAttamptMax) {
|
||||
setProperty(CONN_RECONN_ATTAMPT_MAX, connReconnAttamptMax);
|
||||
}
|
||||
|
||||
public String getUserNameProperty() {
|
||||
return getPropertyAsString(USER_NAME_AUTH, "").trim();
|
||||
}
|
||||
|
||||
private String userName;
|
||||
|
||||
public String getUserNameAuth() {
|
||||
if (userName == null) {
|
||||
String prefix = getUserNameProperty();
|
||||
if (isUserNamePrefix()) {
|
||||
userName = Util.generateClientId(prefix);
|
||||
} else {
|
||||
userName = prefix;
|
||||
}
|
||||
}
|
||||
return userName;
|
||||
}
|
||||
|
||||
|
||||
public void setUserNameAuth(String userName) {
|
||||
setProperty(USER_NAME_AUTH, userName);
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public boolean isUserNamePrefix() {
|
||||
return getPropertyAsBoolean(USER_NAME_PREFIX);
|
||||
}
|
||||
|
||||
public void setUserNamePrefix(boolean prefix) {
|
||||
setProperty(USER_NAME_PREFIX, prefix);
|
||||
}
|
||||
|
||||
public boolean isKeepTimeShow() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isConnectionShareShow() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private String clientId;
|
||||
|
||||
protected String getClientId() {
|
||||
if (clientId == null) {
|
||||
if (isClientIdSuffix()) {
|
||||
clientId = Util.generateClientId(getConnPrefix());
|
||||
} else {
|
||||
clientId = getConnPrefix();
|
||||
}
|
||||
}
|
||||
return clientId;
|
||||
}
|
||||
|
||||
protected String mqttServerIp;
|
||||
protected long mqttServerPort;
|
||||
private static byte[] commonSecret= {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x78,0x79,0x7A,0x7B,0x7C,0x7D,0x7E,0x7F};
|
||||
protected String privateSecret;
|
||||
protected String token;
|
||||
|
||||
protected boolean getToken(String userId) {
|
||||
String url = "http://" + getServer() + ":18080/admin/user/token";
|
||||
String adminSecret = "123456";
|
||||
HttpPost post = null;
|
||||
try {
|
||||
HttpClient httpClient = HttpClientBuilder.create().build();
|
||||
|
||||
int nonce = (int)(Math.random() * 100000 + 3);
|
||||
long timestamp = System.currentTimeMillis();
|
||||
String str = nonce + "|" + adminSecret + "|" + timestamp;
|
||||
String sign = DigestUtils.sha1Hex(str);
|
||||
|
||||
|
||||
post = new HttpPost(url);
|
||||
post.setHeader("Content-type", "application/json; charset=utf-8");
|
||||
post.setHeader("Connection", "Keep-Alive");
|
||||
post.setHeader("nonce", nonce + "");
|
||||
post.setHeader("timestamp", "" + timestamp);
|
||||
post.setHeader("sign", sign);
|
||||
|
||||
String jsonStr = new Gson().toJson(new InputGetToken(userId, getClientId()));
|
||||
logger.info("http request content: " + jsonStr);
|
||||
|
||||
StringEntity entity = new StringEntity(jsonStr, Charset.forName("UTF-8"));
|
||||
entity.setContentEncoding("UTF-8");
|
||||
entity.setContentType("application/json");
|
||||
post.setEntity(entity);
|
||||
HttpResponse response = httpClient.execute(post);
|
||||
|
||||
int statusCode = response.getStatusLine().getStatusCode();
|
||||
if(statusCode != HttpStatus.SC_OK){
|
||||
logger.info("Request error: " + statusCode);
|
||||
throw new Exception("Http request error with code:" + statusCode);
|
||||
}else{
|
||||
BufferedReader in = new BufferedReader(new InputStreamReader(response.getEntity()
|
||||
.getContent(),"utf-8"));
|
||||
StringBuffer sb = new StringBuffer();
|
||||
String line;
|
||||
String NL = System.getProperty("line.separator");
|
||||
while ((line = in.readLine()) != null) {
|
||||
sb.append(line + NL);
|
||||
}
|
||||
|
||||
in.close();
|
||||
|
||||
String content = sb.toString();
|
||||
logger.info("http request response content: " + content);
|
||||
|
||||
IMResult<OutputGetIMTokenData> result = fromJsonObject(content, OutputGetIMTokenData.class);
|
||||
if (result == null || result.getCode() != IMResult.IMResultCode.IMRESULT_CODE_SUCCESS.code) {
|
||||
logger.error("get token result failure");
|
||||
return false;
|
||||
}
|
||||
|
||||
OutputGetIMTokenData out = result.getResult();
|
||||
if (out != null && out.getToken() != null) {
|
||||
byte[] data = Base64.getDecoder().decode(out.getToken());
|
||||
if (data != null) {
|
||||
data = AES.AESDecrypt(data, null, true);
|
||||
if (data != null) {
|
||||
String tokensecrets = new String(data);
|
||||
String[] keys = tokensecrets.split("\\|");
|
||||
if (keys.length == 3) {
|
||||
token = keys[0];
|
||||
privateSecret = keys[1];
|
||||
return true;
|
||||
} else {
|
||||
logger.info("get token keys not correct (" + tokensecrets + ")");
|
||||
}
|
||||
} else {
|
||||
logger.info("get token decode token failure");
|
||||
}
|
||||
} else {
|
||||
logger.info("get token decode base64 failure");
|
||||
}
|
||||
} else {
|
||||
logger.info("get token data invalide");
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}finally{
|
||||
if(post != null){
|
||||
post.releaseConnection();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static <T> IMResult<T> fromJsonObject(String content, Class<T> clazz) {
|
||||
Type type = ikidou.reflect.TypeBuilder
|
||||
.newInstance(IMResult.class)
|
||||
.addTypeParam(clazz)
|
||||
.build();
|
||||
return new Gson().fromJson(content, type);
|
||||
}
|
||||
|
||||
protected boolean route(String userId, String token) {
|
||||
HttpPost httpPost;
|
||||
try{
|
||||
HttpClient httpClient = new DefaultHttpClient();
|
||||
httpPost = new HttpPost("http://" + getServer() + ":" + getPort() + "/route");
|
||||
String cid = Base64.getEncoder().encodeToString(AES.AESEncrypt(getClientId().getBytes(), commonSecret));
|
||||
httpPost.setHeader("cid", cid);
|
||||
|
||||
String uid = Base64.getEncoder().encodeToString(AES.AESEncrypt(userId.getBytes(), commonSecret));
|
||||
httpPost.setHeader("uid", uid);
|
||||
|
||||
InputRoute inputRoute = new InputRoute();
|
||||
inputRoute.setUserId(userId);
|
||||
inputRoute.setClientId(getClientId());
|
||||
inputRoute.setToken(token);
|
||||
|
||||
WFCMessage.RouteRequest routeRequest = WFCMessage.RouteRequest.newBuilder().setApp("jmeter.test").setSdkVersion("0.1").build();
|
||||
WFCMessage.IMHttpWrapper request = WFCMessage.IMHttpWrapper.newBuilder().setClientId(getClientId()).setToken(token).setRequest("ROUTE").setData(routeRequest.toByteString()).build();
|
||||
byte[] data = AES.AESEncrypt(request.toByteArray(), privateSecret );
|
||||
data = Base64.getEncoder().encode(data);
|
||||
|
||||
|
||||
StringEntity entity = new StringEntity(new String(data), Charset.forName("UTF-8"));
|
||||
entity.setContentEncoding("UTF-8");
|
||||
entity.setContentType("application/json");
|
||||
httpPost.setEntity(entity);
|
||||
|
||||
|
||||
HttpResponse response = httpClient.execute(httpPost);
|
||||
if(response != null){
|
||||
if (response.getStatusLine().getStatusCode() != 200) {
|
||||
logger.error("Http response error {" + response.getStatusLine().getStatusCode() + "}");
|
||||
return false;
|
||||
}
|
||||
HttpEntity resEntity = response.getEntity();
|
||||
if(resEntity != null){
|
||||
|
||||
try {
|
||||
|
||||
byte[] contentbyte = new byte[(int)response.getEntity().getContentLength()];
|
||||
int readLen = response.getEntity().getContent().read(contentbyte);
|
||||
|
||||
data = new byte[contentbyte.length - 1];
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
data[i] = contentbyte[i+1];
|
||||
}
|
||||
|
||||
data = AES.AESDecrypt(data, privateSecret, true);
|
||||
|
||||
WFCMessage.RouteResponse routeResponse = WFCMessage.RouteResponse.parseFrom(data);
|
||||
mqttServerIp = routeResponse.getHost();
|
||||
mqttServerPort = routeResponse.getLongPort();
|
||||
routeResponse.getShortPort();
|
||||
return true;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
logger.error(e.toString());
|
||||
} catch (UnsupportedOperationException e) {
|
||||
e.printStackTrace();
|
||||
logger.error(e.toString());
|
||||
}
|
||||
} else {
|
||||
logger.error("route response entry is nil");
|
||||
}
|
||||
} else {
|
||||
logger.error("Http response nil");
|
||||
}
|
||||
}catch(IOException ex){
|
||||
ex.printStackTrace();
|
||||
logger.error(ex.toString());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package net.xmeter.samplers;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.apache.jorphan.logging.LoggingManager;
|
||||
import org.apache.log.Logger;
|
||||
import org.apache.log.Priority;
|
||||
import org.fusesource.mqtt.client.Callback;
|
||||
import org.fusesource.mqtt.client.CallbackConnection;
|
||||
|
||||
public class ConnectionCallback implements Callback<byte[]>{
|
||||
private static Logger logger = LoggingManager.getLoggerForClass();
|
||||
private Object connLock;
|
||||
private CallbackConnection connection;
|
||||
private boolean connectionSucc = false;
|
||||
|
||||
public ConnectionCallback(CallbackConnection connection, Object connLock) {
|
||||
this.connection = connection;
|
||||
this.connLock = connLock;
|
||||
}
|
||||
@Override
|
||||
public void onSuccess(byte[] value) {
|
||||
synchronized (connLock) {
|
||||
logger.info(MessageFormat.format("The connection {0} is established successfully.", this.connection + Thread.currentThread().getName()));
|
||||
connectionSucc = true;
|
||||
this.connLock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable value) {
|
||||
synchronized (connLock) {
|
||||
connectionSucc = false;
|
||||
logger.log(Priority.ERROR, value.getMessage(), value);
|
||||
this.connLock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isConnectionSucc() {
|
||||
return connectionSucc;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,222 @@
|
||||
package net.xmeter.samplers;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import io.moquette.spi.impl.security.AES;
|
||||
import org.apache.jmeter.JMeter;
|
||||
import org.apache.jmeter.samplers.Entry;
|
||||
import org.apache.jmeter.samplers.Interruptible;
|
||||
import org.apache.jmeter.samplers.SampleEvent;
|
||||
import org.apache.jmeter.samplers.SampleListener;
|
||||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jmeter.testelement.TestStateListener;
|
||||
import org.apache.jmeter.testelement.ThreadListener;
|
||||
import org.apache.jorphan.logging.LoggingManager;
|
||||
import org.apache.log.Logger;
|
||||
import org.apache.log.Priority;
|
||||
import org.fusesource.hawtbuf.UTF8Buffer;
|
||||
import org.fusesource.mqtt.client.Future;
|
||||
import org.fusesource.mqtt.client.FutureConnection;
|
||||
import org.fusesource.mqtt.client.MQTT;
|
||||
|
||||
public class ConnectionSampler extends AbstractMQTTSampler
|
||||
implements TestStateListener, ThreadListener, Interruptible, SampleListener {
|
||||
private transient static Logger logger = LoggingManager.getLoggerForClass();
|
||||
private transient MQTT mqtt = new MQTT();
|
||||
private transient FutureConnection connection = null;
|
||||
private boolean interrupt = false;
|
||||
//Declare it as static, for the instance variable will be set to initial value 0 in testEnded method.
|
||||
//The static value will not be reset.
|
||||
private static int keepTime = 0;
|
||||
|
||||
private static AtomicBoolean sleepFlag = new AtomicBoolean(false);
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 1859006013465470528L;
|
||||
|
||||
@Override
|
||||
public boolean isKeepTimeShow() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleResult sample(Entry entry) {
|
||||
SampleResult result = new SampleResult();
|
||||
result.setSampleLabel(getName());
|
||||
try {
|
||||
result.sampleStart();
|
||||
|
||||
if (!getToken(getUserNameAuth())) {
|
||||
throw new Exception("get token failure!!!");
|
||||
}
|
||||
|
||||
if (!route(getUserNameAuth(), token)) {
|
||||
throw new Exception("route failure!!!");
|
||||
}
|
||||
|
||||
mqtt.setHost("tcp://" + mqttServerIp + ":" + mqttServerPort);
|
||||
mqtt.setVersion(getMqttVersion());
|
||||
mqtt.setKeepAlive((short) Integer.parseInt(getConnKeepAlive()));
|
||||
|
||||
mqtt.setClientId(getClientId());
|
||||
mqtt.setConnectAttemptsMax(Integer.parseInt(getConnAttamptMax()));
|
||||
mqtt.setReconnectAttemptsMax(Integer.parseInt(getConnReconnAttamptMax()));
|
||||
|
||||
mqtt.setUserName(getUserNameAuth());
|
||||
|
||||
byte[] password = AES.AESEncrypt(token, privateSecret);
|
||||
mqtt.setPassword(new UTF8Buffer(password));
|
||||
|
||||
connection = mqtt.futureConnection();
|
||||
|
||||
Future<byte[]> f1 = connection.connect();
|
||||
f1.await(Integer.parseInt(getConnTimeout()), TimeUnit.SECONDS);
|
||||
|
||||
result.sampleEnd();
|
||||
result.setSuccessful(true);
|
||||
result.setResponseData("Successful.".getBytes());
|
||||
result.setResponseMessage(MessageFormat.format("Connection {0} connected successfully.", connection));
|
||||
result.setResponseCodeOK();
|
||||
} catch (Exception e) {
|
||||
logger.log(Priority.ERROR, e.getMessage(), e);
|
||||
result.sampleEnd();
|
||||
result.setSuccessful(false);
|
||||
result.setResponseMessage(MessageFormat.format("Connection {0} connected failed.", connection));
|
||||
result.setResponseData("Failed.".getBytes());
|
||||
result.setResponseCode("500");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testEnded() {
|
||||
this.testEnded("local");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testEnded(String arg0) {
|
||||
logger.info("in testEnded, isNonGUI=" + JMeter.isNonGUI() + ", sleepFlag=" + sleepFlag.get());
|
||||
this.interrupt = true;
|
||||
|
||||
try {
|
||||
if (JMeter.isNonGUI()) {
|
||||
if(!sleepFlag.get()) {
|
||||
//The keepTime is saved as static variable, because keepTime variable in testEnded()
|
||||
//returns with initial value.
|
||||
logger.info("The work has been done, will keep connection for " + keepTime + " sceconds.");
|
||||
TimeUnit.SECONDS.sleep(keepTime);
|
||||
sleepFlag.set(true);
|
||||
}
|
||||
|
||||
//The following code does not make sense, because the connection variable was already reset.
|
||||
//But it makes sense in threadFinished method.
|
||||
//The reason for not sleeping and then disconnecting in threadFinished is to avoid maintain too much of threads.
|
||||
//Otherwise each thread (for a thread-group) will be kept open before sleeping.
|
||||
/*if(this.connection != null) {
|
||||
this.connection.disconnect();
|
||||
logger.info(MessageFormat.format("The connection {0} disconneted successfully.", connection));
|
||||
}*/
|
||||
}
|
||||
} catch(Exception ex) {
|
||||
logger.error(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testStarted() {
|
||||
this.testStarted("local");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void testStarted(String arg0) {
|
||||
sleepFlag.set(false);
|
||||
keepTime = Integer.parseInt(getConnKeepTime());
|
||||
logger.info("*** Keeptime is: " + keepTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void threadFinished() {
|
||||
|
||||
}
|
||||
|
||||
private void sleepCurrentThreadAndDisconnect() {
|
||||
try {
|
||||
//If the connection is null or does not connect successfully, then not necessary to keep the connection.
|
||||
if(connection == null || (!connection.isConnected())) {
|
||||
if(connection == null) {
|
||||
logger.info("Connection is null.");
|
||||
} else if(!connection.isConnected()) {
|
||||
logger.info("Connection is created, but is not connected.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
long start = System.currentTimeMillis();
|
||||
while ((System.currentTimeMillis() - start) <= TimeUnit.SECONDS.toMillis(keepTime)) {
|
||||
if (this.interrupt) {
|
||||
logger.info("interrupted flag is true, and stop the sleep.");
|
||||
break;
|
||||
}
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error(e.getMessage(), e);
|
||||
} finally {
|
||||
if (connection != null) {
|
||||
try {
|
||||
connection.kill().await();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
logger.log(Priority.INFO, MessageFormat.format("The connection {0} disconneted successfully.", connection));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void threadStarted() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean interrupt() {
|
||||
this.interrupt = true;
|
||||
if (!JMeter.isNonGUI()) {
|
||||
logger.info("In GUI mode, received the interrupt request from user.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Note: JMeter.isNonGUI() only valid when you specify "-n" option from command line,
|
||||
// other cases (such as JMeter GUI, remote engine) all treat isNonGUI() as "false"
|
||||
// So, if you use remote engine, it's actually follow isNonGUI()=false path in this sampler code,
|
||||
// and you can control the test and stop it in JMeter GUI via say "Remote Stop All" button.
|
||||
//
|
||||
// You can also start remote agent with say "jmeter-server -DJMeter.NonGui=true",
|
||||
// in order to fool JMeter to treat isNonGUI() as "true".
|
||||
// However, the interrupt mechanism may not work well with remote engine when stop the remote test from JMeter GUI,
|
||||
// you may need to manually kill remote jmeter process to clean it up.
|
||||
//
|
||||
|
||||
/**
|
||||
* In this listener, it can receive the interrupt event trigger by user.
|
||||
*/
|
||||
@Override
|
||||
public void sampleOccurred(SampleEvent event) {
|
||||
if (!JMeter.isNonGUI() && "Wildfire Connection Sampler".equals(event.getResult().getSampleLabel() )) {
|
||||
logger.info("Created the sampler results, will sleep current thread for " + getConnKeepTime() + " sceconds");
|
||||
sleepCurrentThreadAndDisconnect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sampleStarted(SampleEvent arg0) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sampleStopped(SampleEvent arg0) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package net.xmeter.samplers;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.fusesource.mqtt.client.CallbackConnection;
|
||||
import org.fusesource.mqtt.client.MQTT;
|
||||
|
||||
public class ConnectionsManager {
|
||||
public static class ConnectionInfo {
|
||||
public String userName;
|
||||
public String token;
|
||||
public String privateSecrect;
|
||||
public String serverAddress;
|
||||
public long serverPort;
|
||||
|
||||
public ConnectionInfo(String userName, String token, String privateSecrect, String serverAddress, long serverPort) {
|
||||
this.userName = userName;
|
||||
this.token = token;
|
||||
this.privateSecrect = privateSecrect;
|
||||
this.serverAddress = serverAddress;
|
||||
this.serverPort = serverPort;
|
||||
}
|
||||
}
|
||||
|
||||
private ConcurrentHashMap<String, CallbackConnection> connections = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, Boolean> connectionsStatus = new ConcurrentHashMap<>();
|
||||
private ConcurrentHashMap<String, ConnectionInfo> connectionInfos = new ConcurrentHashMap<>();
|
||||
|
||||
private static ConnectionsManager connectionsManager = new ConnectionsManager();
|
||||
private ConnectionsManager() {
|
||||
|
||||
}
|
||||
|
||||
public static synchronized ConnectionsManager getInstance() {
|
||||
return connectionsManager;
|
||||
}
|
||||
|
||||
public CallbackConnection createConnection(String key, MQTT mqtt, ConnectionInfo connectionInfo) {
|
||||
CallbackConnection conn = mqtt.callbackConnection();
|
||||
connections.put(key, conn);
|
||||
connectionInfos.put(key, connectionInfo);
|
||||
return conn;
|
||||
}
|
||||
|
||||
public CallbackConnection getConnection(String key) {
|
||||
return this.connections.get(key);
|
||||
}
|
||||
|
||||
public ConnectionInfo getConnectionInfo(String key) {
|
||||
return this.connectionInfos.get(key);
|
||||
}
|
||||
|
||||
public boolean containsConnection(String key) {
|
||||
return connections.containsKey(key);
|
||||
}
|
||||
|
||||
public void removeConnection(String key) {
|
||||
this.connections.remove(key);
|
||||
this.connectionInfos.remove(key);
|
||||
}
|
||||
|
||||
public void setConnectionStatus(String key, Boolean status) {
|
||||
connectionsStatus.put(key, status);
|
||||
}
|
||||
|
||||
public boolean getConnectionStatus(String key) {
|
||||
if(!connectionsStatus.containsKey(key)) {
|
||||
throw new RuntimeException("Cannot find conn status for key: " + key);
|
||||
}
|
||||
return connectionsStatus.get(key);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package net.xmeter.samplers;
|
||||
|
||||
import org.apache.jorphan.logging.LoggingManager;
|
||||
import org.apache.log.Logger;
|
||||
import org.apache.log.Priority;
|
||||
import org.fusesource.mqtt.client.Callback;
|
||||
|
||||
public class SendMessageCallback implements Callback<byte[]>{
|
||||
private static Logger logger = LoggingManager.getLoggerForClass();
|
||||
private boolean successful = false;
|
||||
private Object connLock;
|
||||
private int errorCode;
|
||||
|
||||
public SendMessageCallback(Object connLock) {
|
||||
this.connLock = connLock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(byte[] value) {
|
||||
//If QoS == 0, then the current thread is the same thread of caller thread.
|
||||
//Else if QoS == 1 | 2, then the current thread is hawtdispatch-DEFAULT-x
|
||||
if (value != null && value.length > 0) {
|
||||
errorCode = value[0]&0xff;
|
||||
} else {
|
||||
onFailure(new Throwable("Send message with invalid data back"));
|
||||
return;
|
||||
}
|
||||
if (errorCode != 0) {
|
||||
onFailure(new Throwable("Send message failure with error code(" + errorCode + ")"));
|
||||
return;
|
||||
}
|
||||
synchronized (connLock) {
|
||||
this.successful = true;
|
||||
connLock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable value) {
|
||||
synchronized (connLock) {
|
||||
this.successful = false;
|
||||
logger.log(Priority.ERROR, value.getMessage(), value);
|
||||
connLock.notify();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSuccessful() {
|
||||
return successful;
|
||||
}
|
||||
|
||||
public int getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,317 @@
|
||||
package net.xmeter.samplers;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
|
||||
import cn.wildfirechat.proto.ProtoConstants;
|
||||
import cn.wildfirechat.proto.WFCMessage;
|
||||
import io.moquette.spi.impl.security.AES;
|
||||
import org.fusesource.mqtt.client.MQTT;
|
||||
import org.apache.jmeter.samplers.Entry;
|
||||
import org.apache.jmeter.samplers.SampleResult;
|
||||
import org.apache.jmeter.testelement.ThreadListener;
|
||||
import org.apache.jorphan.logging.LoggingManager;
|
||||
import org.apache.log.Logger;
|
||||
import org.apache.log.Priority;
|
||||
import org.fusesource.hawtbuf.Buffer;
|
||||
import org.fusesource.hawtbuf.UTF8Buffer;
|
||||
|
||||
import net.xmeter.Util;
|
||||
import org.fusesource.mqtt.client.Callback;
|
||||
import org.fusesource.mqtt.client.CallbackConnection;
|
||||
import org.fusesource.mqtt.client.Listener;
|
||||
import org.fusesource.mqtt.client.QoS;
|
||||
|
||||
|
||||
public class SendMessageSampler extends AbstractMQTTSampler implements ThreadListener {
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -4312341622759500786L;
|
||||
private transient static Logger logger = LoggingManager.getLoggerForClass();
|
||||
private transient MQTT mqtt = new MQTT();
|
||||
private transient CallbackConnection connection = null;
|
||||
private String payload = null;
|
||||
private QoS qos_enum = QoS.AT_MOST_ONCE;
|
||||
private String topicName = "";
|
||||
private String connKey = "";
|
||||
|
||||
public String getQOS() {
|
||||
return getPropertyAsString(QOS_LEVEL, String.valueOf(QOS_0));
|
||||
}
|
||||
|
||||
public void setQOS(String qos) {
|
||||
setProperty(QOS_LEVEL, qos);
|
||||
}
|
||||
|
||||
public String getTopic() {
|
||||
return getPropertyAsString(TOPIC_NAME, DEFAULT_TOPIC_NAME);
|
||||
}
|
||||
|
||||
public void setTopic(String topicName) {
|
||||
setProperty(TOPIC_NAME, topicName);
|
||||
}
|
||||
|
||||
public void setTarget(String target) {
|
||||
setProperty(TARGET, target);
|
||||
}
|
||||
|
||||
public String getTarget() {
|
||||
return getPropertyAsString(TARGET, DEFAULT_TARGET);
|
||||
}
|
||||
|
||||
public void setConvType(String type) {
|
||||
setProperty(CONV_TYPE, type);
|
||||
}
|
||||
|
||||
public String getConvType() {
|
||||
return getPropertyAsString(CONV_TYPE, CONV_TYPE_SINGLE);
|
||||
}
|
||||
|
||||
public boolean isAddTimestamp() {
|
||||
return getPropertyAsBoolean(ADD_TIMESTAMP);
|
||||
}
|
||||
|
||||
public void setAddTimestamp(boolean addTimestamp) {
|
||||
setProperty(ADD_TIMESTAMP, addTimestamp);
|
||||
}
|
||||
|
||||
public String getMessageType() {
|
||||
return getPropertyAsString(MESSAGE_TYPE, MESSAGE_TYPE_RANDOM_STR_WITH_FIX_LEN);
|
||||
}
|
||||
|
||||
public void setMessageType(String messageType) {
|
||||
setProperty(MESSAGE_TYPE, messageType);
|
||||
}
|
||||
|
||||
public String getMessageLength() {
|
||||
return getPropertyAsString(MESSAGE_FIX_LENGTH, DEFAULT_MESSAGE_FIX_LENGTH);
|
||||
}
|
||||
|
||||
public void setMessageLength(String length) {
|
||||
setProperty(MESSAGE_FIX_LENGTH, length);
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return getPropertyAsString(MESSAGE_TO_BE_SENT, "hello");
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
setProperty(MESSAGE_TO_BE_SENT, message);
|
||||
}
|
||||
|
||||
public String getConnPrefix() {
|
||||
return getPropertyAsString(CONN_CLIENT_ID_PREFIX, DEFAULT_CONN_PREFIX_FOR_PUB);
|
||||
}
|
||||
|
||||
public static byte[] hexToBinary(String hex) {
|
||||
return DatatypeConverter.parseHexBinary(hex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConnectionShareShow() {
|
||||
return true;
|
||||
}
|
||||
|
||||
private String getKey() {
|
||||
String key = getThreadName();
|
||||
if(!isConnectionShare()) {
|
||||
key = new String(getThreadName() + this.hashCode());
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SampleResult sample(Entry arg0) {
|
||||
this.connKey = getKey();
|
||||
if(connection == null) {
|
||||
connection = ConnectionsManager.getInstance().getConnection(connKey);
|
||||
if(connection != null) {
|
||||
logger.info("Use the shared connection: " + connection);
|
||||
ConnectionsManager.ConnectionInfo info = ConnectionsManager.getInstance().getConnectionInfo(connKey);
|
||||
setUserName(info.userName);
|
||||
token = info.token;
|
||||
privateSecret = info.privateSecrect;
|
||||
mqttServerIp = info.serverAddress;
|
||||
mqttServerPort = info.serverPort;
|
||||
} else {
|
||||
try {
|
||||
if (!getToken(getUserNameAuth())) {
|
||||
throw new Exception("get token failure!!!");
|
||||
}
|
||||
|
||||
if (!route(getUserNameAuth(), token)) {
|
||||
throw new Exception("route failure!!!");
|
||||
}
|
||||
|
||||
mqtt.setHost("tcp://" + mqttServerIp + ":" + mqttServerPort);
|
||||
mqtt.setVersion(getMqttVersion());
|
||||
mqtt.setKeepAlive((short) Integer.parseInt(getConnKeepAlive()));
|
||||
|
||||
mqtt.setClientId(getClientId());
|
||||
mqtt.setConnectAttemptsMax(Integer.parseInt(getConnAttamptMax()));
|
||||
mqtt.setReconnectAttemptsMax(Integer.parseInt(getConnReconnAttamptMax()));
|
||||
|
||||
mqtt.setUserName(getUserNameAuth());
|
||||
|
||||
byte[] password = AES.AESEncrypt(token, privateSecret);
|
||||
mqtt.setPassword(new UTF8Buffer(password));
|
||||
|
||||
Object connLock = new Object();
|
||||
connection = ConnectionsManager.getInstance().createConnection(connKey, mqtt, new ConnectionsManager.ConnectionInfo(getUserNameAuth(), token, privateSecret, mqttServerIp, mqttServerPort));
|
||||
|
||||
connection.listener(new Listener() {
|
||||
@Override
|
||||
public void onConnected() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnected() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPublish(UTF8Buffer topic, Buffer body, Runnable ack) {
|
||||
logger.log(Priority.DEBUG, "receive publish with topic:" + topic);
|
||||
ack.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable value) {
|
||||
|
||||
}
|
||||
});
|
||||
synchronized (connLock) {
|
||||
ConnectionCallback callback = new ConnectionCallback(connection, connLock);
|
||||
connection.connect(callback);
|
||||
connLock.wait(TimeUnit.SECONDS.toMillis(Integer.parseInt(getConnTimeout())));
|
||||
ConnectionsManager.getInstance().setConnectionStatus(connKey, callback.isConnectionSucc());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.log(Priority.ERROR, e.getMessage(), e);
|
||||
ConnectionsManager.getInstance().setConnectionStatus(connKey, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
payload = getMessage();
|
||||
if(payload == null) {
|
||||
payload = Util.generatePayload(120);
|
||||
}
|
||||
|
||||
SampleResult result = new SampleResult();
|
||||
result.setSampleLabel(getName());
|
||||
|
||||
if(!ConnectionsManager.getInstance().getConnectionStatus(connKey)) {
|
||||
result.sampleStart();
|
||||
result.setSuccessful(false);
|
||||
result.sampleEnd();
|
||||
result.setResponseMessage(MessageFormat.format("Publish failed for connection {0}.", connection));
|
||||
result.setResponseData("Publish failed becasue the connection has not been established.".getBytes());
|
||||
result.setResponseCode("500");
|
||||
return result;
|
||||
}
|
||||
try {
|
||||
byte[] toSend;
|
||||
result.sampleStart();
|
||||
|
||||
final Object connLock = new Object();
|
||||
SendMessageCallback pubCallback = new SendMessageCallback(connLock);
|
||||
|
||||
WFCMessage.Message message = WFCMessage.Message.newBuilder()
|
||||
.setConversation(WFCMessage.Conversation.newBuilder().setType(getConvType().equals(CONV_TYPE_SINGLE) ? ProtoConstants.ConversationType.ConversationType_Private : ProtoConstants.ConversationType.ConversationType_Group).setTarget(getTarget()).setLine(0).build())
|
||||
.setFromUser("")
|
||||
.setContent(WFCMessage.MessageContent.newBuilder().setType(1).setSearchableContent(getMessage()).build())
|
||||
.build();
|
||||
toSend = message.toByteArray();
|
||||
toSend = AES.AESEncrypt(toSend, privateSecret);
|
||||
|
||||
//wildfire send message use Qos1 and MS topic
|
||||
topicName = "MS";
|
||||
synchronized (connLock) {
|
||||
connection.publish(topicName, toSend, QoS.AT_LEAST_ONCE, false, pubCallback);
|
||||
connLock.wait();
|
||||
}
|
||||
|
||||
String sendData = "Conversation(" + getConvType() + ":" + getTarget() + "), Message(" + getMessage() + ")";
|
||||
result.sampleEnd();
|
||||
result.setSamplerData(sendData);
|
||||
result.setSentBytes(sendData.length());
|
||||
result.setLatency(result.getEndTime() - result.getStartTime());
|
||||
result.setSuccessful(pubCallback.isSuccessful());
|
||||
|
||||
if(pubCallback.isSuccessful()) {
|
||||
result.setResponseData("Publish successfuly.".getBytes());
|
||||
result.setResponseMessage(MessageFormat.format("publish successfully for Connection {0}.", connection));
|
||||
result.setResponseCodeOK();
|
||||
} else {
|
||||
result.setSuccessful(false);
|
||||
result.setResponseMessage(MessageFormat.format("Publish failed for connection {0}.", connection));
|
||||
result.setResponseData(("Publish failed with error code " + pubCallback.getErrorCode()).getBytes());
|
||||
result.setResponseCode("500");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
logger.log(Priority.ERROR, ex.getMessage(), ex);
|
||||
result.sampleEnd();
|
||||
result.setLatency(result.getEndTime() - result.getStartTime());
|
||||
result.setSuccessful(false);
|
||||
result.setResponseMessage(MessageFormat.format("Publish failed for connection {0}.", connection));
|
||||
result.setResponseData(ex.getMessage().getBytes());
|
||||
result.setResponseCode("500");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void threadStarted() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void threadFinished() {
|
||||
if (!isConnectionShare()) {
|
||||
if (this.connection != null) {
|
||||
final CountDownLatch cdl = new CountDownLatch(1);
|
||||
Callback<Void> cb = new Callback<Void>() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(Void value) {
|
||||
logger.info(MessageFormat.format("The connection {0} disconneted successfully.", connection));
|
||||
cdl.countDown();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Throwable value) {
|
||||
logger.log(Priority.ERROR, value.getMessage(), value);
|
||||
cdl.countDown();
|
||||
}
|
||||
};
|
||||
logger.info("before disconnection");
|
||||
this.connection.disconnect(cb);
|
||||
logger.info("after disconnection");
|
||||
try {
|
||||
cdl.await();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (ConnectionsManager.getInstance().containsConnection(connKey)) {
|
||||
ConnectionsManager.getInstance().removeConnection(connKey);
|
||||
}
|
||||
} else {
|
||||
logger.info("share connection, not disconnect the connection");
|
||||
}
|
||||
}
|
||||
public static String getUUID() {
|
||||
UUID uuid = UUID.randomUUID();
|
||||
String str = uuid.toString();
|
||||
|
||||
str = str.replace("-", "");
|
||||
return str;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user