() {});
}
diff --git a/src/main/java/org/slf4j/Logger.java b/src/main/java/org/slf4j/Logger.java
new file mode 100644
index 0000000..185d404
--- /dev/null
+++ b/src/main/java/org/slf4j/Logger.java
@@ -0,0 +1,766 @@
+/**
+ * Copyright (c) 2004-2011 QOS.ch
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+package org.slf4j;
+
+/**
+ * The org.slf4j.Logger interface is the main user entry point of SLF4J API.
+ * It is expected that logging takes place through concrete implementations
+ * of this interface.
+ *
+ * Typical usage pattern:
+ *
+ * import org.slf4j.Logger;
+ * import org.slf4j.LoggerFactory;
+ *
+ * public class Wombat {
+ *
+ * final static Logger logger = LoggerFactory.getLogger(Wombat.class);
+ * Integer t;
+ * Integer oldT;
+ *
+ * public void setTemperature(Integer temperature) {
+ * oldT = t;
+ * t = temperature;
+ * logger.debug("Temperature set to {}. Old temperature was {}.", t, oldT);
+ * if(temperature.intValue() > 50) {
+ * logger.info("Temperature has risen above 50 degrees.");
+ * }
+ * }
+ * }
+ *
+ *
+ * Be sure to read the FAQ entry relating to parameterized
+ * logging. Note that logging statements can be parameterized in
+ * presence of an exception/throwable.
+ *
+ * Once you are comfortable using loggers, i.e. instances of this interface, consider using
+ * MDC as well as Markers.
+ *
+ * @author Ceki Gülcü
+ */
+public interface Logger {
+
+ /**
+ * Case insensitive String constant used to retrieve the name of the root logger.
+ *
+ * @since 1.3
+ */
+ final public String ROOT_LOGGER_NAME = "ROOT";
+
+ /**
+ * Return the name of this Logger
instance.
+ * @return name of this logger instance
+ */
+ public String getName();
+
+ /**
+ * Is the logger instance enabled for the TRACE level?
+ *
+ * @return True if this Logger is enabled for the TRACE level,
+ * false otherwise.
+ * @since 1.4
+ */
+ public boolean isTraceEnabled();
+
+ /**
+ * Log a message at the TRACE level.
+ *
+ * @param msg the message string to be logged
+ * @since 1.4
+ */
+ public void trace(String msg);
+
+ /**
+ * Log a message at the TRACE level according to the specified format
+ * and argument.
+ *
+ * This form avoids superfluous object creation when the logger
+ * is disabled for the TRACE level.
+ *
+ * @param format the format string
+ * @param arg the argument
+ * @since 1.4
+ */
+ public void trace(String format, Object arg);
+
+ /**
+ * Log a message at the TRACE level according to the specified format
+ * and arguments.
+ *
+ * This form avoids superfluous object creation when the logger
+ * is disabled for the TRACE level.
+ *
+ * @param format the format string
+ * @param arg1 the first argument
+ * @param arg2 the second argument
+ * @since 1.4
+ */
+ public void trace(String format, Object arg1, Object arg2);
+
+ /**
+ * Log a message at the TRACE level according to the specified format
+ * and arguments.
+ *
+ * This form avoids superfluous string concatenation when the logger
+ * is disabled for the TRACE level. However, this variant incurs the hidden
+ * (and relatively small) cost of creating an Object[]
before invoking the method,
+ * even if this logger is disabled for TRACE. The variants taking {@link #trace(String, Object) one} and
+ * {@link #trace(String, Object, Object) two} arguments exist solely in order to avoid this hidden cost.
+ *
+ * @param format the format string
+ * @param arguments a list of 3 or more arguments
+ * @since 1.4
+ */
+ public void trace(String format, Object... arguments);
+
+ /**
+ * Log an exception (throwable) at the TRACE level with an
+ * accompanying message.
+ *
+ * @param msg the message accompanying the exception
+ * @param t the exception (throwable) to log
+ * @since 1.4
+ */
+ public void trace(String msg, Throwable t);
+
+ /**
+ * Similar to {@link #isTraceEnabled()} method except that the
+ * marker data is also taken into account.
+ *
+ * @param marker The marker data to take into consideration
+ * @return True if this Logger is enabled for the TRACE level,
+ * false otherwise.
+ *
+ * @since 1.4
+ */
+ public boolean isTraceEnabled(Marker marker);
+
+ /**
+ * Log a message with the specific Marker at the TRACE level.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param msg the message string to be logged
+ * @since 1.4
+ */
+ public void trace(Marker marker, String msg);
+
+ /**
+ * This method is similar to {@link #trace(String, Object)} method except that the
+ * marker data is also taken into consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arg the argument
+ * @since 1.4
+ */
+ public void trace(Marker marker, String format, Object arg);
+
+ /**
+ * This method is similar to {@link #trace(String, Object, Object)}
+ * method except that the marker data is also taken into
+ * consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arg1 the first argument
+ * @param arg2 the second argument
+ * @since 1.4
+ */
+ public void trace(Marker marker, String format, Object arg1, Object arg2);
+
+ /**
+ * This method is similar to {@link #trace(String, Object...)}
+ * method except that the marker data is also taken into
+ * consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param argArray an array of arguments
+ * @since 1.4
+ */
+ public void trace(Marker marker, String format, Object... argArray);
+
+ /**
+ * This method is similar to {@link #trace(String, Throwable)} method except that the
+ * marker data is also taken into consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param msg the message accompanying the exception
+ * @param t the exception (throwable) to log
+ * @since 1.4
+ */
+ public void trace(Marker marker, String msg, Throwable t);
+
+ /**
+ * Is the logger instance enabled for the DEBUG level?
+ *
+ * @return True if this Logger is enabled for the DEBUG level,
+ * false otherwise.
+ */
+ public boolean isDebugEnabled();
+
+ /**
+ * Log a message at the DEBUG level.
+ *
+ * @param msg the message string to be logged
+ */
+ public void debug(String msg);
+
+ /**
+ * Log a message at the DEBUG level according to the specified format
+ * and argument.
+ *
+ * This form avoids superfluous object creation when the logger
+ * is disabled for the DEBUG level.
+ *
+ * @param format the format string
+ * @param arg the argument
+ */
+ public void debug(String format, Object arg);
+
+ /**
+ * Log a message at the DEBUG level according to the specified format
+ * and arguments.
+ *
+ * This form avoids superfluous object creation when the logger
+ * is disabled for the DEBUG level.
+ *
+ * @param format the format string
+ * @param arg1 the first argument
+ * @param arg2 the second argument
+ */
+ public void debug(String format, Object arg1, Object arg2);
+
+ /**
+ * Log a message at the DEBUG level according to the specified format
+ * and arguments.
+ *
+ * This form avoids superfluous string concatenation when the logger
+ * is disabled for the DEBUG level. However, this variant incurs the hidden
+ * (and relatively small) cost of creating an Object[]
before invoking the method,
+ * even if this logger is disabled for DEBUG. The variants taking
+ * {@link #debug(String, Object) one} and {@link #debug(String, Object, Object) two}
+ * arguments exist solely in order to avoid this hidden cost.
+ *
+ * @param format the format string
+ * @param arguments a list of 3 or more arguments
+ */
+ public void debug(String format, Object... arguments);
+
+ /**
+ * Log an exception (throwable) at the DEBUG level with an
+ * accompanying message.
+ *
+ * @param msg the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ public void debug(String msg, Throwable t);
+
+ /**
+ * Similar to {@link #isDebugEnabled()} method except that the
+ * marker data is also taken into account.
+ *
+ * @param marker The marker data to take into consideration
+ * @return True if this Logger is enabled for the DEBUG level,
+ * false otherwise.
+ */
+ public boolean isDebugEnabled(Marker marker);
+
+ /**
+ * Log a message with the specific Marker at the DEBUG level.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param msg the message string to be logged
+ */
+ public void debug(Marker marker, String msg);
+
+ /**
+ * This method is similar to {@link #debug(String, Object)} method except that the
+ * marker data is also taken into consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arg the argument
+ */
+ public void debug(Marker marker, String format, Object arg);
+
+ /**
+ * This method is similar to {@link #debug(String, Object, Object)}
+ * method except that the marker data is also taken into
+ * consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arg1 the first argument
+ * @param arg2 the second argument
+ */
+ public void debug(Marker marker, String format, Object arg1, Object arg2);
+
+ /**
+ * This method is similar to {@link #debug(String, Object...)}
+ * method except that the marker data is also taken into
+ * consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arguments a list of 3 or more arguments
+ */
+ public void debug(Marker marker, String format, Object... arguments);
+
+ /**
+ * This method is similar to {@link #debug(String, Throwable)} method except that the
+ * marker data is also taken into consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param msg the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ public void debug(Marker marker, String msg, Throwable t);
+
+ /**
+ * Is the logger instance enabled for the INFO level?
+ *
+ * @return True if this Logger is enabled for the INFO level,
+ * false otherwise.
+ */
+ public boolean isInfoEnabled();
+
+ /**
+ * Log a message at the INFO level.
+ *
+ * @param msg the message string to be logged
+ */
+ public void info(String msg);
+
+ /**
+ * Log a message at the INFO level according to the specified format
+ * and argument.
+ *
+ * This form avoids superfluous object creation when the logger
+ * is disabled for the INFO level.
+ *
+ * @param format the format string
+ * @param arg the argument
+ */
+ public void info(String format, Object arg);
+
+ /**
+ * Log a message at the INFO level according to the specified format
+ * and arguments.
+ *
+ * This form avoids superfluous object creation when the logger
+ * is disabled for the INFO level.
+ *
+ * @param format the format string
+ * @param arg1 the first argument
+ * @param arg2 the second argument
+ */
+ public void info(String format, Object arg1, Object arg2);
+
+ /**
+ * Log a message at the INFO level according to the specified format
+ * and arguments.
+ *
+ * This form avoids superfluous string concatenation when the logger
+ * is disabled for the INFO level. However, this variant incurs the hidden
+ * (and relatively small) cost of creating an Object[]
before invoking the method,
+ * even if this logger is disabled for INFO. The variants taking
+ * {@link #info(String, Object) one} and {@link #info(String, Object, Object) two}
+ * arguments exist solely in order to avoid this hidden cost.
+ *
+ * @param format the format string
+ * @param arguments a list of 3 or more arguments
+ */
+ public void info(String format, Object... arguments);
+
+ /**
+ * Log an exception (throwable) at the INFO level with an
+ * accompanying message.
+ *
+ * @param msg the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ public void info(String msg, Throwable t);
+
+ /**
+ * Similar to {@link #isInfoEnabled()} method except that the marker
+ * data is also taken into consideration.
+ *
+ * @param marker The marker data to take into consideration
+ * @return true if this logger is warn enabled, false otherwise
+ */
+ public boolean isInfoEnabled(Marker marker);
+
+ /**
+ * Log a message with the specific Marker at the INFO level.
+ *
+ * @param marker The marker specific to this log statement
+ * @param msg the message string to be logged
+ */
+ public void info(Marker marker, String msg);
+
+ /**
+ * This method is similar to {@link #info(String, Object)} method except that the
+ * marker data is also taken into consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arg the argument
+ */
+ public void info(Marker marker, String format, Object arg);
+
+ /**
+ * This method is similar to {@link #info(String, Object, Object)}
+ * method except that the marker data is also taken into
+ * consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arg1 the first argument
+ * @param arg2 the second argument
+ */
+ public void info(Marker marker, String format, Object arg1, Object arg2);
+
+ /**
+ * This method is similar to {@link #info(String, Object...)}
+ * method except that the marker data is also taken into
+ * consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arguments a list of 3 or more arguments
+ */
+ public void info(Marker marker, String format, Object... arguments);
+
+ /**
+ * This method is similar to {@link #info(String, Throwable)} method
+ * except that the marker data is also taken into consideration.
+ *
+ * @param marker the marker data for this log statement
+ * @param msg the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ public void info(Marker marker, String msg, Throwable t);
+
+ /**
+ * Is the logger instance enabled for the WARN level?
+ *
+ * @return True if this Logger is enabled for the WARN level,
+ * false otherwise.
+ */
+ public boolean isWarnEnabled();
+
+ /**
+ * Log a message at the WARN level.
+ *
+ * @param msg the message string to be logged
+ */
+ public void warn(String msg);
+
+ /**
+ * Log a message at the WARN level according to the specified format
+ * and argument.
+ *
+ * This form avoids superfluous object creation when the logger
+ * is disabled for the WARN level.
+ *
+ * @param format the format string
+ * @param arg the argument
+ */
+ public void warn(String format, Object arg);
+
+ /**
+ * Log a message at the WARN level according to the specified format
+ * and arguments.
+ *
+ * This form avoids superfluous string concatenation when the logger
+ * is disabled for the WARN level. However, this variant incurs the hidden
+ * (and relatively small) cost of creating an Object[]
before invoking the method,
+ * even if this logger is disabled for WARN. The variants taking
+ * {@link #warn(String, Object) one} and {@link #warn(String, Object, Object) two}
+ * arguments exist solely in order to avoid this hidden cost.
+ *
+ * @param format the format string
+ * @param arguments a list of 3 or more arguments
+ */
+ public void warn(String format, Object... arguments);
+
+ /**
+ * Log a message at the WARN level according to the specified format
+ * and arguments.
+ *
+ * This form avoids superfluous object creation when the logger
+ * is disabled for the WARN level.
+ *
+ * @param format the format string
+ * @param arg1 the first argument
+ * @param arg2 the second argument
+ */
+ public void warn(String format, Object arg1, Object arg2);
+
+ /**
+ * Log an exception (throwable) at the WARN level with an
+ * accompanying message.
+ *
+ * @param msg the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ public void warn(String msg, Throwable t);
+
+ /**
+ * Similar to {@link #isWarnEnabled()} method except that the marker
+ * data is also taken into consideration.
+ *
+ * @param marker The marker data to take into consideration
+ * @return True if this Logger is enabled for the WARN level,
+ * false otherwise.
+ */
+ public boolean isWarnEnabled(Marker marker);
+
+ /**
+ * Log a message with the specific Marker at the WARN level.
+ *
+ * @param marker The marker specific to this log statement
+ * @param msg the message string to be logged
+ */
+ public void warn(Marker marker, String msg);
+
+ /**
+ * This method is similar to {@link #warn(String, Object)} method except that the
+ * marker data is also taken into consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arg the argument
+ */
+ public void warn(Marker marker, String format, Object arg);
+
+ /**
+ * This method is similar to {@link #warn(String, Object, Object)}
+ * method except that the marker data is also taken into
+ * consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arg1 the first argument
+ * @param arg2 the second argument
+ */
+ public void warn(Marker marker, String format, Object arg1, Object arg2);
+
+ /**
+ * This method is similar to {@link #warn(String, Object...)}
+ * method except that the marker data is also taken into
+ * consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arguments a list of 3 or more arguments
+ */
+ public void warn(Marker marker, String format, Object... arguments);
+
+ /**
+ * This method is similar to {@link #warn(String, Throwable)} method
+ * except that the marker data is also taken into consideration.
+ *
+ * @param marker the marker data for this log statement
+ * @param msg the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ public void warn(Marker marker, String msg, Throwable t);
+
+ /**
+ * Is the logger instance enabled for the ERROR level?
+ *
+ * @return True if this Logger is enabled for the ERROR level,
+ * false otherwise.
+ */
+ public boolean isErrorEnabled();
+
+ /**
+ * Log a message at the ERROR level.
+ *
+ * @param msg the message string to be logged
+ */
+ public void error(String msg);
+
+ /**
+ * Log a message at the ERROR level according to the specified format
+ * and argument.
+ *
+ * This form avoids superfluous object creation when the logger
+ * is disabled for the ERROR level.
+ *
+ * @param format the format string
+ * @param arg the argument
+ */
+ public void error(String format, Object arg);
+
+ /**
+ * Log a message at the ERROR level according to the specified format
+ * and arguments.
+ *
+ * This form avoids superfluous object creation when the logger
+ * is disabled for the ERROR level.
+ *
+ * @param format the format string
+ * @param arg1 the first argument
+ * @param arg2 the second argument
+ */
+ public void error(String format, Object arg1, Object arg2);
+
+ /**
+ * Log a message at the ERROR level according to the specified format
+ * and arguments.
+ *
+ * This form avoids superfluous string concatenation when the logger
+ * is disabled for the ERROR level. However, this variant incurs the hidden
+ * (and relatively small) cost of creating an Object[]
before invoking the method,
+ * even if this logger is disabled for ERROR. The variants taking
+ * {@link #error(String, Object) one} and {@link #error(String, Object, Object) two}
+ * arguments exist solely in order to avoid this hidden cost.
+ *
+ * @param format the format string
+ * @param arguments a list of 3 or more arguments
+ */
+ public void error(String format, Object... arguments);
+
+ /**
+ * Log an exception (throwable) at the ERROR level with an
+ * accompanying message.
+ *
+ * @param msg the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ public void error(String msg, Throwable t);
+
+ /**
+ * Similar to {@link #isErrorEnabled()} method except that the
+ * marker data is also taken into consideration.
+ *
+ * @param marker The marker data to take into consideration
+ * @return True if this Logger is enabled for the ERROR level,
+ * false otherwise.
+ */
+ public boolean isErrorEnabled(Marker marker);
+
+ /**
+ * Log a message with the specific Marker at the ERROR level.
+ *
+ * @param marker The marker specific to this log statement
+ * @param msg the message string to be logged
+ */
+ public void error(Marker marker, String msg);
+
+ /**
+ * This method is similar to {@link #error(String, Object)} method except that the
+ * marker data is also taken into consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arg the argument
+ */
+ public void error(Marker marker, String format, Object arg);
+
+ /**
+ * This method is similar to {@link #error(String, Object, Object)}
+ * method except that the marker data is also taken into
+ * consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arg1 the first argument
+ * @param arg2 the second argument
+ */
+ public void error(Marker marker, String format, Object arg1, Object arg2);
+
+ /**
+ * This method is similar to {@link #error(String, Object...)}
+ * method except that the marker data is also taken into
+ * consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param format the format string
+ * @param arguments a list of 3 or more arguments
+ */
+ public void error(Marker marker, String format, Object... arguments);
+
+ /**
+ * This method is similar to {@link #error(String, Throwable)}
+ * method except that the marker data is also taken into
+ * consideration.
+ *
+ * @param marker the marker data specific to this log statement
+ * @param msg the message accompanying the exception
+ * @param t the exception (throwable) to log
+ */
+ public void error(Marker marker, String msg, Throwable t);
+
+ /**
+ * This is a start method for controlling log folding
+ *
+ * @param startTitle the title of folding
+ */
+ public void groupStart(String startTitle);
+
+ /**
+ * This is a end method for controlling log folding
+ *
+ * @param endTitle the title of folding
+ */
+ public void groupEnd(String endTitle);
+
+ /**
+ * This is a info log method for controlling log folding
+ *
+ * @param msg the log content
+ * @param subTagName the sub tag name
+ */
+ public void infoInTag(String msg, String subTagName);
+
+ /**
+ * This is a error log method for controlling log folding
+ *
+ * @param msg the log content
+ * @param subTagName the sub tag name
+ */
+ public void errorInTag(String msg, String subTagName);
+
+ /**
+ * This is a warn log method for controlling log folding
+ *
+ * @param msg the log content
+ * @param subTagName the sub tag name
+ */
+ public void warnInTag(String msg, String subTagName);
+
+ /**
+ * This is a finish method for controlling log loading
+ *
+ * @param subTagName the sub tag name
+ */
+ public void finishTag(String msg, String subTagName);
+
+}
diff --git a/src/main/java/org/slf4j/LoggerFactory.java b/src/main/java/org/slf4j/LoggerFactory.java
new file mode 100644
index 0000000..2be57c7
--- /dev/null
+++ b/src/main/java/org/slf4j/LoggerFactory.java
@@ -0,0 +1,430 @@
+/**
+ * Copyright (c) 2004-2011 QOS.ch
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+package org.slf4j;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import org.slf4j.event.SubstituteLoggingEvent;
+import org.slf4j.helpers.NOPLoggerFactory;
+import org.slf4j.helpers.SubstituteLogger;
+import org.slf4j.helpers.SubstituteLoggerFactory;
+import org.slf4j.helpers.Util;
+import org.slf4j.impl.StaticLoggerBinder;
+
+/**
+ * The LoggerFactory
is a utility class producing Loggers for
+ * various logging APIs, most notably for log4j, logback and JDK 1.4 logging.
+ * Other implementations such as {@link org.slf4j.impl.NOPLogger NOPLogger} and
+ * {@link org.slf4j.impl.SimpleLogger SimpleLogger} are also supported.
+ *
+ *
+ * LoggerFactory
is essentially a wrapper around an
+ * {@link ILoggerFactory} instance bound with LoggerFactory
at
+ * compile time.
+ *
+ *
+ * Please note that all methods in LoggerFactory
are static.
+ *
+ *
+ * @author Alexander Dorokhine
+ * @author Robert Elliot
+ * @author Ceki Gülcü
+ *
+ */
+public final class LoggerFactory {
+
+ static final String CODES_PREFIX = "http://www.slf4j.org/codes.html";
+
+ static final String NO_STATICLOGGERBINDER_URL = CODES_PREFIX + "#StaticLoggerBinder";
+ static final String MULTIPLE_BINDINGS_URL = CODES_PREFIX + "#multiple_bindings";
+ static final String NULL_LF_URL = CODES_PREFIX + "#null_LF";
+ static final String VERSION_MISMATCH = CODES_PREFIX + "#version_mismatch";
+ static final String SUBSTITUTE_LOGGER_URL = CODES_PREFIX + "#substituteLogger";
+ static final String LOGGER_NAME_MISMATCH_URL = CODES_PREFIX + "#loggerNameMismatch";
+ static final String REPLAY_URL = CODES_PREFIX + "#replay";
+
+ static final String UNSUCCESSFUL_INIT_URL = CODES_PREFIX + "#unsuccessfulInit";
+ static final String UNSUCCESSFUL_INIT_MSG = "org.slf4j.LoggerFactory could not be successfully initialized. See also " + UNSUCCESSFUL_INIT_URL;
+
+ static final int UNINITIALIZED = 0;
+ static final int ONGOING_INITIALIZATION = 1;
+ static final int FAILED_INITIALIZATION = 2;
+ static final int SUCCESSFUL_INITIALIZATION = 3;
+ static final int NOP_FALLBACK_INITIALIZATION = 4;
+
+ static volatile int INITIALIZATION_STATE = UNINITIALIZED;
+ static SubstituteLoggerFactory SUBST_FACTORY = new SubstituteLoggerFactory();
+ static NOPLoggerFactory NOP_FALLBACK_FACTORY = new NOPLoggerFactory();
+
+ // Support for detecting mismatched logger names.
+ static final String DETECT_LOGGER_NAME_MISMATCH_PROPERTY = "slf4j.detectLoggerNameMismatch";
+ static final String JAVA_VENDOR_PROPERTY = "java.vendor.url";
+
+ static boolean DETECT_LOGGER_NAME_MISMATCH = Util.safeGetBooleanSystemProperty(DETECT_LOGGER_NAME_MISMATCH_PROPERTY);
+
+ /**
+ * It is LoggerFactory's responsibility to track version changes and manage
+ * the compatibility list.
+ *
+ *
+ * It is assumed that all versions in the 1.6 are mutually compatible.
+ */
+ static private final String[] API_COMPATIBILITY_LIST = new String[] { "1.6", "1.7" };
+
+ // private constructor prevents instantiation
+ private LoggerFactory() {
+ }
+
+ /**
+ * Force LoggerFactory to consider itself uninitialized.
+ *
+ *
+ * This method is intended to be called by classes (in the same package) for
+ * testing purposes. This method is internal. It can be modified, renamed or
+ * removed at any time without notice.
+ *
+ *
+ * You are strongly discouraged from calling this method in production code.
+ */
+ static void reset() {
+ INITIALIZATION_STATE = UNINITIALIZED;
+ }
+
+ private final static void performInitialization() {
+ bind();
+ if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) {
+ versionSanityCheck();
+ }
+ }
+
+ private static boolean messageContainsOrgSlf4jImplStaticLoggerBinder(String msg) {
+ if (msg == null)
+ return false;
+ if (msg.contains("org/slf4j/impl/StaticLoggerBinder"))
+ return true;
+ if (msg.contains("org.slf4j.impl.StaticLoggerBinder"))
+ return true;
+ return false;
+ }
+
+ private final static void bind() {
+ try {
+ Set staticLoggerBinderPathSet = null;
+ // skip check under android, see also
+ // http://jira.qos.ch/browse/SLF4J-328
+ if (!isAndroid()) {
+ staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
+ reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
+ }
+ // the next line does the binding
+ StaticLoggerBinder.getSingleton();
+ INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
+ reportActualBinding(staticLoggerBinderPathSet);
+ fixSubstituteLoggers();
+ replayEvents();
+ // release all resources in SUBST_FACTORY
+ SUBST_FACTORY.clear();
+ } catch (NoClassDefFoundError ncde) {
+ String msg = ncde.getMessage();
+ if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
+ INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;
+ Util.report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
+ Util.report("Defaulting to no-operation (NOP) logger implementation");
+ Util.report("See " + NO_STATICLOGGERBINDER_URL + " for further details.");
+ } else {
+ failedBinding(ncde);
+ throw ncde;
+ }
+ } catch (java.lang.NoSuchMethodError nsme) {
+ String msg = nsme.getMessage();
+ if (msg != null && msg.contains("org.slf4j.impl.StaticLoggerBinder.getSingleton()")) {
+ INITIALIZATION_STATE = FAILED_INITIALIZATION;
+ Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding.");
+ Util.report("Your binding is version 1.5.5 or earlier.");
+ Util.report("Upgrade your binding to version 1.6.x.");
+ }
+ throw nsme;
+ } catch (Exception e) {
+ failedBinding(e);
+ throw new IllegalStateException("Unexpected initialization failure", e);
+ }
+ }
+
+ private static void fixSubstituteLoggers() {
+ synchronized (SUBST_FACTORY) {
+ SUBST_FACTORY.postInitialization();
+ for (SubstituteLogger substLogger : SUBST_FACTORY.getLoggers()) {
+ Logger logger = getLogger(substLogger.getName());
+ substLogger.setDelegate(logger);
+ }
+ }
+
+ }
+
+ static void failedBinding(Throwable t) {
+ INITIALIZATION_STATE = FAILED_INITIALIZATION;
+ Util.report("Failed to instantiate SLF4J LoggerFactory", t);
+ }
+
+ private static void replayEvents() {
+ final LinkedBlockingQueue queue = SUBST_FACTORY.getEventQueue();
+ final int queueSize = queue.size();
+ int count = 0;
+ final int maxDrain = 128;
+ List eventList = new ArrayList(maxDrain);
+ while (true) {
+ int numDrained = queue.drainTo(eventList, maxDrain);
+ if (numDrained == 0)
+ break;
+ for (SubstituteLoggingEvent event : eventList) {
+ replaySingleEvent(event);
+ if (count++ == 0)
+ emitReplayOrSubstituionWarning(event, queueSize);
+ }
+ eventList.clear();
+ }
+ }
+
+ private static void emitReplayOrSubstituionWarning(SubstituteLoggingEvent event, int queueSize) {
+ if (event.getLogger().isDelegateEventAware()) {
+ emitReplayWarning(queueSize);
+ } else if (event.getLogger().isDelegateNOP()) {
+ // nothing to do
+ } else {
+ emitSubstitutionWarning();
+ }
+ }
+
+ private static void replaySingleEvent(SubstituteLoggingEvent event) {
+ if (event == null)
+ return;
+
+ SubstituteLogger substLogger = event.getLogger();
+ String loggerName = substLogger.getName();
+ if (substLogger.isDelegateNull()) {
+ throw new IllegalStateException("Delegate logger cannot be null at this state.");
+ }
+
+ if (substLogger.isDelegateNOP()) {
+ // nothing to do
+ } else if (substLogger.isDelegateEventAware()) {
+ substLogger.log(event);
+ } else {
+ Util.report(loggerName);
+ }
+ }
+
+ private static void emitSubstitutionWarning() {
+ Util.report("The following set of substitute loggers may have been accessed");
+ Util.report("during the initialization phase. Logging calls during this");
+ Util.report("phase were not honored. However, subsequent logging calls to these");
+ Util.report("loggers will work as normally expected.");
+ Util.report("See also " + SUBSTITUTE_LOGGER_URL);
+ }
+
+ private static void emitReplayWarning(int eventCount) {
+ Util.report("A number (" + eventCount + ") of logging calls during the initialization phase have been intercepted and are");
+ Util.report("now being replayed. These are subject to the filtering rules of the underlying logging system.");
+ Util.report("See also " + REPLAY_URL);
+ }
+
+ private final static void versionSanityCheck() {
+ try {
+ String requested = StaticLoggerBinder.REQUESTED_API_VERSION;
+
+ boolean match = false;
+ for (String aAPI_COMPATIBILITY_LIST : API_COMPATIBILITY_LIST) {
+ if (requested.startsWith(aAPI_COMPATIBILITY_LIST)) {
+ match = true;
+ }
+ }
+ if (!match) {
+ Util.report("The requested version " + requested + " by your slf4j binding is not compatible with "
+ + Arrays.asList(API_COMPATIBILITY_LIST).toString());
+ Util.report("See " + VERSION_MISMATCH + " for further details.");
+ }
+ } catch (java.lang.NoSuchFieldError nsfe) {
+ // given our large user base and SLF4J's commitment to backward
+ // compatibility, we cannot cry here. Only for implementations
+ // which willingly declare a REQUESTED_API_VERSION field do we
+ // emit compatibility warnings.
+ } catch (Throwable e) {
+ // we should never reach here
+ Util.report("Unexpected problem occured during version sanity check", e);
+ }
+ }
+
+ // We need to use the name of the StaticLoggerBinder class, but we can't
+ // reference
+ // the class itself.
+ private static String STATIC_LOGGER_BINDER_PATH = "org/slf4j/impl/StaticLoggerBinder.class";
+
+ static Set findPossibleStaticLoggerBinderPathSet() {
+ // use Set instead of list in order to deal with bug #138
+ // LinkedHashSet appropriate here because it preserves insertion order
+ // during iteration
+ Set staticLoggerBinderPathSet = new LinkedHashSet();
+ try {
+ ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader();
+ Enumeration paths;
+ if (loggerFactoryClassLoader == null) {
+ paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
+ } else {
+ paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH);
+ }
+ while (paths.hasMoreElements()) {
+ URL path = paths.nextElement();
+ staticLoggerBinderPathSet.add(path);
+ }
+ } catch (IOException ioe) {
+ Util.report("Error getting resources from path", ioe);
+ }
+ return staticLoggerBinderPathSet;
+ }
+
+ private static boolean isAmbiguousStaticLoggerBinderPathSet(Set binderPathSet) {
+ return binderPathSet.size() > 1;
+ }
+
+ /**
+ * Prints a warning message on the console if multiple bindings were found
+ * on the class path. No reporting is done otherwise.
+ *
+ */
+ private static void reportMultipleBindingAmbiguity(Set binderPathSet) {
+ if (isAmbiguousStaticLoggerBinderPathSet(binderPathSet)) {
+ Util.report("Class path contains multiple SLF4J bindings.");
+ for (URL path : binderPathSet) {
+ Util.report("Found binding in [" + path + "]");
+ }
+ Util.report("See " + MULTIPLE_BINDINGS_URL + " for an explanation.");
+ }
+ }
+
+ private static boolean isAndroid() {
+ String vendor = Util.safeGetSystemProperty(JAVA_VENDOR_PROPERTY);
+ if (vendor == null)
+ return false;
+ return vendor.toLowerCase().contains("android");
+ }
+
+ private static void reportActualBinding(Set binderPathSet) {
+ // binderPathSet can be null under Android
+ if (binderPathSet != null && isAmbiguousStaticLoggerBinderPathSet(binderPathSet)) {
+ Util.report("Actual binding is of type [" + StaticLoggerBinder.getSingleton().getLoggerFactoryClassStr() + "]");
+ }
+ }
+
+ /**
+ * Return a logger named according to the name parameter using the
+ * statically bound {@link ILoggerFactory} instance.
+ *
+ * @param name
+ * The name of the logger.
+ * @return logger
+ */
+ public static Logger getLogger(String name) {
+ ILoggerFactory iLoggerFactory = getILoggerFactory();
+ return iLoggerFactory.getLogger(name);
+ }
+
+ /**
+ * Return a logger named corresponding to the class passed as parameter,
+ * using the statically bound {@link ILoggerFactory} instance.
+ *
+ *
+ * In case the the clazz
parameter differs from the name of the
+ * caller as computed internally by SLF4J, a logger name mismatch warning
+ * will be printed but only if the
+ * slf4j.detectLoggerNameMismatch
system property is set to
+ * true. By default, this property is not set and no warnings will be
+ * printed even in case of a logger name mismatch.
+ *
+ * @param clazz
+ * the returned logger will be named after clazz
+ * @return logger
+ *
+ *
+ * @see Detected
+ * logger name mismatch
+ */
+ public static Logger getLogger(Class> clazz) {
+ Logger logger = getLogger(clazz.getName());
+ if (DETECT_LOGGER_NAME_MISMATCH) {
+ Class> autoComputedCallingClass = Util.getCallingClass();
+ if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
+ Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(),
+ autoComputedCallingClass.getName()));
+ Util.report("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation");
+ }
+ }
+ return logger;
+ }
+
+ private static boolean nonMatchingClasses(Class> clazz, Class> autoComputedCallingClass) {
+ return !autoComputedCallingClass.isAssignableFrom(clazz);
+ }
+
+ /**
+ * Return the {@link ILoggerFactory} instance in use.
+ *
+ *
+ * ILoggerFactory instance is bound with this class at compile time.
+ *
+ * @return the ILoggerFactory instance in use
+ */
+ public static ILoggerFactory getILoggerFactory() {
+ if (INITIALIZATION_STATE == UNINITIALIZED) {
+ synchronized (LoggerFactory.class) {
+ if (INITIALIZATION_STATE == UNINITIALIZED) {
+ INITIALIZATION_STATE = ONGOING_INITIALIZATION;
+ performInitialization();
+ }
+ }
+ }
+ switch (INITIALIZATION_STATE) {
+ case SUCCESSFUL_INITIALIZATION:
+ return StaticLoggerBinder.getSingleton().getLoggerFactory();
+ case NOP_FALLBACK_INITIALIZATION:
+ return NOP_FALLBACK_FACTORY;
+ case FAILED_INITIALIZATION:
+ throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
+ case ONGOING_INITIALIZATION:
+ // support re-entrant behavior.
+ // See also http://jira.qos.ch/browse/SLF4J-97
+ return SUBST_FACTORY;
+ }
+ throw new IllegalStateException("Unreachable code");
+ }
+}
diff --git a/src/main/java/org/slf4j/impl/SimpleLogger.java b/src/main/java/org/slf4j/impl/SimpleLogger.java
new file mode 100644
index 0000000..0440df3
--- /dev/null
+++ b/src/main/java/org/slf4j/impl/SimpleLogger.java
@@ -0,0 +1,705 @@
+/**
+ * Copyright (c) 2004-2012 QOS.ch
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+package org.slf4j.impl;
+
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.event.LoggingEvent;
+import org.slf4j.helpers.FormattingTuple;
+import org.slf4j.helpers.MarkerIgnoringBase;
+import org.slf4j.helpers.MessageFormatter;
+import org.slf4j.helpers.Util;
+import org.slf4j.spi.LocationAwareLogger;
+
+/**
+ * Simple implementation of {@link Logger} that sends all enabled log messages,
+ * for all defined loggers, to the console ({@code System.err}).
+ * The following system properties are supported to configure the behavior of this logger:
+ *
+ *
+ * org.slf4j.simpleLogger.logFile
- The output target which can be the path to a file, or
+ * the special values "System.out" and "System.err". Default is "System.err".
+ *
+ * org.slf4j.simpleLogger.defaultLogLevel
- Default log level for all instances of SimpleLogger.
+ * Must be one of ("trace", "debug", "info", "warn", or "error"). If not specified, defaults to "info".
+ *
+ * org.slf4j.simpleLogger.log.a.b.c
- Logging detail level for a SimpleLogger instance
+ * named "a.b.c". Right-side value must be one of "trace", "debug", "info", "warn", or "error". When a SimpleLogger
+ * named "a.b.c" is initialized, its level is assigned from this property. If unspecified, the level of nearest parent
+ * logger will be used, and if none is set, then the value specified by
+ * org.slf4j.simpleLogger.defaultLogLevel
will be used.
+ *
+ * org.slf4j.simpleLogger.showDateTime
- Set to true
if you want the current date and
+ * time to be included in output messages. Default is false
+ *
+ * org.slf4j.simpleLogger.dateTimeFormat
- The date and time format to be used in the output messages.
+ * The pattern describing the date and time format is defined by
+ * SimpleDateFormat
.
+ * If the format is not specified or is invalid, the number of milliseconds since start up will be output.
+ *
+ * org.slf4j.simpleLogger.showThreadName
-Set to true
if you want to output the current
+ * thread name. Defaults to true
.
+ *
+ * org.slf4j.simpleLogger.showLogName
- Set to true
if you want the Logger instance name
+ * to be included in output messages. Defaults to true
.
+ *
+ * org.slf4j.simpleLogger.showShortLogName
- Set to true
if you want the last component
+ * of the name to be included in output messages. Defaults to false
.
+ *
+ * org.slf4j.simpleLogger.levelInBrackets
- Should the level string be output in brackets? Defaults
+ * to false
.
+ *
+ * org.slf4j.simpleLogger.warnLevelString
- The string value output for the warn level. Defaults
+ * to WARN
.
+
+ *
+ *
+ * In addition to looking for system properties with the names specified above, this implementation also checks for
+ * a class loader resource named "simplelogger.properties"
, and includes any matching definitions
+ * from this resource (if it exists).
+ *
+ * With no configuration, the default output includes the relative time in milliseconds, thread name, the level,
+ * logger name, and the message followed by the line separator for the host. In log4j terms it amounts to the "%r [%t]
+ * %level %logger - %m%n" pattern.
+ * Sample output follows.
+ *
+ * 176 [main] INFO examples.Sort - Populating an array of 2 elements in reverse order.
+ * 225 [main] INFO examples.SortAlgo - Entered the sort method.
+ * 304 [main] INFO examples.SortAlgo - Dump of integer array:
+ * 317 [main] INFO examples.SortAlgo - Element [0] = 0
+ * 331 [main] INFO examples.SortAlgo - Element [1] = 1
+ * 343 [main] INFO examples.Sort - The next log statement should be an error message.
+ * 346 [main] ERROR examples.SortAlgo - Tried to dump an uninitialized array.
+ * at org.log4j.examples.SortAlgo.dump(SortAlgo.java:58)
+ * at org.log4j.examples.Sort.main(Sort.java:64)
+ * 467 [main] INFO examples.Sort - Exiting main method.
+ *
+ *
+ * This implementation is heavily inspired by
+ * Apache Commons Logging's SimpleLog.
+ *
+ * @author Ceki Gülcü
+ * @author Scott Sanders
+ * @author Rod Waldhoff
+ * @author Robert Burrell Donkin
+ * @author Cédrik LIME
+ */
+public class SimpleLogger extends MarkerIgnoringBase {
+
+ private static final long serialVersionUID = -632788891211436180L;
+ private static final String CONFIGURATION_FILE = "simplelogger.properties";
+
+ private static long START_TIME = System.currentTimeMillis();
+ private static final Properties SIMPLE_LOGGER_PROPS = new Properties();
+
+ private static final int LOG_LEVEL_TRACE = LocationAwareLogger.TRACE_INT;
+ private static final int LOG_LEVEL_DEBUG = LocationAwareLogger.DEBUG_INT;
+ private static final int LOG_LEVEL_INFO = LocationAwareLogger.INFO_INT;
+ private static final int LOG_LEVEL_WARN = LocationAwareLogger.WARN_INT;
+ private static final int LOG_LEVEL_ERROR = LocationAwareLogger.ERROR_INT;
+ private static final int LOG_LEVEL_GROUP_START = LocationAwareLogger.GROUP_START_INT;
+ private static final int LOG_LEVEL_GROUP_END = LocationAwareLogger.GROUP_END_INT;
+ private static final int LOG_LEVEL_SUBTAG_FINISH = LocationAwareLogger.SUBTAG_FINISH_INT;
+
+ private static boolean INITIALIZED = false;
+
+ private static int DEFAULT_LOG_LEVEL = LOG_LEVEL_INFO;
+ private static boolean SHOW_DATE_TIME = false;
+ private static String DATE_TIME_FORMAT_STR = null;
+ private static DateFormat DATE_FORMATTER = null;
+ private static boolean SHOW_THREAD_NAME = false;
+ private static boolean SHOW_LOG_NAME = false;
+ private static boolean SHOW_SHORT_LOG_NAME = false;
+ private static String LOG_FILE = "System.err";
+ private static PrintStream TARGET_STREAM = null;
+ private static boolean LEVEL_IN_BRACKETS = false;
+ private static String WARN_LEVEL_STRING = "WARN";
+
+ /** All system properties used by SimpleLogger
start with this prefix */
+ public static final String SYSTEM_PREFIX = "org.slf4j.simpleLogger.";
+
+ public static final String DEFAULT_LOG_LEVEL_KEY = SYSTEM_PREFIX + "defaultLogLevel";
+ public static final String SHOW_DATE_TIME_KEY = SYSTEM_PREFIX + "showDateTime";
+ public static final String DATE_TIME_FORMAT_KEY = SYSTEM_PREFIX + "dateTimeFormat";
+ public static final String SHOW_THREAD_NAME_KEY = SYSTEM_PREFIX + "showThreadName";
+ public static final String SHOW_LOG_NAME_KEY = SYSTEM_PREFIX + "showLogName";
+ public static final String SHOW_SHORT_LOG_NAME_KEY = SYSTEM_PREFIX + "showShortLogName";
+ public static final String LOG_FILE_KEY = SYSTEM_PREFIX + "logFile";
+ public static final String LEVEL_IN_BRACKETS_KEY = SYSTEM_PREFIX + "levelInBrackets";
+ public static final String WARN_LEVEL_STRING_KEY = SYSTEM_PREFIX + "warnLevelString";
+
+ public static final String LOG_KEY_PREFIX = SYSTEM_PREFIX + "log.";
+
+ public static String LOG_SUBTAG_FLAG = "##subTag##";
+
+ public static String LOG_SUBTAG_FINISH_FLAG = "##subTagFinish##";
+
+ private static String getStringProperty(String name) {
+ String prop = null;
+ try {
+ prop = System.getProperty(name);
+ } catch (SecurityException e) {
+ ; // Ignore
+ }
+ return (prop == null) ? SIMPLE_LOGGER_PROPS.getProperty(name) : prop;
+ }
+
+ private static String getStringProperty(String name, String defaultValue) {
+ String prop = getStringProperty(name);
+ return (prop == null) ? defaultValue : prop;
+ }
+
+ private static boolean getBooleanProperty(String name, boolean defaultValue) {
+ String prop = getStringProperty(name);
+ return (prop == null) ? defaultValue : "true".equalsIgnoreCase(prop);
+ }
+
+ // Initialize class attributes.
+ // Load properties file, if found.
+ // Override with system properties.
+ static void init() {
+ if (INITIALIZED) {
+ return;
+ }
+ INITIALIZED = true;
+ loadProperties();
+
+ String defaultLogLevelString = getStringProperty(DEFAULT_LOG_LEVEL_KEY, null);
+ if (defaultLogLevelString != null)
+ DEFAULT_LOG_LEVEL = stringToLevel(defaultLogLevelString);
+
+ SHOW_LOG_NAME = getBooleanProperty(SHOW_LOG_NAME_KEY, SHOW_LOG_NAME);
+ SHOW_SHORT_LOG_NAME = getBooleanProperty(SHOW_SHORT_LOG_NAME_KEY, SHOW_SHORT_LOG_NAME);
+ SHOW_DATE_TIME = getBooleanProperty(SHOW_DATE_TIME_KEY, SHOW_DATE_TIME);
+ SHOW_THREAD_NAME = getBooleanProperty(SHOW_THREAD_NAME_KEY, SHOW_THREAD_NAME);
+ DATE_TIME_FORMAT_STR = getStringProperty(DATE_TIME_FORMAT_KEY, DATE_TIME_FORMAT_STR);
+ LEVEL_IN_BRACKETS = getBooleanProperty(LEVEL_IN_BRACKETS_KEY, LEVEL_IN_BRACKETS);
+ WARN_LEVEL_STRING = getStringProperty(WARN_LEVEL_STRING_KEY, WARN_LEVEL_STRING);
+
+ LOG_FILE = getStringProperty(LOG_FILE_KEY, LOG_FILE);
+ TARGET_STREAM = computeTargetStream(LOG_FILE);
+
+ if (DATE_TIME_FORMAT_STR != null) {
+ try {
+ DATE_FORMATTER = new SimpleDateFormat(DATE_TIME_FORMAT_STR);
+ } catch (IllegalArgumentException e) {
+ Util.report("Bad date format in " + CONFIGURATION_FILE + "; will output relative time", e);
+ }
+ }
+ }
+
+ private static PrintStream computeTargetStream(String logFile) {
+ if ("System.err".equalsIgnoreCase(logFile))
+ return System.err;
+ else if ("System.out".equalsIgnoreCase(logFile)) {
+ return System.out;
+ } else {
+ try {
+ FileOutputStream fos = new FileOutputStream(logFile);
+ PrintStream printStream = new PrintStream(fos);
+ return printStream;
+ } catch (FileNotFoundException e) {
+ Util.report("Could not open [" + logFile + "]. Defaulting to System.err", e);
+ return System.err;
+ }
+ }
+ }
+
+ private static void loadProperties() {
+ // Add props from the resource simplelogger.properties
+ InputStream in = AccessController.doPrivileged(new PrivilegedAction() {
+ public InputStream run() {
+ ClassLoader threadCL = Thread.currentThread().getContextClassLoader();
+ if (threadCL != null) {
+ return threadCL.getResourceAsStream(CONFIGURATION_FILE);
+ } else {
+ return ClassLoader.getSystemResourceAsStream(CONFIGURATION_FILE);
+ }
+ }
+ });
+ if (null != in) {
+ try {
+ SIMPLE_LOGGER_PROPS.load(in);
+ in.close();
+ } catch (java.io.IOException e) {
+ // ignored
+ }
+ }
+ }
+
+ /** The current log level */
+ protected int currentLogLevel = LOG_LEVEL_INFO;
+ /** The short name of this simple log instance */
+ private transient String shortLogName = null;
+
+ /**
+ * Package access allows only {@link SimpleLoggerFactory} to instantiate
+ * SimpleLogger instances.
+ */
+ SimpleLogger(String name) {
+ this.name = name;
+
+ String levelString = recursivelyComputeLevelString();
+ if (levelString != null) {
+ this.currentLogLevel = stringToLevel(levelString);
+ } else {
+ this.currentLogLevel = DEFAULT_LOG_LEVEL;
+ }
+ }
+
+ String recursivelyComputeLevelString() {
+ String tempName = name;
+ String levelString = null;
+ int indexOfLastDot = tempName.length();
+ while ((levelString == null) && (indexOfLastDot > -1)) {
+ tempName = tempName.substring(0, indexOfLastDot);
+ levelString = getStringProperty(LOG_KEY_PREFIX + tempName, null);
+ indexOfLastDot = String.valueOf(tempName).lastIndexOf(".");
+ }
+ return levelString;
+ }
+
+ private static int stringToLevel(String levelStr) {
+ if ("trace".equalsIgnoreCase(levelStr)) {
+ return LOG_LEVEL_TRACE;
+ } else if ("debug".equalsIgnoreCase(levelStr)) {
+ return LOG_LEVEL_DEBUG;
+ } else if ("info".equalsIgnoreCase(levelStr)) {
+ return LOG_LEVEL_INFO;
+ } else if ("warn".equalsIgnoreCase(levelStr)) {
+ return LOG_LEVEL_WARN;
+ } else if ("error".equalsIgnoreCase(levelStr)) {
+ return LOG_LEVEL_ERROR;
+ }
+ // assume INFO by default
+ return LOG_LEVEL_INFO;
+ }
+
+ /**
+ * This is our internal implementation for logging regular (non-parameterized)
+ * log messages.
+ *
+ * @param level One of the LOG_LEVEL_XXX constants defining the log level
+ * @param message The message itself
+ * @param t The exception whose stack trace should be logged
+ */
+ private void log(int level, String message, String subTagName, Throwable t) {
+ if (!isLevelEnabled(level)) {
+ return;
+ }
+
+ StringBuilder buf = new StringBuilder(32);
+
+ // Append sub-tag if specified
+ if (subTagName != null) {
+ buf.append(LOG_SUBTAG_FLAG).append(subTagName).append(LOG_SUBTAG_FLAG);
+
+ // Append sub-tag finsh flag
+ if (level == LOG_LEVEL_SUBTAG_FINISH) buf.append(LOG_SUBTAG_FINISH_FLAG);
+ }
+
+ // Append date-time if so configured
+ if (SHOW_DATE_TIME) {
+ if (DATE_FORMATTER != null) {
+ buf.append(getFormattedDate());
+ buf.append(' ');
+ } else {
+ buf.append(System.currentTimeMillis() - START_TIME);
+ buf.append(' ');
+ }
+ }
+
+ // Append current thread name if so configured
+ if (SHOW_THREAD_NAME) {
+ buf.append('[');
+ buf.append(Thread.currentThread().getName());
+ buf.append("] ");
+ }
+
+ if (LEVEL_IN_BRACKETS)
+ buf.append('[');
+
+ // Append a readable representation of the log level
+ switch (level) {
+ case LOG_LEVEL_TRACE:
+ buf.append("TRACE");
+ break;
+ case LOG_LEVEL_DEBUG:
+ buf.append("##[debug]");
+ break;
+ case LOG_LEVEL_INFO:
+ buf.append("##[info]");
+ break;
+ case LOG_LEVEL_WARN:
+ buf.append("##[warning]");
+ break;
+ case LOG_LEVEL_ERROR:
+ buf.append("##[error]");
+ break;
+ case LOG_LEVEL_GROUP_START:
+ buf.append("##[group]");
+ break;
+ case LOG_LEVEL_GROUP_END:
+ buf.append("##[endgroup]");
+ break;
+ }
+ if (LEVEL_IN_BRACKETS)
+ buf.append(']');
+// buf.append(' ');
+
+ // Append the name of the log instance if so configured
+ if (SHOW_SHORT_LOG_NAME) {
+ if (shortLogName == null)
+ shortLogName = computeShortName();
+ buf.append(String.valueOf(shortLogName)).append(" - ");
+ } else if (SHOW_LOG_NAME) {
+ buf.append(String.valueOf(name)).append(" - ");
+ }
+
+ // Append the message
+ buf.append(message);
+
+ write(buf, t);
+
+ }
+
+ void write(StringBuilder buf, Throwable t) {
+ TARGET_STREAM.println(buf.toString());
+ if (t != null) {
+ t.printStackTrace(TARGET_STREAM);
+ }
+ TARGET_STREAM.flush();
+ }
+
+ private String getFormattedDate() {
+ Date now = new Date();
+ String dateText;
+ synchronized (DATE_FORMATTER) {
+ dateText = DATE_FORMATTER.format(now);
+ }
+ return dateText;
+ }
+
+ private String computeShortName() {
+ return name.substring(name.lastIndexOf(".") + 1);
+ }
+
+ /**
+ * For formatted messages, first substitute arguments and then log.
+ *
+ * @param level
+ * @param format
+ * @param arg1
+ * @param arg2
+ */
+ private void formatAndLog(int level, String format, Object arg1, Object arg2) {
+ if (!isLevelEnabled(level)) {
+ return;
+ }
+ FormattingTuple tp = MessageFormatter.format(format, arg1, arg2);
+ log(level, tp.getMessage(), null, tp.getThrowable());
+ }
+
+ /**
+ * For formatted messages, first substitute arguments and then log.
+ *
+ * @param level
+ * @param format
+ * @param arguments a list of 3 ore more arguments
+ */
+ private void formatAndLog(int level, String format, Object... arguments) {
+ if (!isLevelEnabled(level)) {
+ return;
+ }
+ FormattingTuple tp = MessageFormatter.arrayFormat(format, arguments);
+ log(level, tp.getMessage(), null, tp.getThrowable());
+ }
+
+ /**
+ * Is the given log level currently enabled?
+ *
+ * @param logLevel is this level enabled?
+ */
+ protected boolean isLevelEnabled(int logLevel) {
+ // log level are numerically ordered so can use simple numeric
+ // comparison
+ return (logLevel >= currentLogLevel);
+ }
+
+ /** Are {@code trace} messages currently enabled? */
+ public boolean isTraceEnabled() {
+ return isLevelEnabled(LOG_LEVEL_TRACE);
+ }
+
+ /**
+ * A simple implementation which logs messages of level TRACE according
+ * to the format outlined above.
+ */
+ public void trace(String msg) {
+ log(LOG_LEVEL_TRACE, msg, null, null);
+ }
+
+ /**
+ * Perform single parameter substitution before logging the message of level
+ * TRACE according to the format outlined above.
+ */
+ public void trace(String format, Object param1) {
+ formatAndLog(LOG_LEVEL_TRACE, format, param1, null);
+ }
+
+ /**
+ * Perform double parameter substitution before logging the message of level
+ * TRACE according to the format outlined above.
+ */
+ public void trace(String format, Object param1, Object param2) {
+ formatAndLog(LOG_LEVEL_TRACE, format, param1, param2);
+ }
+
+ /**
+ * Perform double parameter substitution before logging the message of level
+ * TRACE according to the format outlined above.
+ */
+ public void trace(String format, Object... argArray) {
+ formatAndLog(LOG_LEVEL_TRACE, format, argArray);
+ }
+
+ /** Log a message of level TRACE, including an exception. */
+ public void trace(String msg, Throwable t) {
+ log(LOG_LEVEL_TRACE, msg, null, t);
+ }
+
+ /** Are {@code debug} messages currently enabled? */
+ public boolean isDebugEnabled() {
+ return isLevelEnabled(LOG_LEVEL_DEBUG);
+ }
+
+ /**
+ * A simple implementation which logs messages of level DEBUG according
+ * to the format outlined above.
+ */
+ public void debug(String msg) {
+ log(LOG_LEVEL_DEBUG, msg, null, null);
+ }
+
+ /**
+ * Perform single parameter substitution before logging the message of level
+ * DEBUG according to the format outlined above.
+ */
+ public void debug(String format, Object param1) {
+ formatAndLog(LOG_LEVEL_DEBUG, format, param1, null);
+ }
+
+ /**
+ * Perform double parameter substitution before logging the message of level
+ * DEBUG according to the format outlined above.
+ */
+ public void debug(String format, Object param1, Object param2) {
+ formatAndLog(LOG_LEVEL_DEBUG, format, param1, param2);
+ }
+
+ /**
+ * Perform double parameter substitution before logging the message of level
+ * DEBUG according to the format outlined above.
+ */
+ public void debug(String format, Object... argArray) {
+ formatAndLog(LOG_LEVEL_DEBUG, format, argArray);
+ }
+
+ /** Log a message of level DEBUG, including an exception. */
+ public void debug(String msg, Throwable t) {
+ log(LOG_LEVEL_DEBUG, msg, null, t);
+ }
+
+ /** Are {@code info} messages currently enabled? */
+ public boolean isInfoEnabled() {
+ return isLevelEnabled(LOG_LEVEL_INFO);
+ }
+
+ /**
+ * A simple implementation which logs messages of level INFO according
+ * to the format outlined above.
+ */
+ public void info(String msg) {
+ log(LOG_LEVEL_INFO, msg, null, null);
+ }
+
+ /**
+ * Perform single parameter substitution before logging the message of level
+ * INFO according to the format outlined above.
+ */
+ public void info(String format, Object arg) {
+ formatAndLog(LOG_LEVEL_INFO, format, arg, null);
+ }
+
+ /**
+ * Perform double parameter substitution before logging the message of level
+ * INFO according to the format outlined above.
+ */
+ public void info(String format, Object arg1, Object arg2) {
+ formatAndLog(LOG_LEVEL_INFO, format, arg1, arg2);
+ }
+
+ /**
+ * Perform double parameter substitution before logging the message of level
+ * INFO according to the format outlined above.
+ */
+ public void info(String format, Object... argArray) {
+ formatAndLog(LOG_LEVEL_INFO, format, argArray);
+ }
+
+ /** Log a message of level INFO, including an exception. */
+ public void info(String msg, Throwable t) {
+ log(LOG_LEVEL_INFO, msg, null, t);
+ }
+
+ /** Are {@code warn} messages currently enabled? */
+ public boolean isWarnEnabled() {
+ return isLevelEnabled(LOG_LEVEL_WARN);
+ }
+
+ /**
+ * A simple implementation which always logs messages of level WARN according
+ * to the format outlined above.
+ */
+ public void warn(String msg) {
+ log(LOG_LEVEL_WARN, msg, null, null);
+ }
+
+ /**
+ * Perform single parameter substitution before logging the message of level
+ * WARN according to the format outlined above.
+ */
+ public void warn(String format, Object arg) {
+ formatAndLog(LOG_LEVEL_WARN, format, arg, null);
+ }
+
+ /**
+ * Perform double parameter substitution before logging the message of level
+ * WARN according to the format outlined above.
+ */
+ public void warn(String format, Object arg1, Object arg2) {
+ formatAndLog(LOG_LEVEL_WARN, format, arg1, arg2);
+ }
+
+ /**
+ * Perform double parameter substitution before logging the message of level
+ * WARN according to the format outlined above.
+ */
+ public void warn(String format, Object... argArray) {
+ formatAndLog(LOG_LEVEL_WARN, format, argArray);
+ }
+
+ /** Log a message of level WARN, including an exception. */
+ public void warn(String msg, Throwable t) {
+ log(LOG_LEVEL_WARN, msg, null, t);
+ }
+
+ /** Are {@code error} messages currently enabled? */
+ public boolean isErrorEnabled() {
+ return isLevelEnabled(LOG_LEVEL_ERROR);
+ }
+
+ /**
+ * A simple implementation which always logs messages of level ERROR according
+ * to the format outlined above.
+ */
+ public void error(String msg) {
+ log(LOG_LEVEL_ERROR, msg, null, null);
+ }
+
+ /**
+ * Perform single parameter substitution before logging the message of level
+ * ERROR according to the format outlined above.
+ */
+ public void error(String format, Object arg) {
+ formatAndLog(LOG_LEVEL_ERROR, format, arg, null);
+ }
+
+ /**
+ * Perform double parameter substitution before logging the message of level
+ * ERROR according to the format outlined above.
+ */
+ public void error(String format, Object arg1, Object arg2) {
+ formatAndLog(LOG_LEVEL_ERROR, format, arg1, arg2);
+ }
+
+ /**
+ * Perform double parameter substitution before logging the message of level
+ * ERROR according to the format outlined above.
+ */
+ public void error(String format, Object... argArray) {
+ formatAndLog(LOG_LEVEL_ERROR, format, argArray);
+ }
+
+ /** Log a message of level ERROR, including an exception. */
+ public void error(String msg, Throwable t) {
+ log(LOG_LEVEL_ERROR, msg, null, t);
+ }
+
+ public void groupStart(String startTitle){
+ this.log(LOG_LEVEL_GROUP_START, startTitle, null, (Throwable)null);
+ }
+
+ public void groupEnd(String endTitle){
+ this.log(LOG_LEVEL_GROUP_END, endTitle, null, (Throwable)null);
+ }
+
+ public void infoInTag(String msg, String subTagName) {
+ log(LOG_LEVEL_INFO, msg, subTagName, null);
+ }
+
+ public void errorInTag(String msg, String subTagName) {
+ log(LOG_LEVEL_ERROR, msg, subTagName, null);
+ }
+
+ public void warnInTag(String msg, String subTagName) {
+ log(LOG_LEVEL_WARN, msg, subTagName, null);
+ }
+
+ public void finishTag(String msg, String subTagName) {
+ log(LOG_LEVEL_SUBTAG_FINISH, msg, subTagName, null);
+ }
+
+ public void log(LoggingEvent event) {
+ int levelInt = event.getLevel().toInt();
+
+ if (!isLevelEnabled(levelInt)) {
+ return;
+ }
+ FormattingTuple tp = MessageFormatter.arrayFormat(event.getMessage(), event.getArgumentArray(), event.getThrowable());
+ log(levelInt, tp.getMessage(), null, event.getThrowable());
+ }
+
+}
diff --git a/src/main/java/org/slf4j/spi/LocationAwareLogger.java b/src/main/java/org/slf4j/spi/LocationAwareLogger.java
new file mode 100644
index 0000000..5c7d438
--- /dev/null
+++ b/src/main/java/org/slf4j/spi/LocationAwareLogger.java
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2004-2011 QOS.ch
+ * All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+package org.slf4j.spi;
+
+import org.slf4j.Logger;
+import org.slf4j.Marker;
+
+/**
+ * An optional interface helping integration with logging systems capable of
+ * extracting location information. This interface is mainly used by SLF4J bridges
+ * such as jcl-over-slf4j, jul-to-slf4j and log4j-over-slf4j or {@link Logger} wrappers
+ * which need to provide hints so that the underlying logging system can extract
+ * the correct location information (method name, line number).
+ *
+ * @author Ceki Gulcu
+ * @since 1.3
+ */
+public interface LocationAwareLogger extends Logger {
+
+ // these constants should be in EventContants. However, in order to preserve binary backward compatibility
+ // we keep these constants here
+ final public int TRACE_INT = 00;
+ final public int DEBUG_INT = 10;
+ final public int INFO_INT = 20;
+ final public int WARN_INT = 30;
+ final public int ERROR_INT = 40;
+ final public int GROUP_START_INT = 50;
+ final public int GROUP_END_INT = 51;
+ final public int SUBTAG_FINISH_INT = 51;
+
+ /**
+ * Printing method with support for location information.
+ *
+ * @param marker The marker to be used for this event, may be null.
+ * @param fqcn The fully qualified class name of the logger instance,
+ * typically the logger class, logger bridge or a logger wrapper.
+ * @param level One of the level integers defined in this interface
+ * @param message The message for the log event
+ * @param t Throwable associated with the log event, may be null.
+ */
+ public void log(Marker marker, String fqcn, int level, String message, Object[] argArray, Throwable t);
+
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/common/OS.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/common/OS.kt
new file mode 100644
index 0000000..ba45f62
--- /dev/null
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/common/OS.kt
@@ -0,0 +1,7 @@
+package com.tencent.bk.devops.plugin.common
+
+enum class OS {
+ MACOS,
+ WINDOWS,
+ LINUX
+}
\ No newline at end of file
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/executor/docker/CommonExecutor.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/CommonExecutor.kt
similarity index 84%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/executor/docker/CommonExecutor.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/docker/CommonExecutor.kt
index b0c6bb6..fc77eba 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/executor/docker/CommonExecutor.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/CommonExecutor.kt
@@ -1,15 +1,15 @@
-package com.tencent.bk.devops.plugin.executor.docker
+package com.tencent.bk.devops.plugin.docker
import com.fasterxml.jackson.core.type.TypeReference
import com.tencent.bk.devops.atom.api.SdkEnv
import com.tencent.bk.devops.atom.pojo.Result
import com.tencent.bk.devops.atom.utils.http.OkHttpUtils
import com.tencent.bk.devops.atom.utils.json.JsonUtil
-import com.tencent.bk.devops.plugin.pojo.docker.DockerRunLogRequest
-import com.tencent.bk.devops.plugin.pojo.docker.DockerRunLogResponse
-import com.tencent.bk.devops.plugin.pojo.docker.DockerRunRequest
-import com.tencent.bk.devops.plugin.pojo.docker.DockerRunResponse
-import com.tencent.bk.devops.plugin.pojo.docker.common.DockerStatus
+import com.tencent.bk.devops.plugin.docker.pojo.DockerRunLogRequest
+import com.tencent.bk.devops.plugin.docker.pojo.DockerRunLogResponse
+import com.tencent.bk.devops.plugin.docker.pojo.DockerRunRequest
+import com.tencent.bk.devops.plugin.docker.pojo.DockerRunResponse
+import com.tencent.bk.devops.plugin.docker.pojo.common.DockerStatus
import org.apache.tools.ant.types.Commandline
import org.slf4j.LoggerFactory
@@ -17,6 +17,8 @@ object CommonExecutor {
private val logger = LoggerFactory.getLogger(CommonExecutor::class.java)
+ private const val ONE_MILL_SECONDS = 1000
+
fun execute(
projectId: String,
pipelineId: String,
@@ -28,12 +30,14 @@ object CommonExecutor {
val dockerHostIP = System.getenv("docker_host_ip")
val dockerHostPort = System.getenv("docker_host_port") ?: "80"
val vmSeqId = SdkEnv.getVmSeqId()
- val dockerRunUrl = "http://$dockerHostIP:$dockerHostPort/api/docker/run/$projectId/$pipelineId/$vmSeqId/$buildId"
+ val dockerRunUrl =
+ "http://$dockerHostIP:$dockerHostPort/api/docker/run/$projectId/$pipelineId/$vmSeqId/$buildId"
logger.info("execute docker run url: $dockerRunUrl")
val responseContent = OkHttpUtils.doPost(dockerRunUrl, runParam)
logger.info("execute docker run response: $responseContent")
- val extraOptions = JsonUtil.fromJson(responseContent, object : TypeReference>>() {}).data
+ val extraOptions =
+ JsonUtil.fromJson(responseContent, object : TypeReference>>() {}).data
return DockerRunResponse(
extraOptions = mapOf(
"containerId" to extraOptions["containerId"].toString(),
@@ -54,7 +58,8 @@ object CommonExecutor {
val dockerHostPort = System.getenv("docker_host_port") ?: "80"
val vmSeqId = SdkEnv.getVmSeqId()
val dockerGetLogUrl =
- "http://$dockerHostIP:$dockerHostPort/api/docker/runlog/$projectId/$pipelineId/$vmSeqId/$buildId/$containerId/$startTimeStamp"
+ "http://$dockerHostIP:$dockerHostPort/api/docker/runlog/" +
+ "$projectId/$pipelineId/$vmSeqId/$buildId/$containerId/$startTimeStamp"
val logResponse = OkHttpUtils.doGet(dockerGetLogUrl)
val logResult = JsonUtil.fromJson(logResponse, object : TypeReference>() {}).data
?: return DockerRunLogResponse(
@@ -85,7 +90,7 @@ object CommonExecutor {
status = DockerStatus.running,
message = "get log...",
extraOptions = request.extraOptions.plus(mapOf(
- "startTimeStamp" to (startTimeStamp.toLong() + request.timeGap / 1000).toString()
+ "startTimeStamp" to (startTimeStamp.toLong() + request.timeGap / ONE_MILL_SECONDS).toString()
))
)
}
@@ -96,7 +101,8 @@ object CommonExecutor {
val runParam = with(param) {
val cmdTmp = mutableListOf()
command.forEach {
- cmdTmp.add(it.removePrefix("\"").removeSuffix("\"").removePrefix("\'").removeSuffix("\'"))
+ cmdTmp.add(it.removePrefix("\"").removeSuffix("\"")
+ .removePrefix("\'").removeSuffix("\'"))
}
val cmd = if (cmdTmp.size == 1) {
Commandline.translateCommandline(cmdTmp.first()).toList()
@@ -140,7 +146,8 @@ object CommonExecutor {
val poolNo: String?
) {
override fun toString(): String {
- return "image name: $imageName, registry user: $registryUser, command: $command, env: $env, pool no: $poolNo"
+ return "image name: $imageName, registry user: $registryUser, " +
+ "command: $command, env: $env, pool no: $poolNo"
}
}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/docker/DockerApi.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/DockerApi.kt
new file mode 100644
index 0000000..8bc0b31
--- /dev/null
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/DockerApi.kt
@@ -0,0 +1,67 @@
+package com.tencent.bk.devops.plugin.docker
+
+import com.tencent.bk.devops.atom.api.BaseApi
+import com.tencent.bk.devops.plugin.docker.exception.DockerRunException
+import com.tencent.bk.devops.plugin.docker.exception.DockerRunLogException
+import com.tencent.bk.devops.plugin.docker.pojo.DockerRunLogRequest
+import com.tencent.bk.devops.plugin.docker.pojo.DockerRunLogResponse
+import com.tencent.bk.devops.plugin.docker.pojo.DockerRunRequest
+import com.tencent.bk.devops.plugin.docker.pojo.DockerRunResponse
+import com.tencent.bk.devops.atom.pojo.Result
+import org.slf4j.LoggerFactory
+
+open class DockerApi : BaseApi() {
+
+ companion object {
+ private val logger = LoggerFactory.getLogger(DockerApi::class.java)
+ }
+
+ fun dockerRunCommand(projectId: String, pipelineId: String, buildId: String,
+ param: DockerRunRequest): Result {
+ try {
+ val property = System.getenv("devops_slave_model")
+
+ var response = dockerRunCustomize(projectId, pipelineId, buildId, param)
+
+ if (response == null) {
+ response = when {
+ "docker" == property -> CommonExecutor.execute(projectId, pipelineId, buildId, param)
+ else -> ThirdPartExecutor.execute(param)
+ }
+ }
+ return Result(response)
+ } catch (e: Exception) {
+ throw DockerRunException(e.message ?: "")
+ }
+ }
+
+ open fun dockerRunCustomize(
+ projectId: String, pipelineId: String, buildId: String, param: DockerRunRequest): DockerRunResponse? {
+ return null
+ }
+
+ fun dockerRunGetLog(projectId: String, pipelineId: String, buildId: String,
+ param: DockerRunLogRequest): Result {
+ try {
+ val property = System.getenv("devops_slave_model")
+
+ var response = dockerRunGetLogCustomize(projectId, pipelineId, buildId, param)
+
+ if (response == null) {
+ response = when {
+ "docker" == property -> CommonExecutor.getLogs(projectId, pipelineId, buildId, param)
+ else -> ThirdPartExecutor.getLogs(param)
+ }
+ }
+
+ return Result(response)
+ } catch (e: Exception) {
+ throw DockerRunLogException(e.message ?: "")
+ }
+ }
+
+ open fun dockerRunGetLogCustomize(
+ projectId: String, pipelineId: String, buildId: String, param: DockerRunLogRequest): DockerRunLogResponse? {
+ return null
+ }
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/executor/docker/ThirdPartExecutor.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/ThirdPartExecutor.kt
similarity index 82%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/executor/docker/ThirdPartExecutor.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/docker/ThirdPartExecutor.kt
index 39dc1e8..695157e 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/executor/docker/ThirdPartExecutor.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/ThirdPartExecutor.kt
@@ -1,16 +1,15 @@
-package com.tencent.bk.devops.plugin.executor.docker
+package com.tencent.bk.devops.plugin.docker
-import com.fasterxml.jackson.core.type.TypeReference
import com.tencent.bk.devops.atom.utils.json.JsonUtil
-import com.tencent.bk.devops.plugin.exception.docker.DockerPullException
-import com.tencent.bk.devops.plugin.pojo.docker.DockerRunLogRequest
-import com.tencent.bk.devops.plugin.pojo.docker.DockerRunLogResponse
-import com.tencent.bk.devops.plugin.pojo.docker.DockerRunRequest
-import com.tencent.bk.devops.plugin.pojo.docker.DockerRunResponse
-import com.tencent.bk.devops.plugin.pojo.docker.common.DockerStatus
-import com.tencent.bk.devops.plugin.utils.script.ScriptUtils
+import com.tencent.bk.devops.plugin.docker.exception.DockerPullException
+import com.tencent.bk.devops.plugin.docker.pojo.DockerRunLogRequest
+import com.tencent.bk.devops.plugin.docker.pojo.DockerRunLogResponse
+import com.tencent.bk.devops.plugin.docker.pojo.DockerRunRequest
+import com.tencent.bk.devops.plugin.docker.pojo.DockerRunResponse
+import com.tencent.bk.devops.plugin.docker.pojo.common.DockerStatus
+import com.tencent.bk.devops.plugin.docker.utils.ParamUtils.beiJ2UTC
+import com.tencent.bk.devops.plugin.script.ScriptUtils
import com.tencent.bk.devops.plugin.utils.MachineEnvUtils
-import com.tencent.bk.devops.plugin.utils.ParamUtils.beiJ2UTC
import org.slf4j.LoggerFactory
import java.io.File
import java.lang.StringBuilder
@@ -51,6 +50,7 @@ object ThirdPartExecutor {
return ScriptUtils.execute(command, param.workspace)
}
+ @Synchronized
private fun doDockerPull(param: DockerRunRequest) {
try {
val pullCmd = "docker pull ${param.imageName}"
@@ -69,8 +69,10 @@ object ThirdPartExecutor {
}
fun getLogs(param: DockerRunLogRequest): DockerRunLogResponse {
- val startTimestamp = param.extraOptions["startTimestamp"]?.toLong() ?: throw RuntimeException("startTimestamp is null")
- val containerId = param.extraOptions["dockerContainerId"] ?: throw RuntimeException("dockerContainerId is null")
+ val startTimestamp = param.extraOptions["startTimestamp"]?.toLong()
+ ?: throw RuntimeException("startTimestamp is null")
+ val containerId = param.extraOptions["dockerContainerId"]
+ ?: throw RuntimeException("dockerContainerId is null")
val statusPair = getContainerStatus(containerId, param.workspace)
val status = statusPair.first
@@ -109,8 +111,9 @@ object ThirdPartExecutor {
}
private fun getContainerStatus(containerId: String, workspace: File): Pair {
- val inspectResult = ScriptUtils.execute(script = "docker inspect $containerId", dir = workspace, printLog = false)
- val inspectMap = JsonUtil.fromJson(inspectResult, object : TypeReference>>() {}).first()
+ val inspectResult =
+ ScriptUtils.execute(script = "docker inspect $containerId", dir = workspace, printLog = false)
+ val inspectMap = JsonUtil.fromJson>>(inspectResult).first()
val state = inspectMap["State"] as Map
val status = state["Status"] as String
if (status == "running") return Pair(DockerStatus.running, "")
@@ -129,6 +132,7 @@ object ThirdPartExecutor {
ScriptUtils.execute(script = cmd, dir = workspace, failExit = false)
}
+ @Synchronized
private fun dockerLogin(param: DockerRunRequest) {
if (param.dockerLoginUsername.isNullOrBlank()) return
@@ -137,10 +141,12 @@ object ThirdPartExecutor {
val loginHost = param.imageName.split("/").first()
// WARNING! Using --password via the CLI is insecure. Use --password-stdin.
val commandStr = "docker login $loginHost --username $username --password $password"
- logger.info("[execute script]: " + String.format("docker login %s --username %s --password ***", loginHost, username))
+ logger.info("[execute script]: " +
+ String.format("docker login %s --username %s --password ***", loginHost, username))
ScriptUtils.execute(commandStr, param.workspace)
}
+ @Synchronized
private fun dockerLogout(param: DockerRunRequest) {
if (param.dockerLoginUsername.isNullOrBlank()) return
@@ -149,4 +155,4 @@ object ThirdPartExecutor {
logger.info("[execute script]: $commandStr")
ScriptUtils.execute(commandStr, param.workspace)
}
-}
\ No newline at end of file
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/exception/docker/DockerPullException.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/exception/DockerPullException.kt
similarity index 60%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/exception/docker/DockerPullException.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/docker/exception/DockerPullException.kt
index 990fa9f..a833666 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/exception/docker/DockerPullException.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/exception/DockerPullException.kt
@@ -1,8 +1,8 @@
-package com.tencent.bk.devops.plugin.exception.docker
+package com.tencent.bk.devops.plugin.docker.exception
import java.lang.RuntimeException
data class DockerPullException(
val errorMsg: String,
val errorCode: Int = 2198001
-): RuntimeException(errorMsg)
\ No newline at end of file
+): RuntimeException(errorMsg)
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/exception/docker/DockerRunException.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/exception/DockerRunException.kt
similarity index 60%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/exception/docker/DockerRunException.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/docker/exception/DockerRunException.kt
index ebd6230..ae1e22f 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/exception/docker/DockerRunException.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/exception/DockerRunException.kt
@@ -1,8 +1,8 @@
-package com.tencent.bk.devops.plugin.exception.docker
+package com.tencent.bk.devops.plugin.docker.exception
import java.lang.RuntimeException
data class DockerRunException(
val errorMsg: String,
val errorCode: Int = 2198002
-): RuntimeException(errorMsg)
\ No newline at end of file
+): RuntimeException(errorMsg)
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/exception/docker/DockerRunLogException.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/exception/DockerRunLogException.kt
similarity index 60%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/exception/docker/DockerRunLogException.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/docker/exception/DockerRunLogException.kt
index 815f112..3336d7f 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/exception/docker/DockerRunLogException.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/exception/DockerRunLogException.kt
@@ -1,8 +1,8 @@
-package com.tencent.bk.devops.plugin.exception.docker
+package com.tencent.bk.devops.plugin.docker.exception
import java.lang.RuntimeException
data class DockerRunLogException(
val errorMsg: String,
val errorCode: Int = 2198003
-): RuntimeException(errorMsg)
\ No newline at end of file
+): RuntimeException(errorMsg)
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/DockerRunLogRequest.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/DockerRunLogRequest.kt
similarity index 63%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/DockerRunLogRequest.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/DockerRunLogRequest.kt
index af01dd7..eca32b6 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/DockerRunLogRequest.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/DockerRunLogRequest.kt
@@ -1,4 +1,4 @@
-package com.tencent.bk.devops.plugin.pojo.docker
+package com.tencent.bk.devops.plugin.docker.pojo
import java.io.File
@@ -9,6 +9,7 @@ data class DockerRunLogRequest (
val extraOptions: Map = mapOf()
) {
override fun toString(): String {
- return "userId: $userId, workspace: $workspace, timeGap: $timeGap, extraOptions: ${extraOptions.filter { !it.key.contains("token", ignoreCase = true) }}"
+ return "userId: $userId, workspace: $workspace, timeGap: $timeGap, " +
+ "extraOptions: ${extraOptions.filter { !it.key.contains("token", ignoreCase = true) }}"
}
-}
\ No newline at end of file
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/DockerRunLogResponse.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/DockerRunLogResponse.kt
new file mode 100644
index 0000000..552cdb4
--- /dev/null
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/DockerRunLogResponse.kt
@@ -0,0 +1,15 @@
+package com.tencent.bk.devops.plugin.docker.pojo
+
+import com.tencent.bk.devops.plugin.docker.pojo.common.DockerStatus
+
+data class DockerRunLogResponse(
+ val log: List? = listOf(),
+ val status: String = DockerStatus.running,
+ val message: String,
+ val extraOptions: Map
+) {
+ override fun toString(): String {
+ return "log: $log, status: $status, message: $message, " +
+ "extraOptions: ${extraOptions.filter { !it.key.contains("token", ignoreCase = true) }}"
+ }
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/DockerRunRequest.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/DockerRunRequest.kt
similarity index 74%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/DockerRunRequest.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/DockerRunRequest.kt
index b77728a..e34321e 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/DockerRunRequest.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/DockerRunRequest.kt
@@ -1,4 +1,4 @@
-package com.tencent.bk.devops.plugin.pojo.docker
+package com.tencent.bk.devops.plugin.docker.pojo
import java.io.File
@@ -10,7 +10,9 @@ data class DockerRunRequest(
val dockerLoginPassword: String? = null,
val envMap: Map? = null,
val workspace: File,
- val extraOptions: Map? = null
+ val extraOptions: Map? = null,
+ var labels: Map? = emptyMap(),
+ var ipEnabled: Boolean? = true
) {
override fun toString(): String {
return "userId: $userId, imageName: $imageName, dockerLoginUsername: $dockerLoginUsername, " +
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/DockerRunResponse.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/DockerRunResponse.kt
similarity index 81%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/DockerRunResponse.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/DockerRunResponse.kt
index bd7c17e..e7f5c98 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/DockerRunResponse.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/DockerRunResponse.kt
@@ -1,4 +1,4 @@
-package com.tencent.bk.devops.plugin.pojo.docker
+package com.tencent.bk.devops.plugin.docker.pojo
data class DockerRunResponse(
val extraOptions: Map
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/TaskStatus.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/TaskStatus.kt
similarity index 71%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/TaskStatus.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/TaskStatus.kt
index 0aac9d6..b8307cd 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/TaskStatus.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/TaskStatus.kt
@@ -1,7 +1,7 @@
-package com.tencent.bk.devops.plugin.pojo.docker
+package com.tencent.bk.devops.plugin.docker.pojo
data class TaskStatus(
var status: String? = null,
val taskId: String? = null,
val responseBody: String? = null
-)
\ No newline at end of file
+)
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/common/DockerStatus.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/common/DockerStatus.kt
similarity index 68%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/common/DockerStatus.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/common/DockerStatus.kt
index 6127b32..1b8556e 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/common/DockerStatus.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/pojo/common/DockerStatus.kt
@@ -1,7 +1,7 @@
-package com.tencent.bk.devops.plugin.pojo.docker.common
+package com.tencent.bk.devops.plugin.docker.pojo.common
object DockerStatus {
const val success = "success"
const val failure = "failure"
const val running = "running"
-}
\ No newline at end of file
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/docker/utils/EnvUtils.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/utils/EnvUtils.kt
new file mode 100644
index 0000000..2888412
--- /dev/null
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/utils/EnvUtils.kt
@@ -0,0 +1,24 @@
+package com.tencent.bk.devops.plugin.docker.utils
+
+import org.apache.commons.lang3.StringUtils
+import org.slf4j.LoggerFactory
+import java.net.InetAddress
+import java.net.UnknownHostException
+
+object EnvUtils {
+
+ private val logger = LoggerFactory.getLogger(EnvUtils::class.java)
+
+ fun getHostName(): String {
+ var hostname = System.getenv("HOSTNAME")
+ if (hostname == null || StringUtils.isBlank(hostname)) {
+ try {
+ hostname = InetAddress.getLocalHost().hostName
+ } catch (e: UnknownHostException) {
+ e.printStackTrace()
+ }
+ }
+ logger.info("env host name is: $hostname")
+ return hostname
+ }
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/docker/utils/ParamUtils.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/utils/ParamUtils.kt
new file mode 100644
index 0000000..e0fcb64
--- /dev/null
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/docker/utils/ParamUtils.kt
@@ -0,0 +1,12 @@
+package com.tencent.bk.devops.plugin.docker.utils
+
+import java.text.SimpleDateFormat
+import java.util.TimeZone
+
+object ParamUtils {
+ fun beiJ2UTC(timestamp: Long?): String {
+ val formatter = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSSSSS'Z'")
+ formatter.timeZone = TimeZone.getTimeZone("UTC")
+ return formatter.format(timestamp ?: System.currentTimeMillis())
+ }
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/executor/docker/DockerApi.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/executor/docker/DockerApi.kt
deleted file mode 100644
index c65e6e6..0000000
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/executor/docker/DockerApi.kt
+++ /dev/null
@@ -1,46 +0,0 @@
-package com.tencent.bk.devops.plugin.executor.docker
-
-import com.tencent.bk.devops.atom.api.BaseApi
-import com.tencent.bk.devops.plugin.exception.docker.DockerRunException
-import com.tencent.bk.devops.plugin.exception.docker.DockerRunLogException
-import com.tencent.bk.devops.plugin.pojo.docker.DockerRunLogRequest
-import com.tencent.bk.devops.plugin.pojo.docker.DockerRunLogResponse
-import com.tencent.bk.devops.plugin.pojo.docker.DockerRunRequest
-import com.tencent.bk.devops.plugin.pojo.docker.DockerRunResponse
-import org.slf4j.LoggerFactory
-import com.tencent.bk.devops.atom.pojo.Result
-
-class DockerApi : BaseApi() {
-
- companion object {
- private val logger = LoggerFactory.getLogger(DockerApi::class.java)
- }
-
- fun dockerRunCommand(projectId: String, pipelineId: String, buildId: String, param: DockerRunRequest): Result {
- try {
- val property = System.getenv("devops_slave_model")
-
- val response = when {
- "docker" == property -> CommonExecutor.execute(projectId, pipelineId, buildId, param)
- else -> ThirdPartExecutor.execute(param)
- }
- return Result(response)
- } catch (e: Exception) {
- throw DockerRunException(e.message ?: "")
- }
- }
-
- fun dockerRunGetLog(projectId: String, pipelineId: String, buildId: String, param: DockerRunLogRequest): Result {
- try {
- val property = System.getenv("devops_slave_model")
-
- val response = when {
- "docker" == property -> CommonExecutor.getLogs(projectId, pipelineId, buildId, param)
- else -> ThirdPartExecutor.getLogs(param)
- }
- return Result(response)
- } catch (e: Exception) {
- throw DockerRunLogException(e.message ?: "")
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/ErrorType.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/ErrorType.kt
new file mode 100644
index 0000000..9d43c39
--- /dev/null
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/ErrorType.kt
@@ -0,0 +1,27 @@
+package com.tencent.bk.devops.plugin.pojo
+
+enum class ErrorType(val typeName: String, val num: Int) {
+ USER("用户配置错误", 1), // 1 用户配置报错
+ THIRD_PARTY("第三方系统错误", 2), // 2 第三方系统接入错误
+ PLUGIN("插件执行错误", 3); // 3 插件执行错误
+
+ companion object {
+
+ fun getErrorType(name: String): ErrorType? {
+ values().forEach { enumObj ->
+ if (enumObj.name == name) {
+ return enumObj
+ }
+ }
+ return null
+ }
+
+ fun getErrorType(ordinal: Int?): ErrorType {
+ return when (ordinal) {
+ 1 -> USER
+ 2 -> THIRD_PARTY
+ else -> PLUGIN
+ }
+ }
+ }
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/Result.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/Result.kt
new file mode 100644
index 0000000..bca7f64
--- /dev/null
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/Result.kt
@@ -0,0 +1,23 @@
+package com.tencent.bk.devops.plugin.pojo
+
+import com.fasterxml.jackson.annotation.JsonIgnore
+
+data class Result(
+ val status: Int = 0, // 状态码,0代表成功
+ val message: String? = null, // 描述信息
+ val data: T? = null
+) { // 数据对象
+
+ constructor(data: T) : this(0, null, data)
+ constructor(status: Int, message: String?) : this(status, message, null)
+
+ @JsonIgnore
+ fun isOk(): Boolean {
+ return status == 0
+ }
+
+ @JsonIgnore
+ fun isNotOk(): Boolean {
+ return status != 0
+ }
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/DockerRunLogResponse.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/DockerRunLogResponse.kt
deleted file mode 100644
index d8b4365..0000000
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/DockerRunLogResponse.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.tencent.bk.devops.plugin.pojo.docker
-
-import com.tencent.bk.devops.plugin.pojo.docker.common.DockerStatus
-
-data class DockerRunLogResponse(
- val log: List? = listOf(),
- val status: String = DockerStatus.running,
- val message: String,
- val extraOptions: Map
-) {
- override fun toString(): String {
- return "log: $log, status: $status, message: $message, extraOptions: ${extraOptions.filter { !it.key.contains("token", ignoreCase = true) }}"
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/status/JobStatusData.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/status/JobStatusData.kt
deleted file mode 100644
index ae754e4..0000000
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/status/JobStatusData.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.tencent.bk.devops.plugin.pojo.docker.status
-
-data class JobStatusData(
- val deleted: Boolean,
- val status: String,
- val pod_result: List?
-) {
- data class PodResult(
- val events: List?
- )
-
- data class PodResultEvent(
- val message: String,
- val reason: String,
- val type: String
- ) {
- override fun toString(): String {
- return "reason: $reason, type: $type"
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/status/JobStatusResponse.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/status/JobStatusResponse.kt
deleted file mode 100644
index a7a383e..0000000
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/pojo/docker/status/JobStatusResponse.kt
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.tencent.bk.devops.plugin.pojo.docker.status
-
-
-data class JobStatusResponse (
- val actionCode: Int,
- val actionMessage: String,
- val data: JobStatusData
-)
\ No newline at end of file
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/BatScriptUtil.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/script/BatScriptUtil.kt
similarity index 98%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/BatScriptUtil.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/script/BatScriptUtil.kt
index 3590ac0..c630c5a 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/BatScriptUtil.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/script/BatScriptUtil.kt
@@ -1,4 +1,4 @@
-package com.tencent.bk.devops.plugin.utils.script
+package com.tencent.bk.devops.plugin.script
import org.slf4j.LoggerFactory
import java.io.File
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/CommandLineExecutor.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/script/CommandLineExecutor.kt
similarity index 99%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/CommandLineExecutor.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/script/CommandLineExecutor.kt
index e36cae9..da4133e 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/CommandLineExecutor.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/script/CommandLineExecutor.kt
@@ -1,4 +1,4 @@
-package com.tencent.bk.devops.plugin.utils.script
+package com.tencent.bk.devops.plugin.script
import java.io.File
import java.io.IOException
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/CommandLineUtils.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/script/CommandLineUtils.kt
similarity index 93%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/CommandLineUtils.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/script/CommandLineUtils.kt
index 2909d51..ec8cbf7 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/CommandLineUtils.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/script/CommandLineUtils.kt
@@ -1,4 +1,4 @@
-package com.tencent.bk.devops.plugin.utils.script
+package com.tencent.bk.devops.plugin.script
import java.io.File
import org.apache.commons.exec.CommandLine
@@ -10,7 +10,8 @@ object CommandLineUtils {
private val logger = LoggerFactory.getLogger(CommandLineUtils::class.java)
- fun execute(command: String, workspace: File?, print2Logger: Boolean, prefix: String = "", printException: Boolean = false): String {
+ fun execute(command: String, workspace: File?, print2Logger: Boolean,
+ prefix: String = "", printException: Boolean = false): String {
val result = StringBuffer()
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/ScriptUtils.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/script/ScriptUtils.kt
similarity index 94%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/ScriptUtils.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/script/ScriptUtils.kt
index 8dce6c0..d077d7b 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/ScriptUtils.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/script/ScriptUtils.kt
@@ -1,4 +1,4 @@
-package com.tencent.bk.devops.plugin.utils.script
+package com.tencent.bk.devops.plugin.script
import com.tencent.bk.devops.plugin.utils.MachineEnvUtils
import java.io.File
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/SensitiveLineParser.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/script/SensitiveLineParser.kt
similarity index 93%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/SensitiveLineParser.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/script/SensitiveLineParser.kt
index 725c23f..ae40cec 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/SensitiveLineParser.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/script/SensitiveLineParser.kt
@@ -1,4 +1,4 @@
-package com.tencent.bk.devops.plugin.utils.script
+package com.tencent.bk.devops.plugin.script
import java.util.regex.Pattern
import org.slf4j.LoggerFactory
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/ShellUtil.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/script/ShellUtil.kt
similarity index 74%
rename from src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/ShellUtil.kt
rename to src/main/kotlin/com/tencent/bk/devops/plugin/script/ShellUtil.kt
index 4cadaf5..48d069f 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/script/ShellUtil.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/script/ShellUtil.kt
@@ -1,30 +1,4 @@
-/*
- * Tencent is pleased to support the open source community by making BK-CI 蓝鲸持续集成平台 available.
- *
- * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
- *
- * BK-CI 蓝鲸持续集成平台 is licensed under the MIT license.
- *
- * A copy of the MIT License is included in this file.
- *
- *
- * Terms of the MIT License:
- * ---------------------------------------------------
- * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation
- * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,
- * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
- * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
- * NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-package com.tencent.bk.devops.plugin.utils.script
+package com.tencent.bk.devops.plugin.script
import org.slf4j.LoggerFactory
import java.io.File
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/JsonUtil.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/utils/JsonUtil.kt
new file mode 100644
index 0000000..4f9cc88
--- /dev/null
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/utils/JsonUtil.kt
@@ -0,0 +1,144 @@
+package com.tencent.bk.devops.plugin.utils
+
+import com.fasterxml.jackson.annotation.JsonFilter
+import com.fasterxml.jackson.annotation.JsonInclude
+import com.fasterxml.jackson.core.JsonParser
+import com.fasterxml.jackson.core.type.TypeReference
+import com.fasterxml.jackson.databind.DeserializationFeature
+import com.fasterxml.jackson.databind.ObjectMapper
+import com.fasterxml.jackson.databind.SerializationFeature
+import com.fasterxml.jackson.databind.ser.FilterProvider
+import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter
+import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider
+import com.fasterxml.jackson.module.kotlin.KotlinModule
+import com.google.common.collect.Maps
+import com.tencent.bk.devops.atom.utils.json.annotation.SkipLogField
+
+object JsonUtil {
+ private val objectMapper = ObjectMapper().apply {
+ registerModule(KotlinModule())
+ configure(SerializationFeature.INDENT_OUTPUT, true)
+ configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)
+ configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true)
+ setSerializationInclusion(JsonInclude.Include.NON_NULL)
+ disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
+ }
+
+ private val skipEmptyObjectMapper = ObjectMapper().apply {
+ registerModule(KotlinModule())
+ configure(SerializationFeature.INDENT_OUTPUT, true)
+ configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true)
+ configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true)
+ setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
+ disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
+ configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
+ }
+
+ fun getObjectMapper() = objectMapper
+
+
+ private val jsonMappers: MutableMap = Maps.newConcurrentMap()
+
+ /**
+ * 序列化时忽略bean中的某些字段,字段需要用注解SkipLogFields包括
+ *
+ * @param bean 对象
+ * @param 对象类型
+ * @return Json字符串
+ * @see SkipLogField
+ */
+ fun skipLogFields(bean: T): String? {
+ return jsonMappers.computeIfAbsent("__skipLogFields__" + bean.javaClass.name) { s: String? ->
+ val nonEmptyMapper = ObjectMapper()
+ var aClass: Class<*>? = bean.javaClass
+ val skipFields: MutableSet = HashSet()
+ while (aClass != null) {
+ val fields = aClass.declaredFields
+ for (field in fields) {
+ val fieldAnnotation = field.getAnnotation(SkipLogField::class.java) ?: continue
+ if (fieldAnnotation.value.trim().isNotEmpty()) {
+ skipFields.add(fieldAnnotation.value)
+ } else {
+ skipFields.add(field.name)
+ }
+ }
+ aClass = aClass.superclass
+ }
+ if (skipFields.isNotEmpty()) {
+ nonEmptyMapper.addMixIn(bean.javaClass, SkipLogField::class.java)
+ // 仅包含
+ val filterProvider: FilterProvider = SimpleFilterProvider()
+ .addFilter(SkipLogField::class.java.getAnnotation(JsonFilter::class.java).value,
+ SimpleBeanPropertyFilter.serializeAllExcept(skipFields))
+ nonEmptyMapper.setFilterProvider(filterProvider)
+ }
+ nonEmptyMapper
+ }.writeValueAsString(bean)
+ }
+ /**
+ * 转成Json
+ */
+ fun toJson(bean: Any): String {
+ if (ReflectUtil.isNativeType(bean) || bean is String) {
+ return bean.toString()
+ }
+ return getObjectMapper().writeValueAsString(bean)!!
+ }
+
+ /**
+ * 将对象转可修改的Map,
+ * 注意:会忽略掉值为空串和null的属性
+ */
+ fun toMutableMapSkipEmpty(bean: Any): MutableMap {
+ if (ReflectUtil.isNativeType(bean)) {
+ return mutableMapOf()
+ }
+ return if (bean is String)
+ skipEmptyObjectMapper.readValue>(
+ bean.toString(),
+ object : TypeReference>() {})
+ else
+ skipEmptyObjectMapper.readValue>(
+ skipEmptyObjectMapper.writeValueAsString(bean),
+ object : TypeReference>() {})
+ }
+
+ /**
+ * 将对象转不可修改的Map
+ * 注意:会忽略掉值为null的属性
+ */
+ fun toMap(bean: Any): Map {
+ return when {
+ ReflectUtil.isNativeType(bean) -> mapOf()
+ bean is String -> to(bean)
+ else -> to(getObjectMapper().writeValueAsString(bean))
+ }
+ }
+
+ /**
+ * 将json转指定类型对象
+ * @param json json字符串
+ * @return 指定对象
+ */
+ fun to(json: String): T {
+ return getObjectMapper().readValue(json, object : TypeReference() {})
+ }
+
+ fun to(json: String, typeReference: TypeReference): T {
+ return getObjectMapper().readValue(json, typeReference)
+ }
+
+ fun to(json: String, type: Class): T = getObjectMapper().readValue(json, type)
+
+ fun toOrNull(json: String?, type: Class): T? {
+ return if (json.isNullOrBlank()) {
+ null
+ } else {
+ getObjectMapper().readValue(json, type)
+ }
+ }
+
+ fun mapTo(map: Map, type: Class): T = getObjectMapper().readValue(
+ getObjectMapper().writeValueAsString(map), type)
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/MachineEnvUtils.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/utils/MachineEnvUtils.kt
index 94ff48f..308145d 100644
--- a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/MachineEnvUtils.kt
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/utils/MachineEnvUtils.kt
@@ -22,4 +22,4 @@ object MachineEnvUtils {
const val MAC_OS = "MAC_OS"
const val OTHER = "OTHER"
}
-}
\ No newline at end of file
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/OkhttpUtils.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/utils/OkhttpUtils.kt
new file mode 100644
index 0000000..bbe0a84
--- /dev/null
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/utils/OkhttpUtils.kt
@@ -0,0 +1,154 @@
+package com.tencent.bk.devops.plugin.utils
+
+import okhttp3.ConnectionPool
+import okhttp3.Headers.Companion.toHeaders
+import okhttp3.MediaType.Companion.toMediaTypeOrNull
+import okhttp3.OkHttpClient
+import okhttp3.Request
+import okhttp3.RequestBody
+import okhttp3.Response
+import org.slf4j.LoggerFactory
+import java.io.File
+import java.io.FileOutputStream
+import java.util.concurrent.TimeUnit
+
+object OkhttpUtils {
+
+ private val logger = LoggerFactory.getLogger(OkhttpUtils::class.java)
+
+ private val okHttpClient = okhttp3.OkHttpClient.Builder()
+ .connectTimeout(60L, TimeUnit.SECONDS)
+ .readTimeout(30L, TimeUnit.MINUTES)
+ .writeTimeout(30L, TimeUnit.MINUTES)
+ .connectionPool(ConnectionPool(64, 5, TimeUnit.MINUTES))
+ .build()
+
+ private val shortOkHttpClient = okhttp3.OkHttpClient.Builder()
+ .connectTimeout(30L, TimeUnit.SECONDS)
+ .readTimeout(30L, TimeUnit.SECONDS)
+ .writeTimeout(30L, TimeUnit.SECONDS)
+ .connectionPool(ConnectionPool(64, 5, TimeUnit.MINUTES))
+ .build()
+
+ private val noRetryShortOkHttpClient = okhttp3.OkHttpClient.Builder()
+ .connectTimeout(5L, TimeUnit.SECONDS)
+ .readTimeout(30L, TimeUnit.SECONDS)
+ .writeTimeout(30L, TimeUnit.SECONDS)
+ .connectionPool(ConnectionPool(64, 5, TimeUnit.MINUTES))
+ .retryOnConnectionFailure(false)
+ .build()
+
+ private val noRetryOkHttpClient = okhttp3.OkHttpClient.Builder()
+ .connectTimeout(60L, TimeUnit.SECONDS)
+ .readTimeout(30L, TimeUnit.MINUTES)
+ .writeTimeout(30L, TimeUnit.MINUTES)
+ .connectionPool(ConnectionPool(64, 5, TimeUnit.MINUTES))
+ .retryOnConnectionFailure(false)
+ .build()
+
+ private const val CONTENT_TYPE_JSON = "application/json; charset=utf-8"
+
+ fun doShortGet(url: String, headers: Map = mapOf()): Response {
+ return doGet(shortOkHttpClient, url, headers)
+ }
+
+ fun doGet(url: String, headers: Map = mapOf()): Response {
+ return doGet(okHttpClient, url, headers)
+ }
+
+ fun doGet(client: OkHttpClient, url: String, headers: Map = mapOf()): Response {
+ val requestBuilder = Request.Builder()
+ .url(url)
+ .get()
+ if (headers.isNotEmpty()) {
+ headers.forEach { key, value ->
+ requestBuilder.addHeader(key, value)
+ }
+ }
+ val request = requestBuilder.build()
+ return client.newCall(request).execute()
+ }
+
+ fun doShortHttp(request: Request): Response {
+ return shortOkHttpClient.newCall(request).execute()
+ }
+
+ fun doShortHttpNoRetry(request: Request): Response {
+ return noRetryShortOkHttpClient.newCall(request).execute()
+ }
+
+ fun doHttp(request: Request): Response {
+ return okHttpClient.newCall(request).execute()
+ }
+
+ fun doHttpNoRetry(request: Request): Response {
+ return noRetryOkHttpClient.newCall(request).execute()
+ }
+
+ fun downloadFile(url: String, destPath: File) {
+ val request = Request.Builder()
+ .url(url)
+ .get()
+ .build()
+ okHttpClient.newCall(request).execute().use { response ->
+ if (response.code == 404) {
+ logger.warn("The file $url is not exist")
+ throw RuntimeException("文件不存在")
+ }
+ if (!response.isSuccessful) {
+ logger.warn("fail to download the file from $url " +
+ "because of ${response.message} and code ${response.code}")
+ throw RuntimeException("获取文件失败")
+ }
+ if (!destPath.parentFile.exists()) destPath.parentFile.mkdirs()
+ val buf = ByteArray(4096)
+ response.body!!.byteStream().use { bs ->
+ var len = bs.read(buf)
+ FileOutputStream(destPath).use { fos ->
+ while (len != -1) {
+ fos.write(buf, 0, len)
+ len = bs.read(buf)
+ }
+ }
+ }
+ }
+ }
+
+ fun downloadFile(response: Response, destPath: File) {
+ if (response.code == 304) {
+ logger.info("file is newest, do not download to $destPath")
+ return
+ }
+ if (!response.isSuccessful) {
+ logger.warn("fail to download the file because of ${response.message} and code ${response.code}")
+ throw RuntimeException("获取文件失败")
+ }
+ if (!destPath.parentFile.exists()) destPath.parentFile.mkdirs()
+ val buf = ByteArray(4096)
+ response.body!!.byteStream().use { bs ->
+ var len = bs.read(buf)
+ FileOutputStream(destPath).use { fos ->
+ while (len != -1) {
+ fos.write(buf, 0, len)
+ len = bs.read(buf)
+ }
+ }
+ }
+ }
+
+ fun doPost(url: String, jsonParam: String, headers: Map = mapOf()): Response {
+ val builder = getBuilder(url, headers)
+ val body = RequestBody.create(CONTENT_TYPE_JSON.toMediaTypeOrNull(), jsonParam)
+ val request = builder.post(body).build()
+ return doHttp(request)
+ }
+
+ private fun getBuilder(url: String, headers: Map?): Request.Builder {
+ val builder = Request.Builder()
+ builder.url(url)
+ if (null != headers) {
+ builder.headers(headers.toHeaders())
+ }
+ return builder
+ }
+}
diff --git a/src/main/kotlin/com/tencent/bk/devops/plugin/utils/ReflectUtil.kt b/src/main/kotlin/com/tencent/bk/devops/plugin/utils/ReflectUtil.kt
new file mode 100644
index 0000000..3ed8d32
--- /dev/null
+++ b/src/main/kotlin/com/tencent/bk/devops/plugin/utils/ReflectUtil.kt
@@ -0,0 +1,17 @@
+package com.tencent.bk.devops.plugin.utils
+
+/**
+ *
+ * @version 1.0
+ */
+object ReflectUtil {
+
+ fun isNativeType(bean: Any): Boolean {
+ return bean is Int ||
+ bean is Long ||
+ bean is Double ||
+ bean is Float ||
+ bean is Short ||
+ bean is Byte
+ }
+}
diff --git a/src/test/java/com/tencent/bk/devops/atom/utils/http/SdkUtilsTest.java b/src/test/java/com/tencent/bk/devops/atom/utils/http/SdkUtilsTest.java
deleted file mode 100644
index ae5e860..0000000
--- a/src/test/java/com/tencent/bk/devops/atom/utils/http/SdkUtilsTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package com.tencent.bk.devops.atom.utils.http;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class SdkUtilsTest {
-
- @Test
- public void getDataDir() {
- System.out.println(SdkUtils.getDataDir());
- }
-
- @Test
- public void trimProtocol() {
- String host = "www.tencent.com";
- Assert.assertEquals(host, SdkUtils.trimProtocol("http://www.tencent.com/"));
- Assert.assertEquals(host, SdkUtils.trimProtocol("http://www.tencent.com/dodi"));
- Assert.assertEquals(host, SdkUtils.trimProtocol("https://www.tencent.com/dodi"));
- Assert.assertEquals(host, SdkUtils.trimProtocol("https://www.tencent.com"));
- host = "www.ten-cent.com";
- Assert.assertEquals(host, SdkUtils.trimProtocol("https://www.ten-cent.com"));
- }
-
- @Test
- public void hasProtocol() {
- Assert.assertTrue(SdkUtils.hasProtocol("http://www.tencent.com/"));
- Assert.assertTrue(SdkUtils.hasProtocol("http://www.tencent.com/dodi"));
- Assert.assertTrue(SdkUtils.hasProtocol("https://www.tencent.com/dodi"));
- Assert.assertTrue(SdkUtils.hasProtocol("https://www.tencent.com"));
- Assert.assertTrue(SdkUtils.hasProtocol("https://www.ten-cent.com"));
- }
-}
\ No newline at end of file