Commit 712c0ccc by 李艳岭

Initial commit

parents
HELP.md
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**
!**/src/test/**
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
### VS Code ###
.vscode/
plugins {
id 'org.springframework.boot' version '2.2.5.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group = 'com.grandage'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '1.8'
repositories {
maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' }
maven { url "https://repo.spring.io/libs-milestone/" }
mavenCentral()
}
configurations {
provided
// remove default logger移除自带的logback
all*.exclude group: 'org.springframework.boot', module: 'spring-boot-starter-logging'
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
jar {
manifest {
attributes 'Main-Class': 'com.grandage.client.ClientApplication'
}
}
#Wed Jun 24 10:38:00 CST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.4.1-all.zip
#!/usr/bin/env sh
#
# Copyright 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
#
# https://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.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
rootProject.name = 'client'
package com.grandage.client;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author zhaoxin
* @data 2020/6/24
*/
@SpringBootApplication
public class ClientApplication {
public static void main(String[] args) {
SpringApplication.run(ClientApplication.class, args);
}
}
package com.grandage.client.server;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.management.*;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.TabularData;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.text.FieldPosition;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.logging.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author zhaoxin
* @data 2020/6/24
*/
@RestController
@RequestMapping("/jmx")
public class Client {
private static final Logger logger = Logger.getLogger(Client.class.getName());
private static final String USAGE = "Usage: java -jar cmdline-jmxclient.jar USER:PASS HOST:PORT [BEAN] [COMMAND]\nOptions:\n USER:PASS Username and password. Required. If none, pass '-'.\n E.g. 'controlRole:secret'\n HOST:PORT Hostname and port to connect to. Required. E.g. localhost:8081.\n Lists registered beans if only USER:PASS and this argument.\n BEANNAME Optional target bean name. If present we list available operations\n and attributes.\n COMMAND Optional operation to run or attribute to fetch. If none supplied,\n all operations and attributes are listed. Attributes begin with a\n capital letter: e.g. 'Status' or 'Started'. Operations do not.\n Operations can take arguments by adding an '=' followed by\n comma-delimited params. Pass multiple attributes/operations to run\n more than one per invocation.\nRequirements:\n JDK1.5.0. If connecting to a SUN 1.5.0 JDK JMX Agent, remote side must be\n started with system properties such as the following:\n -Dcom.sun.management.jmxremote.port=PORT\n -Dcom.sun.management.jmxremote.authenticate=false\n -Dcom.sun.management.jmxremote.ssl=false\n The above will start the remote server with no password. See\n http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html for more on\n 'Monitoring and Management via JMX'.\nClient Use Examples:\n To list MBeans on a non-password protected remote agent:\n % java -jar cmdline-jmxclient-X.X.jar - localhost:8081 \\\n org.archive.crawler:name=Heritrix,type=Service\n To list attributes and attributes of the Heritrix MBean:\n % java -jar cmdline-jmxclient-X.X.jar - localhost:8081 \\\n org.archive.crawler:name=Heritrix,type=Service \\\n schedule=http://www.archive.org\n To set set logging level to FINE on a password protected JVM:\n % java -jar cmdline-jmxclient-X.X.jar controlRole:secret localhost:8081 \\\n java.util.logging:type=Logging \\\n setLoggerLevel=org.archive.crawler.Heritrix,FINE";
protected static final Pattern CMD_LINE_ARGS_PATTERN = Pattern.compile("^([^=]+)(?:(?:\\=)(.+))?$");
static {
}
@PostMapping(value = "client")
public synchronized String client(@RequestBody String[] args)throws Exception{
Client client = new Client();
Logger l = Logger.getLogger("");
Handler[] hs = l.getHandlers();
for(int i = 0; i < hs.length; ++i) {
Handler h = hs[0];
if (h instanceof ConsoleHandler) {
h.setFormatter(client.new OneLineSimpleLogger());
}
}
List<String> execute = client.execute(args);
StringBuilder resultString = new StringBuilder();
for (String s : execute) {
resultString.append(s).append("\n");
}
return resultString.toString();
}
protected static List<String> usage() {
List<String> usage = usage(0, (String) null);
return usage;
}
protected static List<String> usage(int exitCode, String message) {
List<String> usageString = new ArrayList<>();
if (message != null && message.length() > 0) {
// System.out.println(message);
usageString.add(message);
}
// System.out.println("Usage: java -jar cmdline-jmxclient.jar USER:PASS HOST:PORT [BEAN] [COMMAND]\nOptions:\n USER:PASS Username and password. Required. If none, pass '-'.\n E.g. 'controlRole:secret'\n HOST:PORT Hostname and port to connect to. Required. E.g. localhost:8081.\n Lists registered beans if only USER:PASS and this argument.\n BEANNAME Optional target bean name. If present we list available operations\n and attributes.\n COMMAND Optional operation to run or attribute to fetch. If none supplied,\n all operations and attributes are listed. Attributes begin with a\n capital letter: e.g. 'Status' or 'Started'. Operations do not.\n Operations can take arguments by adding an '=' followed by\n comma-delimited params. Pass multiple attributes/operations to run\n more than one per invocation.\nRequirements:\n JDK1.5.0. If connecting to a SUN 1.5.0 JDK JMX Agent, remote side must be\n started with system properties such as the following:\n -Dcom.sun.management.jmxremote.port=PORT\n -Dcom.sun.management.jmxremote.authenticate=false\n -Dcom.sun.management.jmxremote.ssl=false\n The above will start the remote server with no password. See\n http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html for more on\n 'Monitoring and Management via JMX'.\nClient Use Examples:\n To list MBeans on a non-password protected remote agent:\n % java -jar cmdline-jmxclient-X.X.jar - localhost:8081 \\\n org.archive.crawler:name=Heritrix,type=Service\n To list attributes and attributes of the Heritrix MBean:\n % java -jar cmdline-jmxclient-X.X.jar - localhost:8081 \\\n org.archive.crawler:name=Heritrix,type=Service \\\n schedule=http://www.archive.org\n To set set logging level to FINE on a password protected JVM:\n % java -jar cmdline-jmxclient-X.X.jar controlRole:secret localhost:8081 \\\n java.util.logging:type=Logging \\\n setLoggerLevel=org.archive.crawler.Heritrix,FINE");
usageString.add("\"Usage: java -jar cmdline-jmxclient.jar USER:PASS HOST:PORT [BEAN] [COMMAND]\\nOptions:\\n USER:PASS Username and password. Required. If none, pass '-'.\\n E.g. 'controlRole:secret'\\n HOST:PORT Hostname and port to connect to. Required. E.g. localhost:8081.\\n Lists registered beans if only USER:PASS and this argument.\\n BEANNAME Optional target bean name. If present we list available operations\\n and attributes.\\n COMMAND Optional operation to run or attribute to fetch. If none supplied,\\n all operations and attributes are listed. Attributes begin with a\\n capital letter: e.g. 'Status' or 'Started'. Operations do not.\\n Operations can take arguments by adding an '=' followed by\\n comma-delimited params. Pass multiple attributes/operations to run\\n more than one per invocation.\\nRequirements:\\n JDK1.5.0. If connecting to a SUN 1.5.0 JDK JMX Agent, remote side must be\\n started with system properties such as the following:\\n -Dcom.sun.management.jmxremote.port=PORT\\n -Dcom.sun.management.jmxremote.authenticate=false\\n -Dcom.sun.management.jmxremote.ssl=false\\n The above will start the remote server with no password. See\\n http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html for more on\\n 'Monitoring and Management via JMX'.\\nClient Use Examples:\\n To list MBeans on a non-password protected remote agent:\\n % java -jar cmdline-jmxclient-X.X.jar - localhost:8081 \\\\\\n org.archive.crawler:name=Heritrix,type=Service\\n To list attributes and attributes of the Heritrix MBean:\\n % java -jar cmdline-jmxclient-X.X.jar - localhost:8081 \\\\\\n org.archive.crawler:name=Heritrix,type=Service \\\\\\n schedule=http://www.archive.org\\n To set set logging level to FINE on a password protected JVM:\\n % java -jar cmdline-jmxclient-X.X.jar controlRole:secret localhost:8081 \\\\\\n java.util.logging:type=Logging \\\\\\n setLoggerLevel=org.archive.crawler.Heritrix,FINE\"");
System.exit(exitCode);
return usageString;
}
public Client() {
}
protected Map formatCredentials(String userpass) {
Map env = null;
if (userpass != null && !userpass.equals("-")) {
int index = userpass.indexOf(58);
if (index <= 0) {
throw new RuntimeException("Unable to parse: " + userpass);
} else {
String[] creds = new String[]{userpass.substring(0, index), userpass.substring(index + 1)};
env = new HashMap(1);
env.put("jmx.remote.credentials", creds);
return env;
}
} else {
return env;
}
}
protected List<String> execute(String[] args) throws Exception {
List<String> executeString = new ArrayList<>();
if (args.length == 0 || args.length == 1) {
List<String> usage = usage();
executeString.addAll(usage);
}
String userpass = args[0];
String hostport = args[1];
String beanName = null;
String[] command = null;
if (args.length > 2) {
beanName = args[2];
}
if (args.length > 3) {
command = new String[args.length - 3];
for(int i = 3; i < args.length; ++i) {
command[i - 3] = args[i];
}
}
int index = hostport.indexOf(58);
if (index > 0) {
hostport.substring(0, index);
}
JMXServiceURL rmiurl = new JMXServiceURL("service:jmx:rmi://" + hostport + "/jndi/rmi://" + hostport + "/jmxrmi");
JMXConnector jmxc = JMXConnectorFactory.connect(rmiurl, this.formatCredentials(userpass));
try {
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
ObjectName objName = beanName != null && beanName.length() > 0 ? new ObjectName(beanName) : null;
Set beans = mbsc.queryMBeans(objName, (QueryExp)null);
if (beans.size() == 0) {
logger.severe(objName.getCanonicalName() + " is not a registered bean");
} else if (beans.size() == 1) {
ObjectInstance instance = (ObjectInstance)beans.iterator().next();
List<String> doBeanStrings = this.doBean(mbsc, instance, command);
executeString.addAll(doBeanStrings);
} else {
Iterator i = beans.iterator();
while(i.hasNext()) {
Object obj = i.next();
if (obj instanceof ObjectName) {
// System.out.println(((ObjectName)obj).getCanonicalName());
executeString.add(((ObjectName)obj).getCanonicalName());
} else if (obj instanceof ObjectInstance) {
// System.out.println(((ObjectInstance)obj).getObjectName().getCanonicalName());
executeString.add(((ObjectInstance)obj).getObjectName().getCanonicalName());
} else {
// logger.severe("Unexpected object type: " + obj);
executeString.add("Unexpected object type: " + obj);
}
}
}
} finally {
jmxc.close();
}
return executeString;
}
protected List<String> doBean(MBeanServerConnection mbsc, ObjectInstance instance, String[] command) throws Exception {
List<String> doBeanString = new ArrayList<>();
if (command != null && command.length > 0) {
for(int i = 0; i < command.length; ++i) {
List<String> doSubCommandStrings = this.doSubCommand(mbsc, instance, command[i]);
doBeanString.addAll(doSubCommandStrings);
}
} else {
List<String> listOptions = this.listOptions(mbsc, instance);
doBeanString.addAll(listOptions);
}
return doBeanString;
}
protected List<String> doSubCommand(MBeanServerConnection mbsc, ObjectInstance instance, String subCommand) throws Exception {
List<String> doSubCommandString = new ArrayList<>();
MBeanAttributeInfo[] attributeInfo = mbsc.getMBeanInfo(instance.getObjectName()).getAttributes();
MBeanOperationInfo[] operationInfo = mbsc.getMBeanInfo(instance.getObjectName()).getOperations();
Object result = null;
if (Character.isUpperCase(subCommand.charAt(0))) {
if (!this.isFeatureInfo(attributeInfo, subCommand) && this.isFeatureInfo(operationInfo, subCommand)) {
result = this.doBeanOperation(mbsc, instance, subCommand, operationInfo);
} else {
result = this.doAttributeOperation(mbsc, instance, subCommand, attributeInfo);
}
} else if (!this.isFeatureInfo(operationInfo, subCommand) && this.isFeatureInfo(attributeInfo, subCommand)) {
result = this.doAttributeOperation(mbsc, instance, subCommand, attributeInfo);
} else {
result = this.doBeanOperation(mbsc, instance, subCommand, operationInfo);
}
if (result instanceof CompositeData) {
result = this.recurseCompositeData(new StringBuffer("\n"), "", "", (CompositeData)result);
} else if (result instanceof TabularData) {
result = this.recurseTabularData(new StringBuffer("\n"), "", "", (TabularData)result);
} else if (result instanceof String[]) {
String[] strs = (String[])((String[])result);
StringBuffer buffer = new StringBuffer("\n");
for(int i = 0; i < strs.length; ++i) {
buffer.append(strs[i]);
buffer.append("\n");
}
result = buffer;
}
if (result != null && logger.isLoggable(Level.INFO)) {
// logger.info(subCommand + ": " + result);
doSubCommandString.add(result.toString());
}
return doSubCommandString;
}
protected boolean isFeatureInfo(MBeanFeatureInfo[] infos, String cmd) {
return this.getFeatureInfo(infos, cmd) != null;
}
protected MBeanFeatureInfo getFeatureInfo(MBeanFeatureInfo[] infos, String cmd) {
int index = cmd.indexOf(61);
String name = index > 0 ? cmd.substring(0, index) : cmd;
for(int i = 0; i < infos.length; ++i) {
if (infos[i].getName().equals(name)) {
return infos[i];
}
}
return null;
}
protected StringBuffer recurseTabularData(StringBuffer buffer, String indent, String name, TabularData data) {
this.addNameToBuffer(buffer, indent, name);
Collection c = data.values();
Iterator i = c.iterator();
while(i.hasNext()) {
Object obj = i.next();
if (obj instanceof CompositeData) {
this.recurseCompositeData(buffer, indent + " ", "", (CompositeData)obj);
} else if (obj instanceof TabularData) {
this.recurseTabularData(buffer, indent, "", (TabularData)obj);
} else {
buffer.append(obj);
}
}
return buffer;
}
protected StringBuffer recurseCompositeData(StringBuffer buffer, String indent, String name, CompositeData data) {
indent = this.addNameToBuffer(buffer, indent, name);
Iterator i = data.getCompositeType().keySet().iterator();
while(i.hasNext()) {
String key = (String)i.next();
Object o = data.get(key);
if (o instanceof CompositeData) {
this.recurseCompositeData(buffer, indent + " ", key, (CompositeData)o);
} else if (o instanceof TabularData) {
this.recurseTabularData(buffer, indent, key, (TabularData)o);
} else {
buffer.append(indent);
buffer.append(key);
buffer.append(": ");
buffer.append(o);
buffer.append("\n");
}
}
return buffer;
}
protected String addNameToBuffer(StringBuffer buffer, String indent, String name) {
if (name != null && name.length() != 0) {
buffer.append(indent);
buffer.append(name);
buffer.append(":\n");
return indent + " ";
} else {
return indent;
}
}
protected Object doAttributeOperation(MBeanServerConnection mbsc, ObjectInstance instance, String command, MBeanAttributeInfo[] infos) throws Exception {
Client.CommandParse parse = new Client.CommandParse(command);
if (parse.getArgs() != null && parse.getArgs().length != 0) {
if (parse.getArgs().length != 1) {
throw new IllegalArgumentException("One only argument setting attribute values: " + parse.getArgs());
} else {
MBeanAttributeInfo info = (MBeanAttributeInfo)this.getFeatureInfo(infos, parse.getCmd());
Constructor c = Class.forName(info.getType()).getConstructor(String.class);
Attribute a = new Attribute(parse.getCmd(), c.newInstance(parse.getArgs()[0]));
mbsc.setAttribute(instance.getObjectName(), a);
return null;
}
} else {
return mbsc.getAttribute(instance.getObjectName(), parse.getCmd());
}
}
protected Object doBeanOperation(MBeanServerConnection mbsc, ObjectInstance instance, String command, MBeanOperationInfo[] infos) throws Exception {
Client.CommandParse parse = new Client.CommandParse(command);
MBeanOperationInfo op = (MBeanOperationInfo)this.getFeatureInfo(infos, parse.getCmd());
Object result = null;
if (op == null) {
result = "Operation " + parse.getCmd() + " not found.";
} else {
MBeanParameterInfo[] paraminfos = op.getSignature();
int paraminfosLength = paraminfos == null ? 0 : paraminfos.length;
int objsLength = parse.getArgs() == null ? 0 : parse.getArgs().length;
if (paraminfosLength != objsLength) {
result = "Passed param count does not match signature count";
} else {
String[] signature = new String[paraminfosLength];
Object[] params = paraminfosLength == 0 ? null : new Object[paraminfosLength];
for(int i = 0; i < paraminfosLength; ++i) {
MBeanParameterInfo paraminfo = paraminfos[i];
Constructor c = Class.forName(paraminfo.getType()).getConstructor(String.class);
params[i] = c.newInstance(parse.getArgs()[i]);
signature[i] = paraminfo.getType();
}
result = mbsc.invoke(instance.getObjectName(), parse.getCmd(), params, signature);
}
}
return result;
}
protected List<String> listOptions(MBeanServerConnection mbsc, ObjectInstance instance) throws InstanceNotFoundException, IntrospectionException, ReflectionException, IOException {
List<String> OptionsString = new ArrayList<>();
MBeanInfo info = mbsc.getMBeanInfo(instance.getObjectName());
MBeanAttributeInfo[] attributes = info.getAttributes();
if (attributes.length > 0) {
// System.out.println("Attributes:");
OptionsString.add("Attributes:");
for(int i = 0; i < attributes.length; ++i) {
// System.out.println(' ' + attributes[i].getName() + ": " + attributes[i].getDescription() + " (type=" + attributes[i].getType() + ")");
OptionsString.add(' ' + attributes[i].getName() + ": " + attributes[i].getDescription() + " (type=" + attributes[i].getType() + ")");
}
}
MBeanOperationInfo[] operations = info.getOperations();
if (operations.length > 0) {
// System.out.println("Operations:");
OptionsString.add("Operations:");
for(int i = 0; i < operations.length; ++i) {
MBeanParameterInfo[] params = operations[i].getSignature();
StringBuffer paramsStrBuffer = new StringBuffer();
if (params != null) {
for(int j = 0; j < params.length; ++j) {
paramsStrBuffer.append("\n name=");
paramsStrBuffer.append(params[j].getName());
paramsStrBuffer.append(" type=");
paramsStrBuffer.append(params[j].getType());
paramsStrBuffer.append(" ");
paramsStrBuffer.append(params[j].getDescription());
}
}
// System.out.println(' ' + operations[i].getName() + ": " + operations[i].getDescription() + "\n Parameters " + params.length + ", return type=" + operations[i].getReturnType() + paramsStrBuffer.toString());
OptionsString.add(' ' + operations[i].getName() + ": " + operations[i].getDescription() + "\n Parameters " + params.length + ", return type=" + operations[i].getReturnType() + paramsStrBuffer.toString());
}
}
return OptionsString;
}
private class OneLineSimpleLogger extends SimpleFormatter {
private Date date = new Date();
private FieldPosition position = new FieldPosition(0);
private SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss Z");
private StringBuffer buffer = new StringBuffer();
public OneLineSimpleLogger() {
}
@Override
public synchronized String format(LogRecord record) {
this.buffer.setLength(0);
this.date.setTime(record.getMillis());
this.position.setBeginIndex(0);
this.formatter.format(this.date, this.buffer, this.position);
this.buffer.append(' ');
if (record.getSourceClassName() != null) {
this.buffer.append(record.getSourceClassName());
} else {
this.buffer.append(record.getLoggerName());
}
this.buffer.append(' ');
this.buffer.append(this.formatMessage(record));
this.buffer.append(System.getProperty("line.separator"));
if (record.getThrown() != null) {
try {
StringWriter writer = new StringWriter();
PrintWriter printer = new PrintWriter(writer);
record.getThrown().printStackTrace(printer);
writer.close();
this.buffer.append(writer.toString());
} catch (Exception var4) {
this.buffer.append("Failed to get stack trace: " + var4.getMessage());
}
}
return this.buffer.toString();
}
}
protected class CommandParse {
private String cmd;
private String[] args;
protected CommandParse(String command) throws ParseException {
this.parse(command);
}
private void parse(String command) throws ParseException {
Matcher m = Client.CMD_LINE_ARGS_PATTERN.matcher(command);
if (m != null && m.matches()) {
this.cmd = m.group(1);
if (m.group(2) != null && m.group(2).length() > 0) {
this.args = m.group(2).split(",");
} else {
this.args = null;
}
} else {
throw new ParseException("Failed parse of " + command, 0);
}
}
protected String getCmd() {
return this.cmd;
}
protected String[] getArgs() {
return this.args;
}
}
}
server:
port: 10052
logging:
config: classpath:log4j2-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<!--设置log4j2的自身log级别为warn-->
<!--日志级别以及优先级排序: OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -->
<!--Configuration后面的status,这个用于设置log4j2自身内部的信息输出,可以不设置,
当设置成trace时,你会看到log4j2内部各种详细输出-->
<!--monitorInterval:Log4j能够自动检测修改配置 文件和重新配置本身,设置间隔秒数-->
<configuration status="warn" monitorInterval="30">
<Properties>
<Property name="LOG_HOME">${sys:user.home}/client/</Property>
</Properties>
<Appenders>
<!-- 优先级从高到低分别是 OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL -->
<!-- 单词解释: Match:匹配 DENY:拒绝 Mismatch:不匹配 ACCEPT:接受 -->
<!-- DENY,日志将立即被抛弃不再经过其他过滤器; NEUTRAL,有序列表里的下个过滤器过接着处理日志; ACCEPT,日志会被立即处理,不再经过剩余过滤器。 -->
<!--输出日志的格式
%d{yyyy-MM-dd HH:mm:ss, SSS} : 日志生产时间
%p : 日志输出格式
%c : logger的名称
%m : 日志内容,即 logger.info("message")
%n : 换行符
%C : Java类名
%L : 日志输出所在行数
%M : 日志输出所在方法名
hostName : 本地机器名
hostAddress : 本地ip地址 -->
<Console name="console_out_appender" target="SYSTEM_OUT">
<!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) . -->
<ThresholdFilter level="DEBUG" onMatch="ACCEPT"
onMismatch="DENY"/>
<!-- 输出日志的格式 -->
<PatternLayout
pattern="%highlight{%d{yyyy.MM.dd 'at' HH:mm:ss z} %-5level %class{36} %M() @%L - %msg%n}{FATAL=Bright Red, ERROR=Bright red, WARN=Bright Yellow, INFO=Bright Green, DEBUG=Bright Cyan, TRACE=Bright White}"/>
</Console>
<Console name="console_err_appender" target="SYSTEM_ERR">
<ThresholdFilter level="ERROR" onMatch="ACCEPT"
onMismatch="DENY"/>
<PatternLayout pattern="%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n"/>
</Console>
<RollingFile name="debug_appender" immediateFlush="true"
fileName="${LOG_HOME}/debug.log" filePattern="${LOG_HOME}/debug/debug-%d{yyyy-MM-dd-HH_mm_ss}.log.gz">
<PatternLayout>
<pattern>%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<Filters>
<ThresholdFilter level="debug" onMatch="ACCEPT"
onMismatch="DENY"/>
</Filters>
</RollingFile>
<RollingFile name="info_appender" immediateFlush="true"
fileName="${LOG_HOME}/info.log" filePattern="${LOG_HOME}/info/info-%d{yyyy-MM-dd-HH_mm_ss}.log.gz">
<PatternLayout>
<pattern>%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<Filters>
<ThresholdFilter level="warn" onMatch="DENY"
onMismatch="NEUTRAL"/>
<ThresholdFilter level="info" onMatch="ACCEPT"
onMismatch="DENY"/>
</Filters>
</RollingFile>
<RollingFile name="warn_appender" immediateFlush="true"
fileName="${LOG_HOME}/warn.log" filePattern="${LOG_HOME}/warn/warn-%d{yyyy-MM-dd-HH_mm_ss}.log.gz">
<PatternLayout>
<pattern>%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<Filters>
<ThresholdFilter level="error" onMatch="DENY"
onMismatch="NEUTRAL"/>
<ThresholdFilter level="warn" onMatch="ACCEPT"
onMismatch="DENY"/>
</Filters>
</RollingFile>
<RollingFile name="error_appender" immediateFlush="true"
fileName="${LOG_HOME}/error.log"
filePattern="${LOG_HOME}/error/error-%d{yyyy-MM-dd-HH_mm_ss}.log.gz">
<PatternLayout>
<pattern>%5p [%t] %d{yyyy-MM-dd HH:mm:ss} (%F:%L) %m%n</pattern>
</PatternLayout>
<Policies>
<SizeBasedTriggeringPolicy size="100MB"/>
</Policies>
<Filters>
<ThresholdFilter level="error" onMatch="ACCEPT"
onMismatch="DENY"/>
</Filters>
</RollingFile>
</Appenders>
<!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
<loggers>
<!--过滤掉spring和hibernate的一些无用的debug信息-->
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.mybatis" level="INFO"></logger>
<logger name="org.springframework.core" level="info"/>
<logger name="org.springframework.beans" level="info"/>
<logger name="org.springframework.context" level="info"/>
<logger name="org.springframework.web" level="info"/>
<logger name="org.jboss.netty" level="warn"/>
<logger name="org.apache.http" level="warn"/>
<logger name="org.springframework" level="INFO"></logger>
<logger name="org.hibernate" level="INFO"></logger>
<root level="trace">
<appender-ref ref="console_out_appender"/>
<!--<appender-ref ref="console_err_appender" />-->
<appender-ref ref="debug_appender"/>
<appender-ref ref="info_appender"/>
<appender-ref ref="warn_appender"/>
<appender-ref ref="error_appender"/>
</root>
</loggers>
</configuration>
package com.grandage.client;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class ClientApplicationTests {
@Test
void contextLoads() {
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment