From 8f7e49604729b3f727644db9f4932a87f8cc40d4 Mon Sep 17 00:00:00 2001 From: Jonathan Gallimore Date: Tue, 12 Dec 2023 11:07:16 +0000 Subject: [PATCH] TOMEE-4289 Patch SystemLogHandler --- .../tomcat/util/log/SystemLogHandler.java | 278 ++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/log/SystemLogHandler.java diff --git a/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/log/SystemLogHandler.java b/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/log/SystemLogHandler.java new file mode 100644 index 00000000000..2a3a6cd5a17 --- /dev/null +++ b/tomee/apache-tomee/src/patch/java/org/apache/tomcat/util/log/SystemLogHandler.java @@ -0,0 +1,278 @@ +/* + * 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.tomcat.util.log; + +import java.io.IOException; +import java.io.PrintStream; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.NoSuchElementException; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * This helper class may be used to do sophisticated redirection of + * System.out and System.err on a per Thread basis. + * + * A stack is implemented per Thread so that nested startCapture + * and stopCapture can be used. + * + * @author Remy Maucherat + * @author Glenn L. Nielsen + */ +public class SystemLogHandler extends PrintStream { + + + // ----------------------------------------------------------- Constructors + + + /** + * Construct the handler to capture the output of the given steam. + * + * @param wrapped The stream to capture + */ + public SystemLogHandler(PrintStream wrapped) { + super(wrapped); + out = wrapped; + } + + + // ----------------------------------------------------- Instance Variables + + + /** + * Wrapped PrintStream. + */ + private final PrintStream out; + + + /** + * Thread <-> CaptureLog associations. + */ + private static final ThreadLocal> logs = new ThreadLocal<>(); + + + /** + * Spare CaptureLog ready for reuse. + */ + private static final Queue reuse = new ConcurrentLinkedQueue<>(); + + + // --------------------------------------------------------- Public Methods + + + /** + * Start capturing thread's output. + */ + public static void startCapture() { + CaptureLog log = null; + if (!reuse.isEmpty()) { + try { + log = reuse.remove(); + } catch (NoSuchElementException e) { + log = new CaptureLog(); + } + } else { + log = new CaptureLog(); + } + Deque stack = logs.get(); + if (stack == null) { + stack = new ArrayDeque<>(); + logs.set(stack); + } + stack.addFirst(log); + } + + + /** + * Stop capturing thread's output. + * + * @return The captured data + */ + public static String stopCapture() { + Queue stack = logs.get(); + if (stack == null || stack.isEmpty()) { + return null; + } + CaptureLog log = stack.remove(); + if (log == null) { + return null; + } + String capture = log.getCapture(); + log.reset(); + reuse.add(log); + return capture; + } + + + // ------------------------------------------------------ Protected Methods + + + /** + * Find PrintStream to which the output must be written to. + * @return the print stream + */ + protected PrintStream findStream() { + Queue stack = logs.get(); + if (stack != null && !stack.isEmpty()) { + CaptureLog log = stack.peek(); + if (log != null) { + PrintStream ps = log.getStream(); + if (ps != null) { + return ps; + } + } + } + return out; + } + + + // ---------------------------------------------------- PrintStream Methods + + + @Override + public void flush() { + findStream().flush(); + } + + @Override + public void close() { + findStream().close(); + } + + @Override + public boolean checkError() { + return findStream().checkError(); + } + + @Override + protected void setError() { + //findStream().setError(); + } + + @Override + public void write(int b) { + findStream().write(b); + } + + @Override + public void write(byte[] b) + throws IOException { + findStream().write(b); + } + + @Override + public void write(byte[] buf, int off, int len) { + findStream().write(buf, off, len); + } + + @Override + public void print(boolean b) { + findStream().print(b); + } + + @Override + public void print(char c) { + findStream().print(c); + } + + @Override + public void print(int i) { + findStream().print(i); + } + + @Override + public void print(long l) { + findStream().print(l); + } + + @Override + public void print(float f) { + findStream().print(f); + } + + @Override + public void print(double d) { + findStream().print(d); + } + + @Override + public void print(char[] s) { + findStream().print(s); + } + + @Override + public void print(String s) { + findStream().print(s); + } + + @Override + public void print(Object obj) { + findStream().print(obj); + } + + @Override + public void println() { + findStream().println(); + } + + @Override + public void println(boolean x) { + findStream().println(x); + } + + @Override + public void println(char x) { + findStream().println(x); + } + + @Override + public void println(int x) { + findStream().println(x); + } + + @Override + public void println(long x) { + findStream().println(x); + } + + @Override + public void println(float x) { + findStream().println(x); + } + + @Override + public void println(double x) { + findStream().println(x); + } + + @Override + public void println(char[] x) { + findStream().println(x); + } + + @Override + public void println(String x) { + findStream().println(x); + } + + @Override + public void println(Object x) { + findStream().println(x); + } + +}