This is an automated email from the ASF dual-hosted git repository.
jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git
The following commit(s) were added to refs/heads/master by this push:
new c59f01acc Fix bug with RestObject objects.
c59f01acc is described below
commit c59f01accec64b58b8441415dfd4a81a3e43d28d
Author: JamesBognar <[email protected]>
AuthorDate: Thu Jun 16 11:11:33 2022 -0400
Fix bug with RestObject objects.
---
.../java/org/apache/juneau/reflect/ClassInfo.java | 2 +-
.../logs/.gitignore | 1 +
.../juneau/examples/rest/RootContentTest.java | 2 +-
.../juneau-examples-rest-jetty/logs/.gitignore | 1 +
.../juneau-examples-rest-jetty/logs/empty.txt | 0
.../examples/rest/springboot/RootResources.java | 1 -
.../apache/juneau/examples/rest/RootResources.java | 1 -
.../juneau/examples/rest/UtilityBeansResource.java | 123 +++++++
.../org/apache/juneau/microservice/LogConfig.java | 211 ------------
.../apache/juneau/microservice/Microservice.java | 78 +----
.../microservice/resources/LogEntryFormatter.java | 272 ---------------
.../juneau/microservice/resources/LogParser.java | 234 -------------
.../microservice/resources/LogsResource.java | 373 ---------------------
.../microservice/resources/SampleRootResource.java | 2 +-
.../java/org/apache/juneau/rest/test/Root.java | 1 -
.../rest/test/client/ThirdPartyProxyResource.java | 1 +
.../microservice/jetty/JettyMicroservice.java | 6 -
.../microservice/jetty/template/RootResources.java | 2 -
.../springboot/template/RootResources.java | 3 +-
.../java/org/apache/juneau/rest/RestContext.java | 4 +-
pom.xml | 1 +
21 files changed, 134 insertions(+), 1185 deletions(-)
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
index eb33c0b13..ea7d195e6 100644
---
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
+++
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ClassInfo.java
@@ -120,7 +120,7 @@ public final class ClassInfo {
* @return The constructed class info, or <jk>null</jk> if the object
was <jk>null</jk>.
*/
public static ClassInfo of(Object o) {
- return of(o == null ? null : o.getClass());
+ return of(o == null ? null : o instanceof Class ? (Class<?>)o :
o.getClass());
}
/**
diff --git a/juneau-examples/juneau-examples-rest-jetty-ftest/logs/.gitignore
b/juneau-examples/juneau-examples-rest-jetty-ftest/logs/.gitignore
new file mode 100644
index 000000000..bd317cc13
--- /dev/null
+++ b/juneau-examples/juneau-examples-rest-jetty-ftest/logs/.gitignore
@@ -0,0 +1 @@
+/*log*
diff --git
a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RootContentTest.java
b/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RootContentTest.java
index 9dcd8764c..1383e0493 100644
---
a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RootContentTest.java
+++
b/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/RootContentTest.java
@@ -95,7 +95,7 @@ public class RootContentTest extends ContentComboTestBase {
},
{ /* 10 */
new ComboInput("HTML-content-octal/msgpack",
"/", MediaType.MSGPACK,
- "95 82 A4"
+ "94 82 A4"
)
},
{ /* 11 */
diff --git a/juneau-examples/juneau-examples-rest-jetty/logs/.gitignore
b/juneau-examples/juneau-examples-rest-jetty/logs/.gitignore
new file mode 100644
index 000000000..bd317cc13
--- /dev/null
+++ b/juneau-examples/juneau-examples-rest-jetty/logs/.gitignore
@@ -0,0 +1 @@
+/*log*
diff --git a/juneau-examples/juneau-examples-rest-jetty/logs/empty.txt
b/juneau-examples/juneau-examples-rest-jetty/logs/empty.txt
new file mode 100644
index 000000000..e69de29bb
diff --git
a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/RootResources.java
b/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/RootResources.java
index e560cf1d2..dc6f6bd2c 100644
---
a/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/RootResources.java
+++
b/juneau-examples/juneau-examples-rest-springboot/src/main/java/org/apache/juneau/examples/rest/springboot/RootResources.java
@@ -39,7 +39,6 @@ import org.apache.juneau.serializer.annotation.*;
HelloWorldResource.class,
DtoExamples.class,
ConfigResource.class,
- LogsResource.class,
ShutdownResource.class
}
)
diff --git
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
index bae630594..de6fb06c3 100644
---
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
+++
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RootResources.java
@@ -39,7 +39,6 @@ import org.apache.juneau.serializer.annotation.*;
HelloWorldResource.class,
DtoExamples.class,
ConfigResource.class,
- LogsResource.class,
ShutdownResource.class
}
)
diff --git
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UtilityBeansResource.java
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UtilityBeansResource.java
new file mode 100644
index 000000000..b958bd0eb
--- /dev/null
+++
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/UtilityBeansResource.java
@@ -0,0 +1,123 @@
+//
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
+// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
+// * with the License. You may obtain a copy of the License at
*
+// *
*
+// * http://www.apache.org/licenses/LICENSE-2.0
*
+// *
*
+// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
+// * specific language governing permissions and limitations under the
License. *
+//
***************************************************************************************************************************
+package org.apache.juneau.examples.rest;
+
+import java.util.*;
+
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.examples.parser.*;
+import org.apache.juneau.examples.serializer.*;
+import org.apache.juneau.html.annotation.*;
+import org.apache.juneau.http.annotation.*;
+import org.apache.juneau.http.response.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.beans.*;
+import org.apache.juneau.rest.config.*;
+import org.apache.juneau.rest.servlet.*;
+
+import java.awt.image.*;
+import java.net.*;
+
+/**
+ * Sample resource that allows images to be uploaded and retrieved.
+ *
+ * <ul class='seealso'>
+ * <li class='link'>{@doc jrs.Marshalling REST Marshalling}
+ * <li class='jc'>{@link ImageSerializer}
+ * <li class='jc'>{@link ImageParser}
+ * <li class='extlink'>{@source}
+ * </ul>
+ */
+@Rest(
+ path="/utilitybeans",
+ title="Utility beans examples",
+ description="Examples of utility bean usage."
+)
+@HtmlDocConfig(
+ navlinks="options: ?method=OPTIONS"
+)
+public class UtilityBeansResource extends BasicRestServlet implements
BasicUniversalConfig {
+
+ private static final long serialVersionUID = 1L;
+
+ @RestGet("/")
+ public ResourceDescriptions getDescriptions() {
+ return ResourceDescriptions
+ .create()
+ .append("BeanDescription", "Example of BeanDescription
bean");
+ }
+
+
+ @RestGet("/BeanDescription")
+ public BeanDescription aBeanDescription() {
+ return BeanDescription.of(AddressBook.class);
+ }
+
+ public static class AddressBook extends LinkedList<Person> {
+
+ public AddressBook init() {
+ add(
+ new Person("Bill Clinton", 65,
+ new Address("55W. 125th Street", "New
York", "NY", 10027, true)
+ )
+ );
+ return this;
+ }
+ }
+
+ @Bean(p="street,city,state,zip,isCurrent")
+ public static class Address {
+ public String street;
+ public String city;
+ public String state;
+ public int zip;
+ public boolean isCurrent;
+
+ public Address() {}
+
+ public Address(String street, String city, String state, int
zip, boolean isCurrent) {
+ this.street = street;
+ this.city = city;
+ this.state = state;
+ this.zip = zip;
+ this.isCurrent = isCurrent;
+ }
+ @Override /* Object */
+ public String toString() {
+ return
"Address(street="+street+",city="+city+",state="+state+",zip="+zip+",isCurrent="+isCurrent+")";
+ }
+ }
+
+ @Bean(typeName="Person",p="name,age,addresses")
+ public static class Person {
+ public String name;
+ public int age;
+ public Address[] addresses;
+
+ public Person() {}
+
+ public Person(String name, int age, Address...addresses) {
+ this.name = name;
+ this.age = age;
+ this.addresses = addresses;
+ }
+
+ @Override /* Object */
+ public String toString() {
+ return "Person(name="+name+",age="+age+")";
+ }
+ }
+
+
+
+}
\ No newline at end of file
diff --git
a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/LogConfig.java
b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/LogConfig.java
deleted file mode 100644
index 5221f8b85..000000000
---
a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/LogConfig.java
+++ /dev/null
@@ -1,211 +0,0 @@
-//
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
-// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
-// * with the License. You may obtain a copy of the License at
*
-// *
*
-// * http://www.apache.org/licenses/LICENSE-2.0
*
-// *
*
-// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
-// * specific language governing permissions and limitations under the
License. *
-//
***************************************************************************************************************************
-package org.apache.juneau.microservice;
-
-import static org.apache.juneau.internal.CollectionUtils.*;
-
-import java.util.*;
-import java.util.logging.*;
-import java.util.logging.Formatter;
-
-import org.apache.juneau.microservice.resources.*;
-
-/**
- * Can be used for configuration of simple logging in the microservice.
- *
- * <p>
- * Instances of this class can be created using {@link #create()} and passing
the result to
- * {@link Microservice.Builder#logConfig(LogConfig)}.
- *
- * <p>
- * These values override values specified in the <js>"Logging"</js>
configuration section.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-microservice-core}
- * <li class='extlink'>{@source}
- * </ul>
- */
-public class LogConfig {
-
- String logFile, logDir;
- Boolean append;
- Integer limit, count;
- Level fileLevel, consoleLevel;
- Map<String,Level> levels = map();
- Formatter formatter;
-
- LogConfig() {}
-
- /**
- * Copy constructor.
- *
- * @param copyFrom The log config to copy from.
- */
- protected LogConfig(LogConfig copyFrom) {
- this.logFile = copyFrom.logFile;
- this.logDir = copyFrom.logDir;
- this.append = copyFrom.append;
- this.limit = copyFrom.limit;
- this.count = copyFrom.count;
- this.fileLevel = copyFrom.fileLevel;
- this.consoleLevel = copyFrom.consoleLevel;
- this.levels = copyOf(copyFrom.levels);
- this.formatter = copyFrom.formatter;
- }
-
- /**
- * Creates a copy of this log configuration.
- *
- * @return A new copy of this log configuration.
- */
- public LogConfig copy() {
- return new LogConfig(this);
- }
-
- /**
- * Creates a new instance of this config.
- *
- * @return A new instance of this config.
- */
- public static LogConfig create() {
- return new LogConfig();
- }
-
- /**
- * Returns the name of the log file on the file system to store the log
file for this microservice.
- *
- * <p>
- * This overrides the configuration value <js>"Logging/logFile"</js>.
- * If not specified, no file system logging will be used.
- *
- * @param logFile The log file.
- * @return This object.
- */
- public LogConfig logFile(String logFile) {
- this.logFile = logFile;
- return this;
- }
-
- /**
- * The location of the log directory to create the log file.
- *
- * <p>
- * This overrides the configuration value <js>"Logging/logDir"</js>.
- * If not specified, uses the JVM working directory.
- *
- * @param logDir The log directory location as a path relative to the
working directory.
- * @return This object.
- */
- public LogConfig logDir(String logDir) {
- this.logDir = logDir;
- return this;
- }
-
- /**
- * The log entry formatter.
- *
- * <p>
- * If not specified, uses the following values pulled from the
configuration to construct a {@link LogEntryFormatter}:
- * <ul>
- * <li><js><js>"Logging/format"</js> (default is <js>"[{date}
{level}] {msg}%n"</js>)
- * <li><js><js>"Logging/dateFormat"</js> (default is
<js>"yyyy.MM.dd hh:mm:ss"</js>)
- * <li><js><js>"Logging/useStackTraceHashes"</js> (default is
<jk>false</jk>)
- * </ul>
- *
- *
- * @param formatter The log entry formatter.
- * @return This object.
- * @see LogEntryFormatter
- */
- public LogConfig formatter(Formatter formatter) {
- this.formatter = formatter;
- return this;
- }
-
- /**
- * Specified append mode for the log file.
- *
- * @return This object.
- */
- public LogConfig append() {
- this.append = true;
- return this;
- }
-
- /**
- * The maximum number of bytes to write to any one log file.
- *
- * @param limit The number of bytes.
- * @return This object.
- */
- public LogConfig limit(int limit) {
- this.limit = limit;
- return this;
- }
-
- /**
- * The number of log files to use.
- *
- * @param count The number of log files.
- * @return This object.
- */
- public LogConfig count(int count) {
- this.count = count;
- return this;
- }
-
- /**
- * The default logging level for the log file.
- *
- * @param fileLevel The logging level.
- * @return This object.
- */
- public LogConfig fileLevel(Level fileLevel) {
- this.fileLevel = fileLevel;
- return this;
- }
-
- /**
- * The default logging level for the console.
- *
- * @param consoleLevel The logging level.
- * @return This object.
- */
- public LogConfig consoleLevel(Level consoleLevel) {
- this.consoleLevel = consoleLevel;
- return this;
- }
-
- /**
- * Default logging levels for loggers.
- *
- * @param levels A map of logger names to logger levels.
- * @return This object.
- */
- public LogConfig levels(Map<String,Level> levels) {
- this.levels.putAll(levels);
- return this;
- }
-
- /**
- * Default logging level for logger.
- *
- * @param logger Logger name.
- * @param level Logger level.
- * @return This object.
- */
- public LogConfig level(String logger, Level level) {
- this.levels.put(logger, level);
- return this;
- }
-}
diff --git
a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/Microservice.java
b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/Microservice.java
index 74ac9489c..7f12f0b61 100755
---
a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/Microservice.java
+++
b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/Microservice.java
@@ -14,9 +14,7 @@ package org.apache.juneau.microservice;
import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.CollectionUtils.*;
-import static org.apache.juneau.internal.FileUtils.*;
import static org.apache.juneau.internal.IOUtils.*;
-import static org.apache.juneau.internal.ObjectUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.internal.ThrowableUtils.*;
@@ -28,7 +26,6 @@ import java.util.*;
import java.util.concurrent.*;
import java.util.jar.*;
import java.util.logging.*;
-import java.util.logging.Formatter;
import org.apache.juneau.*;
import org.apache.juneau.collections.*;
@@ -40,7 +37,6 @@ import org.apache.juneau.config.vars.*;
import org.apache.juneau.cp.*;
import org.apache.juneau.internal.*;
import org.apache.juneau.microservice.console.*;
-import org.apache.juneau.microservice.resources.*;
import org.apache.juneau.parser.ParseException;
import org.apache.juneau.svl.*;
import org.apache.juneau.svl.vars.*;
@@ -145,7 +141,6 @@ public class Microservice implements ConfigEventListener {
Args args;
ManifestFile manifest;
Logger logger;
- LogConfig logConfig;
Config config;
String configName;
ConfigStore configStore;
@@ -173,7 +168,6 @@ public class Microservice implements ConfigEventListener {
this.manifest = copyFrom.manifest;
this.logger = copyFrom.logger;
this.configName = copyFrom.configName;
- this.logConfig = copyFrom.logConfig == null ? null :
copyFrom.logConfig.copy();
this.consoleEnabled = copyFrom.consoleEnabled;
this.configBuilder = copyFrom.configBuilder;
this.varResolver = copyFrom.varResolver;
@@ -290,9 +284,6 @@ public class Microservice implements ConfigEventListener {
/**
* Specifies the logger used by the microservice and returned
by the {@link Microservice#getLogger()} method.
*
- * <p>
- * Calling this method overrides the default logging mechanism
controlled by the {@link #logConfig(LogConfig)} method.
- *
* @param logger The logger to use for logging microservice
messages.
* @return This object.
*/
@@ -301,23 +292,6 @@ public class Microservice implements ConfigEventListener {
return this;
}
- /**
- * Specifies logging instructions for the microservice.
- *
- * <p>
- * If not specified, the values are taken from the
<js>"Logging"</js> section of the configuration.
- *
- * <p>
- * This method is ignored if {@link #logger(Logger)} is used to
set the microservice logger.
- *
- * @param logConfig The log configuration.
- * @return This object.
- */
- public Builder logConfig(LogConfig logConfig) {
- this.logConfig = logConfig;
- return this;
- }
-
/**
* Specifies the config for initializing this microservice.
*
@@ -549,7 +523,6 @@ public class Microservice implements ConfigEventListener {
final Messages messages = Messages.of(Microservice.class);
- private final Builder builder;
private final Args args;
private final Config config;
private final ManifestFile manifest;
@@ -563,7 +536,7 @@ public class Microservice implements ConfigEventListener {
final File workingDir;
private final String configName;
- private volatile Logger logger;
+ private volatile Logger logger = Logger.getGlobal();
/**
* Constructor.
@@ -572,10 +545,8 @@ public class Microservice implements ConfigEventListener {
* @throws IOException Problem occurred reading file.
* @throws ParseException Malformed input encountered.
*/
- @SuppressWarnings("resource")
protected Microservice(Builder builder) throws IOException,
ParseException {
setInstance(this);
- this.builder = builder.copy();
this.workingDir = builder.workingDir;
this.configName = builder.configName;
@@ -764,53 +735,6 @@ public class Microservice implements ConfigEventListener {
for (String key : spKeys)
System.setProperty(key,
config.get("SystemProperties/"+key).orElse(null));
- //
--------------------------------------------------------------------------------
- // Initialize logging.
- //
--------------------------------------------------------------------------------
- this.logger = builder.logger;
- LogConfig logConfig = builder.logConfig != null ?
builder.logConfig : new LogConfig();
- if (this.logger == null) {
- LogManager.getLogManager().reset();
- this.logger = Logger.getLogger("");
- String logFile = firstNonNull(logConfig.logFile,
config.get("Logging/logFile").orElse(null));
-
- if (isNotEmpty(logFile)) {
- String logDir = firstNonNull(logConfig.logDir,
config.get("Logging/logDir").orElse("."));
- File logDirFile = resolveFile(logDir);
- mkdirs(logDirFile, false);
- logDir = logDirFile.getAbsolutePath();
- System.setProperty("juneau.logDir", logDir);
-
- boolean append = firstNonNull(logConfig.append,
config.get("Logging/append").asBoolean().orElse(false));
- int limit = firstNonNull(logConfig.limit,
config.get("Logging/limit").asInteger().orElse(1024*1024));
- int count = firstNonNull(logConfig.count,
config.get("Logging/count").asInteger().orElse(1));
-
- FileHandler fh = new FileHandler(logDir + '/' +
logFile, limit, count, append);
-
- Formatter f = logConfig.formatter;
- if (f == null) {
- String format =
config.get("Logging/format").orElse("[{date} {level}] {msg}%n");
- String dateFormat =
config.get("Logging/dateFormat").orElse("yyyy.MM.dd hh:mm:ss");
- boolean useStackTraceHashes =
config.get("Logging/useStackTraceHashes").asBoolean().orElse(false);
- f = new LogEntryFormatter(format,
dateFormat, useStackTraceHashes);
- }
- fh.setFormatter(f);
- fh.setLevel(firstNonNull(logConfig.fileLevel,
config.get("Logging/fileLevel").as(Level.class).orElse(Level.INFO)));
- logger.addHandler(fh);
-
- ConsoleHandler ch = new ConsoleHandler();
-
ch.setLevel(firstNonNull(logConfig.consoleLevel,
config.get("Logging/consoleLevel").as(Level.class).orElse(Level.WARNING)));
- ch.setFormatter(f);
- logger.addHandler(ch);
- }
- }
-
- JsonMap loggerLevels =
config.get("Logging/levels").as(JsonMap.class).orElseGet(JsonMap::new);
- for (String l : loggerLevels.keySet())
- Logger.getLogger(l).setLevel(loggerLevels.get(l,
Level.class));
- for (String l : logConfig.levels.keySet())
- Logger.getLogger(l).setLevel(logConfig.levels.get(l));
-
return this;
}
diff --git
a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogEntryFormatter.java
b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogEntryFormatter.java
deleted file mode 100644
index 5b8d915b0..000000000
---
a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogEntryFormatter.java
+++ /dev/null
@@ -1,272 +0,0 @@
-//
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
-// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
-// * with the License. You may obtain a copy of the License at
*
-// *
*
-// * http://www.apache.org/licenses/LICENSE-2.0
*
-// *
*
-// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
-// * specific language governing permissions and limitations under the
License. *
-//
***************************************************************************************************************************
-package org.apache.juneau.microservice.resources;
-
-import static org.apache.juneau.internal.CollectionUtils.*;
-import static org.apache.juneau.internal.ThrowableUtils.*;
-
-import java.text.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.*;
-import java.util.logging.*;
-import java.util.logging.Formatter;
-import java.util.regex.*;
-
-/**
- * Log entry formatter.
- *
- * <p>
- * Uses three simple parameter for configuring log entry formats:
- * <ul class='spaced-list'>
- * <li>
- * <c>dateFormat</c> - A {@link SimpleDateFormat} string
describing the format for dates.
- * <li>
- * <c>format</c> - A string with <c>{...}</c> replacement
variables representing predefined fields.
- * <li>
- * <c>useStackTraceHashes</c> - A setting that causes duplicate
stack traces to be replaced with 8-character
- * hash strings.
- * </ul>
- *
- * <p>
- * This class converts the format strings into a regular expression that can
be used to parse the resulting log file.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-microservice-core}
- * <li class='extlink'>{@source}
- * </ul>
- */
-public class LogEntryFormatter extends Formatter {
-
- private ConcurrentHashMap<String,AtomicInteger> hashes;
- private DateFormat df;
- private String format;
- private Pattern rePattern;
- private Map<String,Integer> fieldIndexes;
-
- /**
- * Create a new formatter.
- *
- * @param format
- * The log entry format. e.g. <js>"[{date} {level}] {msg}%n"</js>
- * The string can contain any of the following variables:
- * <ol>
- * <li><js>"{date}"</js> - The date, formatted per
<js>"Logging/dateFormat"</js>.
- * <li><js>"{class}"</js> - The class name.
- * <li><js>"{method}"</js> - The method name.
- * <li><js>"{logger}"</js> - The logger name.
- * <li><js>"{level}"</js> - The log level name.
- * <li><js>"{msg}"</js> - The log message.
- * <li><js>"{threadid}"</js> - The thread ID.
- * <li><js>"{exception}"</js> - The localized exception
message.
- * </ol>
- * @param dateFormat
- * The {@link SimpleDateFormat} format to use for dates. e.g.
<js>"yyyy.MM.dd hh:mm:ss"</js>.
- * @param useStackTraceHashes
- * If <jk>true</jk>, only print unique stack traces once and then
refer to them by a simple 8 character hash
- * identifier.
- */
- public LogEntryFormatter(String format, String dateFormat, boolean
useStackTraceHashes) {
- this.df = new SimpleDateFormat(dateFormat);
- if (useStackTraceHashes)
- hashes = new ConcurrentHashMap<>();
-
- fieldIndexes = new HashMap<>();
-
- format = format
- .replaceAll("\\{date\\}", "%1\\$s")
- .replaceAll("\\{class\\}", "%2\\$s")
- .replaceAll("\\{method\\}", "%3\\$s")
- .replaceAll("\\{logger\\}", "%4\\$s")
- .replaceAll("\\{level\\}", "%5\\$s")
- .replaceAll("\\{msg\\}", "%6\\$s")
- .replaceAll("\\{threadid\\}", "%7\\$s")
- .replaceAll("\\{exception\\}", "%8\\$s");
-
- this.format = format;
-
- // Construct a regular expression to match this log entry.
- int index = 1;
- StringBuilder re = new StringBuilder();
- int S1 = 1; // Looking for %
- int S2 = 2; // Found %, looking for number.
- int S3 = 3; // Found number, looking for $.
- int S4 = 4; // Found $, looking for s.
- int state = 1;
- int i1 = 0;
- for (int i = 0; i < format.length(); i++) {
- char c = format.charAt(i);
- if (state == S1) {
- if (c == '%')
- state = S2;
- else {
- if (! (Character.isLetterOrDigit(c) ||
Character.isWhitespace(c)))
- re.append('\\');
- re.append(c);
- }
- } else if (state == S2) {
- if (Character.isDigit(c)) {
- i1 = i;
- state = S3;
- } else {
- re.append("\\%").append(c);
- state = S1;
- }
- } else if (state == S3) {
- if (c == '$') {
- state = S4;
- } else {
-
re.append("\\%").append(format.substring(i1, i));
- state = S1;
- }
- } else if (state == S4) {
- if (c == 's') {
- int group =
Integer.parseInt(format.substring(i1, i-1));
- switch (group) {
- case 1:
-
fieldIndexes.put("date", index++);
- re.append("(" +
dateFormat.replaceAll("[mHhsSdMy]", "\\\\d").replaceAll("\\.", "\\\\.") + ")");
- break;
- case 2:
-
fieldIndexes.put("class", index++);
-
re.append("([\\p{javaJavaIdentifierPart}\\.]+)");
- break;
- case 3:
-
fieldIndexes.put("method", index++);
-
re.append("([\\p{javaJavaIdentifierPart}\\.]+)");
- break;
- case 4:
-
fieldIndexes.put("logger", index++);
-
re.append("([\\w\\d\\.\\_]+)");
- break;
- case 5:
-
fieldIndexes.put("level", index++);
-
re.append("(SEVERE|WARNING|INFO|CONFIG|FINE|FINER|FINEST)");
- break;
- case 6:
- fieldIndexes.put("msg",
index++);
- re.append("(.*)");
- break;
- case 7:
-
fieldIndexes.put("threadid", index++);
- re.append("(\\\\d+)");
- break;
- case 8:
-
fieldIndexes.put("exception", index++);
- re.append("(.*)");
- break;
- default: // Fall through.
- }
- } else {
-
re.append("\\%").append(format.substring(i1, i));
- }
- state = S1;
- }
- }
-
- // The log parser
- String sre = re.toString();
- if (sre.endsWith("\\%n"))
- sre = sre.substring(0, sre.length()-3);
-
- // Replace instances of %n.
- sre = sre.replaceAll("\\\\%n", "\\\\n");
-
- rePattern = Pattern.compile(sre);
- fieldIndexes = unmodifiable(fieldIndexes);
- }
-
- /**
- * Returns the regular expression pattern used for matching log entries.
- *
- * @return The regular expression pattern used for matching log entries.
- */
- public Pattern getLogEntryPattern() {
- return rePattern;
- }
-
- /**
- * Returns the {@link DateFormat} used for matching dates.
- *
- * @return The {@link DateFormat} used for matching dates.
- */
- public DateFormat getDateFormat() {
- return df;
- }
-
- /**
- * Given a matcher that has matched the pattern specified by {@link
#getLogEntryPattern()}, returns the field value
- * from the match.
- *
- * @param fieldName
- * The field name.
- * Possible values are:
- * <ul>
- * <li><js>"date"</js>
- * <li><js>"class"</js>
- * <li><js>"method"</js>
- * <li><js>"logger"</js>
- * <li><js>"level"</js>
- * <li><js>"msg"</js>
- * <li><js>"threadid"</js>
- * <li><js>"exception"</js>
- * </ul>
- * @param m The matcher.
- * @return The field value, or <jk>null</jk> if the specified field
does not exist.
- */
- public String getField(String fieldName, Matcher m) {
- Integer i = fieldIndexes.get(fieldName);
- return (i == null ? null : m.group(i));
- }
-
- @Override /* Formatter */
- public String format(LogRecord r) {
- String msg = formatMessage(r);
- Throwable t = r.getThrown();
- String hash = null;
- int c = 0;
- if (hashes != null && t != null) {
- hash = hashCode(t);
- hashes.putIfAbsent(hash, new AtomicInteger(0));
- c = hashes.get(hash).incrementAndGet();
- if (c <= 5) {
- msg = '[' + hash + '.' + c + "] " + msg;
- } else {
- msg = '[' + hash + '.' + c + "] " + msg + ", "
+ t.getLocalizedMessage();
- t = null;
- }
- }
- String s = String.format(format,
- df.format(new Date(r.getMillis())),
- r.getSourceClassName(),
- r.getSourceMethodName(),
- r.getLoggerName(),
- r.getLevel(),
- msg,
- r.getThreadID(),
- r.getThrown() == null ? "" :
r.getThrown().getMessage());
- if (t != null)
- s += String.format("%s", getStackTrace(r.getThrown()));
- return s;
- }
-
- private static String hashCode(Throwable t) {
- int i = 0;
- while (t != null) {
- for (StackTraceElement e : t.getStackTrace())
- i ^= e.hashCode();
- t = t.getCause();
- }
- return Integer.toHexString(i);
- }
-}
diff --git
a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogParser.java
b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogParser.java
deleted file mode 100644
index 7e1b310e8..000000000
---
a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogParser.java
+++ /dev/null
@@ -1,234 +0,0 @@
-//
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
-// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
-// * with the License. You may obtain a copy of the License at
*
-// *
*
-// * http://www.apache.org/licenses/LICENSE-2.0
*
-// *
*
-// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
-// * specific language governing permissions and limitations under the
License. *
-//
***************************************************************************************************************************
-package org.apache.juneau.microservice.resources;
-
-import static org.apache.juneau.internal.CollectionUtils.*;
-import static org.apache.juneau.internal.ThrowableUtils.*;
-
-import java.io.*;
-import java.nio.charset.*;
-import java.text.*;
-import java.util.*;
-import java.util.regex.*;
-
-/**
- * Utility class for reading log files.
- *
- * <p>
- * Provides the capability of returning splices of log files based on dates
and filtering based on thread and logger
- * names.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-microservice-core}
- * <li class='extlink'>{@source}
- * </ul>
- */
-public final class LogParser implements Iterable<LogParser.Entry>,
Iterator<LogParser.Entry>, Closeable {
- private BufferedReader br;
- LogEntryFormatter formatter;
- Date start, end;
- Set<String> loggerFilter, severityFilter;
- String threadFilter;
- private Entry next;
-
- /**
- * Constructor.
- *
- * @param formatter The log entry formatter.
- * @param f The log file.
- * @param start Don't return rows before this date. If <jk>null</jk>,
start from the beginning of the file.
- * @param end Don't return rows after this date. If <jk>null</jk>, go
to the end of the file.
- * @param thread Only return log entries with this thread name.
- * @param loggers Only return log entries produced by these loggers
(simple class names).
- * @param severity Only return log entries with the specified severity.
- * @throws IOException Thrown by underlying stream.
- */
- public LogParser(LogEntryFormatter formatter, File f, Date start, Date
end, String thread, String[] loggers, String[] severity) throws IOException {
- br = new BufferedReader(new InputStreamReader(new
FileInputStream(f), Charset.defaultCharset()));
- this.formatter = formatter;
- this.start = start;
- this.end = end;
- this.threadFilter = thread;
- if (loggers != null)
- this.loggerFilter = set(loggers);
- if (severity != null)
- this.severityFilter = set(severity);
-
- // Find the first line.
- String line;
- while (next == null && (line = br.readLine()) != null) {
- Entry e = new Entry(line);
- if (e.matches())
- next = e;
- }
- }
-
- @Override /* Iterator */
- public boolean hasNext() {
- return next != null;
- }
-
- @Override /* Iterator */
- public Entry next() {
- Entry current = next;
- Entry prev = next;
- try {
- next = null;
- String line = null;
- while (next == null && (line = br.readLine()) != null) {
- Entry e = new Entry(line);
- if (e.isRecord) {
- if (e.matches())
- next = e;
- prev = null;
- } else {
- if (prev != null)
- prev.addText(e.line);
- }
- }
- } catch (IOException e) {
- throw runtimeException(e);
- }
- return current;
- }
-
- @Override /* Iterator */
- public void remove() {
- throw new NoSuchMethodError();
- }
-
- @Override /* Iterable */
- public Iterator<Entry> iterator() {
- return this;
- }
-
- @Override /* Closeable */
- public void close() throws IOException {
- br.close();
- }
-
- /**
- * Serializes the contents of the parsed log file to the specified
writer and then closes the underlying reader.
- *
- * @param w The writer to write the log file to.
- * @throws IOException Thrown by underlying stream.
- */
- public void writeTo(Writer w) throws IOException {
- try {
- if (! hasNext())
- w.append("[EMPTY]");
- else {
- forEach(le -> safeRun(()->le.append(w)));
- }
- } finally {
- close();
- }
- }
-
- /**
- * Represents a single line from the log file.
- */
- @SuppressWarnings("javadoc")
- public final class Entry {
- public Date date;
- public String severity, logger;
- protected String line, text;
- protected String thread;
- protected List<String> additionalText;
- protected boolean isRecord;
-
- Entry(String line) throws IOException {
- try {
- this.line = line;
- Matcher m =
formatter.getLogEntryPattern().matcher(line);
- if (m.matches()) {
- isRecord = true;
- String s = formatter.getField("date",
m);
- if (s != null)
- date =
formatter.getDateFormat().parse(s);
- thread = formatter.getField("thread",
m);
- severity = formatter.getField("level",
m);
- logger = formatter.getField("logger",
m);
- text = formatter.getField("msg", m);
- if (logger != null &&
logger.indexOf('.') > -1)
- logger =
logger.substring(logger.lastIndexOf('.')+1);
- }
- } catch (ParseException e) {
- throw ioException(e);
- }
- }
-
- void addText(String t) {
- if (additionalText == null)
- additionalText = new LinkedList<>();
- additionalText.add(t);
- }
-
- public String getText() {
- if (additionalText == null)
- return text;
- if (text == null)
- return "";
- int i = text.length();
- for (String s : additionalText)
- i += s.length() + 1;
- StringBuilder sb = new StringBuilder(i);
- sb.append(text);
- additionalText.forEach(s -> sb.append('\n').append(s));
- return sb.toString();
- }
-
- public String getThread() {
- return thread;
- }
-
- public Writer appendHtml(Writer w) throws IOException {
- w.append(toHtml(line)).append("<br>");
- if (additionalText != null)
- for (String t : additionalText)
- w.append(toHtml(t)).append("<br>");
- return w;
- }
-
- protected Writer append(Writer w) throws IOException {
- w.append(line).append('\n');
- if (additionalText != null)
- for (String t : additionalText)
- w.append(t).append('\n');
- return w;
- }
-
- boolean matches() {
- if (! isRecord)
- return false;
- if (start != null && date.before(start))
- return false;
- if (end != null && date.after(end))
- return false;
- if (threadFilter != null && !
threadFilter.equals(thread))
- return false;
- if (loggerFilter != null && !
loggerFilter.contains(logger))
- return false;
- if (severityFilter != null && !
severityFilter.contains(severity))
- return false;
- return true;
- }
- }
-
- static final String toHtml(String s) {
- if (s.indexOf('<') != -1)
- return s.replaceAll("<", "<");//$NON-NLS-2$
- return s;
- }
-}
-
diff --git
a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
deleted file mode 100755
index fb1da1227..000000000
---
a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/LogsResource.java
+++ /dev/null
@@ -1,373 +0,0 @@
-//
***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file *
-// * distributed with this work for additional information regarding copyright
ownership. The ASF licenses this file *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not
use this file except in compliance *
-// * with the License. You may obtain a copy of the License at
*
-// *
*
-// * http://www.apache.org/licenses/LICENSE-2.0
*
-// *
*
-// * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
express or implied. See the License for the *
-// * specific language governing permissions and limitations under the
License. *
-//
***************************************************************************************************************************
-package org.apache.juneau.microservice.resources;
-
-import static org.apache.juneau.internal.CollectionUtils.*;
-import static org.apache.juneau.internal.StringUtils.*;
-
-import java.io.*;
-import java.nio.charset.*;
-import java.util.*;
-
-import org.apache.juneau.annotation.*;
-import org.apache.juneau.config.*;
-import org.apache.juneau.dto.*;
-import org.apache.juneau.html.annotation.*;
-import org.apache.juneau.http.annotation.*;
-import org.apache.juneau.http.response.*;
-import org.apache.juneau.rest.*;
-import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.beans.*;
-import org.apache.juneau.rest.config.*;
-import org.apache.juneau.rest.converter.*;
-import org.apache.juneau.rest.servlet.*;
-
-/**
- * REST resource for viewing and accessing log files.
- *
- * <ul class='seealso'>
- * <li class='link'>{@doc juneau-microservice-core}
- * <li class='extlink'>{@source}
- * </ul>
- *
- * @serial exclude
- */
-@Rest(
- path="/logs",
- title="Log files",
- description="Log files from this service",
- allowedMethodParams="*"
-)
-@HtmlConfig(uriAnchorText="PROPERTY_NAME")
-@SuppressWarnings("javadoc")
-public class LogsResource extends BasicRestServlet implements
BasicUniversalConfig {
- private static final long serialVersionUID = 1L;
-
-
//-------------------------------------------------------------------------------------------------------------------
- // Configurable properties
-
//-------------------------------------------------------------------------------------------------------------------
-
- private static final String PREFIX = "LogsResource.";
-
- /**
- * Root directory.
- */
- public static final String LOGS_RESOURCE_logDir = PREFIX + "logDir.s";
-
- /**
- * Allow deletes on files.
- */
- public static final String LOGS_RESOURCE_allowDeletes = PREFIX +
"allowDeletes.b";
-
- /**
- * Log entry format.
- */
- public static final String LOGS_RESOURCE_logFormat = PREFIX +
"logFormat.s";
-
- /**
- * Log entry format.
- */
- public static final String LOGS_RESOURCE_dateFormat = PREFIX +
"dateFormat.s";
-
- /**
- * Log entry format.
- */
- public static final String LOGS_RESOURCE_useStackTraceHashes = PREFIX +
"useStackTraceHashes.b";
-
-
//-------------------------------------------------------------------------------------------------------------------
- // Instance
-
//-------------------------------------------------------------------------------------------------------------------
-
- private final File logDir;
- private final LogEntryFormatter leFormatter;
- final boolean allowDeletes;
-
- public LogsResource(Config c) {
- logDir = new File(c.get(LOGS_RESOURCE_logDir).orElse("logDir"));
- allowDeletes =
c.get(LOGS_RESOURCE_allowDeletes).asBoolean().orElse(true);
- leFormatter = new LogEntryFormatter(
- c.get(LOGS_RESOURCE_logFormat).orElse("[{date} {level}]
{msg}%n"),
- c.get(LOGS_RESOURCE_dateFormat).orElse("yyyy.MM.dd
hh:mm:ss"),
-
c.get(LOGS_RESOURCE_useStackTraceHashes).asBoolean().orElse(true)
- );
- }
-
- @RestGet(
- path="/*",
- summary="View information on file or directory",
- description="Returns information about the specified file or
directory."
- )
- @HtmlDocConfig(
- nav={"<h5>Folder: $RA{fullPath}</h5>"}
- )
- public FileResource getFile(RestRequest req, @Path("/*") String path)
throws NotFound, Exception {
-
- File dir = getFile(path);
- req.setAttribute("fullPath", dir.getAbsolutePath());
-
- return new FileResource(dir, path, allowDeletes, true);
- }
-
- @RestOp(
- method="VIEW",
- path="/*",
- summary="View contents of log file",
- description="View the contents of a log file."
- )
- public void viewFile(
- RestResponse res,
- @Path("/*") String path,
- @Query("highlight") @Schema(d="Add severity color
highlighting.") boolean highlight,
- @Query("start") @Schema(d="Start timestamp (ISO8601,
full or partial).\nDon't print lines logged before the specified
timestamp.\nUse any of the following formats: yyyy, yyyy-MM, yyyy-MM-dd,
yyyy-MM-ddThh, yyyy-MM-ddThh:mm, yyyy-MM-ddThh:mm:ss, yyyy-MM-ddThh:mm:ss.SSS")
String start,
- @Query("end") @Schema(d="End timestamp (ISO8601, full
or partial).\nDon't print lines logged after the specified timestamp.\nUse any
of the following formats: yyyy, yyyy-MM, yyyy-MM-dd, yyyy-MM-ddThh,
yyyy-MM-ddThh:mm, yyyy-MM-ddThh:mm:ss, yyyy-MM-ddThh:mm:ss.SSS") String end,
- @Query("thread") @Schema(d="Thread name filter.\nOnly
show log entries with the specified thread name.") String thread,
- @Query("loggers") @Schema(d="Logger filter (simple
class name).\nOnly show log entries if they were produced by one of the
specified loggers.") String[] loggers,
- @Query("severity") @Schema(d="Severity filter.\nOnly
show log entries with the specified severity.") String[] severity
- ) throws NotFound, MethodNotAllowed, IOException {
-
- File f = getFile(path);
-
- Date startDate = parseIsoDate(start), endDate =
parseIsoDate(end);
-
- if (! highlight) {
- Object o = getReader(f, startDate, endDate, thread,
loggers, severity);
- res.setContentType("text/plain");
- if (o instanceof Reader)
- res.setContent(o);
- else {
- try (LogParser p = (LogParser)o; Writer w =
res.getNegotiatedWriter()) {
- p.writeTo(w);
- }
- }
- return;
- }
-
- res.setContentType("text/html");
- try (PrintWriter w = res.getNegotiatedWriter()) {
- w.println("<html><body
style='font-family:monospace;font-size:8pt;white-space:pre;'>");
- try (LogParser lp = getLogParser(f, startDate, endDate,
thread, loggers, severity)) {
- if (! lp.hasNext())
- w.append("<span
style='color:gray'>[EMPTY]</span>");
- else for (LogParser.Entry le : lp) {
- char s = le.severity.charAt(0);
- String color = "black";
-
//SEVERE|WARNING|INFO|CONFIG|FINE|FINER|FINEST
- if (s == 'I')
- color = "#006400";
- else if (s == 'W')
- color = "#CC8400";
- else if (s == 'E' || s == 'S')
- color = "#DD0000";
- else if (s == 'D' || s == 'F' || s ==
'T')
- color = "#000064";
- w.append("<span
style='color:").append(color).append("'>");
- le.appendHtml(w).append("</span>");
- }
- w.append("</body></html>");
- }
- }
- }
-
- @RestOp(
- method="PARSE",
- path="/*",
- converters=Queryable.class,
- summary="View parsed contents of file",
- description="View the parsed contents of a file.",
- swagger=@OpSwagger(
- parameters={
- Queryable.SWAGGER_PARAMS
- }
- )
- )
- @HtmlDocConfig(
- nav={"<h5>Folder: $RA{fullPath}</h5>"}
- )
- public LogParser viewParsedEntries(
- RestRequest req,
- @Path("/*") String path,
- @Query("start") @Schema(d="Start timestamp (ISO8601,
full or partial).\nDon't print lines logged before the specified
timestamp.\nUse any of the following formats: yyyy, yyyy-MM, yyyy-MM-dd,
yyyy-MM-ddThh, yyyy-MM-ddThh:mm, yyyy-MM-ddThh:mm:ss, yyyy-MM-ddThh:mm:ss.SSS")
String start,
- @Query("end") @Schema(d="End timestamp (ISO8601, full
or partial).\nDon't print lines logged after the specified timestamp.\nUse any
of the following formats: yyyy, yyyy-MM, yyyy-MM-dd, yyyy-MM-ddThh,
yyyy-MM-ddThh:mm, yyyy-MM-ddThh:mm:ss, yyyy-MM-ddThh:mm:ss.SSS") String end,
- @Query("thread") @Schema(d="Thread name filter.\nOnly
show log entries with the specified thread name.") String thread,
- @Query("loggers") @Schema(d="Logger filter (simple
class name).\nOnly show log entries if they were produced by one of the
specified loggers.") String[] loggers,
- @Query("severity") @Schema(d="Severity filter.\nOnly
show log entries with the specified severity.") String[] severity
- ) throws NotFound, IOException {
-
- File f = getFile(path);
- req.setAttribute("fullPath", f.getAbsolutePath());
-
- Date startDate = parseIsoDate(start), endDate =
parseIsoDate(end);
-
- return getLogParser(f, startDate, endDate, thread, loggers,
severity);
- }
-
- @RestOp(
- method="DOWNLOAD",
- path="/*",
- summary="Download file",
- description="Download the contents of a file.\nContent-Type is
set to 'application/octet-stream'."
- )
- public FileContents downloadFile(RestResponse res, @Path("/*") String
path) throws NotFound, MethodNotAllowed {
- res.setContentType("application/octet-stream");
- try {
- return new FileContents(getFile(path));
- } catch (FileNotFoundException e) {
- throw new NotFound("File not found");
- }
- }
-
- @RestDelete(
- path="/*",
- summary="Delete log file",
- description="Delete a log file on the file system."
- )
- public RedirectToRoot deleteFile(@Path("/*") String path) throws
MethodNotAllowed {
- deleteFile(getFile(path));
- return new RedirectToRoot();
- }
-
-
-
//-----------------------------------------------------------------------------------------------------------------
- // Helper beans
-
//-----------------------------------------------------------------------------------------------------------------
-
- @Response @Schema(type="string",format="binary",description="Contents
of file")
- static class FileContents extends FileInputStream {
- public FileContents(File file) throws FileNotFoundException {
- super(file);
- }
- }
-
- @Response @Schema(description="Redirect to root page on success")
- static class RedirectToRoot extends SeeOtherRoot {}
-
- @Response @Schema(description="File action")
- public static class Action extends LinkString {
- public Action(String name, String uri, Object...uriArgs) {
- super(name, uri, uriArgs);
- }
- }
-
- @Response @Schema(description="File or directory details")
- @Bean(properties="type,name,size,lastModified,actions,files")
- public static class FileResource {
- private final File f;
- private final String path;
- private final String uri;
- private final boolean includeChildren, allowDeletes;
-
- public FileResource(File f, String path, boolean allowDeletes,
boolean includeChildren) {
- this.f = f;
- this.path = path;
- this.uri = "servlet:/"+(path == null ? "" : path);
- this.includeChildren = includeChildren;
- this.allowDeletes = allowDeletes;
- }
-
- public String getType() {
- return (f.isDirectory() ? "dir" : "file");
- }
-
- public LinkString getName() {
- return new LinkString(f.getName(), uri);
- }
-
- public long getSize() {
- return f.isDirectory() ? f.listFiles().length :
f.length();
- }
-
- public Date getLastModified() {
- return new Date(f.lastModified());
- }
-
- @Html(format=HtmlFormat.HTML_CDC)
- public List<Action> getActions() throws Exception {
- List<Action> l = list();
- if (f.canRead() && ! f.isDirectory()) {
- l.add(new Action("view", uri + "?method=VIEW"));
- l.add(new Action("highlighted", uri +
"?method=VIEW&highlight=true"));
- l.add(new Action("parsed", uri +
"?method=PARSE"));
- l.add(new Action("download", uri +
"?method=DOWNLOAD"));
- if (allowDeletes)
- l.add(new Action("delete", uri +
"?method=DELETE"));
- }
- return l;
- }
-
- public Set<FileResource> getFiles() {
- if (f.isFile() || ! includeChildren)
- return null;
- Set<FileResource> s = new TreeSet<>(FILE_COMPARATOR);
- for (File fc : f.listFiles(FILE_FILTER))
- s.add(new FileResource(fc, (path != null ?
(path + '/') : "") + urlEncode(fc.getName()), allowDeletes, false));
- return s;
- }
-
- static final FileFilter FILE_FILTER = new FileFilter() {
- @Override /* FileFilter */
- public boolean accept(File f) {
- return f.isDirectory() ||
f.getName().endsWith(".log");
- }
- };
-
- static final Comparator<FileResource> FILE_COMPARATOR = new
Comparator<FileResource>() {
- @Override /* Comparator */
- public int compare(FileResource o1, FileResource o2) {
- int c = o1.getType().compareTo(o2.getType());
- return c != 0 ? c :
o1.getName().compareTo(o2.getName());
- }
- };
- }
-
-
-
//-----------------------------------------------------------------------------------------------------------------
- // Helper methods
-
//-----------------------------------------------------------------------------------------------------------------
-
- private File getFile(String path) throws NotFound {
- if (path == null)
- return logDir;
- File f = new File(logDir.getAbsolutePath() + '/' + path);
- if (f.exists())
- return f;
- throw new NotFound("File not found.");
- }
-
- private void deleteFile(File f) {
- if (! allowDeletes)
- throw new MethodNotAllowed("DELETE not enabled");
- if (f.isDirectory()) {
- File[] files = f.listFiles();
- if (files != null) {
- for (File fc : files)
- deleteFile(fc);
- }
- }
- if (! f.delete())
- throw new Forbidden("Could not delete file {0}",
f.getAbsolutePath()) ;
- }
-
- private static BufferedReader getReader(File f) throws IOException {
- return new BufferedReader(new InputStreamReader(new
FileInputStream(f), Charset.defaultCharset()));
- }
-
- private Object getReader(File f, final Date start, final Date end,
final String thread, final String[] loggers, final String[] severity) throws
IOException {
- if (start == null && end == null && thread == null && loggers
== null)
- return getReader(f);
- return getLogParser(f, start, end, thread, loggers, severity);
- }
-
- private LogParser getLogParser(File f, final Date start, final Date
end, final String thread, final String[] loggers, final String[] severity)
throws IOException {
- return new LogParser(leFormatter, f, start, end, thread,
loggers, severity);
- }
-}
diff --git
a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/SampleRootResource.java
b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/SampleRootResource.java
index 46ceccf5e..4f3a68257 100755
---
a/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/SampleRootResource.java
+++
b/juneau-microservice/juneau-microservice-core/src/main/java/org/apache/juneau/microservice/resources/SampleRootResource.java
@@ -30,7 +30,7 @@ import org.apache.juneau.rest.servlet.*;
path="/",
title="Sample Root Resource",
description="This is a sample router page",
- children={ConfigResource.class,LogsResource.class}
+ children={ConfigResource.class}
)
public class SampleRootResource extends BasicRestServletGroup implements
BasicUniversalConfig {
private static final long serialVersionUID = 1L;
diff --git
a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/Root.java
b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/Root.java
index d382b039d..80f3efc74 100644
---
a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/Root.java
+++
b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/Root.java
@@ -27,7 +27,6 @@ import org.apache.juneau.rest.test.client.*;
path="/*",
children={
DebugResource.class,
- LogsResource.class,
ConfigResource.class,
LargePojosResource.class,
ThirdPartyProxyResource.class,
diff --git
a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyResource.java
b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyResource.java
index e32eac2e1..193375a41 100644
---
a/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyResource.java
+++
b/juneau-microservice/juneau-microservice-ftest/src/test/java/org/apache/juneau/rest/test/client/ThirdPartyProxyResource.java
@@ -45,6 +45,7 @@ public class ThirdPartyProxyResource extends BasicRestServlet
implements BasicUn
public static FileWriter logFile;
static {
try {
+ new File("./target/logs").mkdirs();
logFile = new
FileWriter("./target/logs/third-party-proxy-resource.txt", false);
} catch (IOException e) {
e.printStackTrace();
diff --git
a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
index 9c1f86162..04b89d3df 100644
---
a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
+++
b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyMicroservice.java
@@ -371,12 +371,6 @@ public class JettyMicroservice extends Microservice {
return this;
}
- @Override /* MicroserviceBuilder */
- public Builder logConfig(LogConfig logConfig) {
- super.logConfig(logConfig);
- return this;
- }
-
@Override /* MicroserviceBuilder */
public Builder config(Config config) {
super.config(config);
diff --git
a/juneau-microservice/juneau-my-jetty-microservice/src/main/java/org/apache/juneau/microservice/jetty/template/RootResources.java
b/juneau-microservice/juneau-my-jetty-microservice/src/main/java/org/apache/juneau/microservice/jetty/template/RootResources.java
index 7d22c775b..fd74c7ae8 100755
---
a/juneau-microservice/juneau-my-jetty-microservice/src/main/java/org/apache/juneau/microservice/jetty/template/RootResources.java
+++
b/juneau-microservice/juneau-my-jetty-microservice/src/main/java/org/apache/juneau/microservice/jetty/template/RootResources.java
@@ -15,7 +15,6 @@ package org.apache.juneau.microservice.jetty.template;
import org.apache.juneau.html.annotation.HtmlDocConfig;
import org.apache.juneau.microservice.jetty.resources.DebugResource;
import org.apache.juneau.microservice.resources.ConfigResource;
-import org.apache.juneau.microservice.resources.LogsResource;
import org.apache.juneau.rest.annotation.*;
import org.apache.juneau.rest.servlet.BasicRestServletGroup;
import org.apache.juneau.rest.widget.ContentTypeMenuItem;
@@ -38,7 +37,6 @@ import org.apache.juneau.rest.widget.ThemeMenuItem;
children={
HelloWorldResource.class,
ConfigResource.class,
- LogsResource.class,
DebugResource.class
}
)
diff --git
a/juneau-microservice/juneau-my-springboot-microservice/src/main/java/org/apache/juneau/microservice/springboot/template/RootResources.java
b/juneau-microservice/juneau-my-springboot-microservice/src/main/java/org/apache/juneau/microservice/springboot/template/RootResources.java
index 051ab0b4c..6122e8ba2 100644
---
a/juneau-microservice/juneau-my-springboot-microservice/src/main/java/org/apache/juneau/microservice/springboot/template/RootResources.java
+++
b/juneau-microservice/juneau-my-springboot-microservice/src/main/java/org/apache/juneau/microservice/springboot/template/RootResources.java
@@ -36,8 +36,7 @@ import org.apache.juneau.serializer.annotation.*;
description="Example of a router resource page.",
children={
HelloWorldResource.class,
- ConfigResource.class,
- LogsResource.class
+ ConfigResource.class
}
)
@HtmlDocConfig(
diff --git
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 79012cf3a..53d594b7b 100644
---
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -4202,12 +4202,12 @@ public class RestContext extends Context {
RestContext cc = cb.init(so).build();
- MethodInfo mi = ClassInfo.of(o).getPublicMethod(
+ MethodInfo mi =
ClassInfo.of(so.get()).getMethod(
x -> x.hasName("setContext")
&& x.hasParamTypes(RestContext.class)
);
if (mi != null)
- mi.accessible().invoke(o, cc);
+ mi.accessible().invoke(so.get(), cc);
v.get().add(cc);
}
diff --git a/pom.xml b/pom.xml
index ef445293d..d35bd162f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -187,6 +187,7 @@
<!-- Generated by embedded
jetty server -->
<exclude>**/jetty.out.xml</exclude>
<exclude>**/*.log</exclude>
+ <exclude>**/*.log.*</exclude>
<!-- Generated in
juneau-microservice-template for some reason -->
<exclude>**/dependency-reduced-pom.xml</exclude>