org.apache.openejb.util.JuliLogStreamFactory Maven / Gradle / Ivy
The newest version!
/*
* 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.openejb.util;
import org.apache.openejb.loader.Options;
import org.apache.openejb.loader.SystemInstance;
import org.apache.openejb.log.ConsoleColorHandler;
import org.apache.openejb.log.SingleLineFormatter;
import org.apache.openejb.util.reflection.Reflections;
import org.apache.webbeans.logger.WebBeansLoggerFacade;
import java.io.OutputStreamWriter;
import java.lang.reflect.Constructor;
import java.util.logging.ConsoleHandler;
import java.util.logging.LogManager;
import java.util.logging.Logger;
/**
* default conf = jre conf
* user conf used transparently
*/
public class JuliLogStreamFactory implements LogStreamFactory {
public static final String OPENEJB_LOG_COLOR_PROP = "openejb.log.color";
private static volatile String consoleHandlerClazz;
private static volatile boolean useOpenEJBHandler;
public JuliLogStreamFactory() {
final boolean tomee = is("org.apache.tomee.catalina.TomcatLoader");
final boolean embedded = is("org.apache.tomee.embedded.Container");
// if embedded case enhance a bit logging if not set
final Options options = SystemInstance.isInitialized() ? SystemInstance.get().getOptions() : new Options(System.getProperties());
final boolean forceLogs = options.get("openejb.jul.forceReload", false);
if ((!tomee || embedded || forceLogs) && System.getProperty("java.util.logging.manager") == null) {
consoleHandlerClazz = options.get("openejb.jul.consoleHandlerClazz", (String) null);
if (consoleHandlerClazz == null) {
if (options.get(OPENEJB_LOG_COLOR_PROP, false) && isNotIDE()) {
consoleHandlerClazz = ConsoleColorHandler.class.getName();
} else {
consoleHandlerClazz = OpenEJBSimpleLayoutHandler.class.getName();
}
}
try { // check it will not fail later (case when a framework change the JVM classloading)
ClassLoader.getSystemClassLoader().loadClass(consoleHandlerClazz);
} catch (final ClassNotFoundException e) {
consoleHandlerClazz = ConsoleHandler.class.getName();
}
if (forceLogs) {
useOpenEJBHandler = options.get("openejb.jul.forceReload.use-openejb-handler", true);
try {
final OpenEJBLogManager value = new OpenEJBLogManager();
Reflections.set(LogManager.class, null, "manager", value);
value.forceReset();
setRootLogger(value);
value.readConfiguration(); // re-read the config to ensure we have a parent logger
} catch (final Exception e) {
// no-op
}
}
// do it last since otherwise it can lock
System.setProperty("java.util.logging.manager", OpenEJBLogManager.class.getName());
}
try {
if (options.get("openjpa.Log", (String) null) == null) {
JuliLogStreamFactory.class.getClassLoader().loadClass("org.apache.openjpa.lib.log.LogFactoryAdapter");
System.setProperty("openjpa.Log", "org.apache.openejb.openjpa.JULOpenJPALogFactory");
}
} catch (final Exception ignored) {
// no-op: openjpa is not at the classpath so don't trigger it loading with our logger
}
try {
System.setProperty(WebBeansLoggerFacade.class.getName(), "org.apache.webbeans.logger.JULLoggerFactory");
} catch (final Throwable th) {
// ignored, surely arquillian remote only so OWB is not here
}
}
@Override
public LogStream createLogStream(final LogCategory logCategory) {
return new JuliLogStream(logCategory);
}
private static void setRootLogger(final OpenEJBLogManager value) {
try { // if we don't do it - which is done in static part of the LogManager - we couldn't log user info when force-reload is to true
final Class> rootLoggerClass = ClassLoader.getSystemClassLoader().loadClass("java.util.logging.LogManager$RootLogger");
final Constructor> cons = rootLoggerClass.getDeclaredConstructor(LogManager.class);
final boolean acc = cons.isAccessible();
if (!acc) {
cons.setAccessible(true);
}
final Logger rootLogger = Logger.class.cast(cons.newInstance(value));
try {
Reflections.set(value, "rootLogger", rootLogger);
} finally {
cons.setAccessible(acc);
}
value.addLogger(rootLogger);
Reflections.invokeByReflection(Reflections.get(value, "systemContext"), "addLocalLogger", new Class>[]{Logger.class}, new Object[]{rootLogger});
Reflections.invokeByReflection(Logger.global, "setLogManager", new Class>[]{LogManager.class}, new Object[]{value});
value.addLogger(Logger.global);
} catch (final Throwable e) {
// no-op
}
}
public static boolean isNotIDE() {
return !System.getProperty("java.class.path").contains("idea_rt"); // TODO: eclipse, netbeans
}
// TODO: mange conf by classloader? see tomcat log manager
public static class OpenEJBLogManager extends LogManager {
static {
final LogManager mgr = LogManager.getLogManager();
if (mgr instanceof OpenEJBLogManager) {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
((OpenEJBLogManager) mgr).forceReset();
}
});
}
}
public void forceReset() {
super.reset();
}
@Override
public void reset() throws SecurityException {
// no-op
}
@Override
public String getProperty(final String name) {
final String parentValue = super.getProperty(name);
if (SystemInstance.isInitialized()) {
if (SystemInstance.get().getProperties().containsKey(name)) {
return SystemInstance.get().getProperty(name);
}
final String propertyKeyValue = "logging" + reverseProperty(name);
if (SystemInstance.get().getProperties().containsKey(propertyKeyValue)) {
return SystemInstance.get().getProperty(propertyKeyValue);
}
}
// if it is one of ours loggers and no value is defined let set our nice logging style
if (OpenEJBLogManager.class.getName().equals(System.getProperty("java.util.logging.manager")) // custom logging
&& isOverridableLogger(name) // managed loggers
&& parentValue == null) { // not already defined
if (name.endsWith(".handlers")) {
return consoleHandlerClazz;
} else if (name.endsWith(".useParentHandlers")) {
return "false";
}
}
return parentValue;
}
}
private static String reverseProperty(final String name) {
if (name.contains(".") && !name.endsWith(".")) {
final int idx = name.lastIndexOf('.');
return name.substring(idx) + "." + name.substring(0, idx);
}
return name;
}
private static boolean isOverridableLogger(final String name) {
return useOpenEJBHandler
|| name.toLowerCase().contains("openejb")
|| name.toLowerCase().contains("transaction")
|| name.toLowerCase().contains("cxf")
|| name.toLowerCase().contains("timer")
|| (name.startsWith("org.apache.") && !name.startsWith("org.apache.geronimo.connector.work.WorkerContext."))
|| name.startsWith("openjpa.")
|| name.startsWith("net.sf.ehcache.")
|| name.startsWith("org.quartz.")
|| name.startsWith("org.hibernate.");
}
public static class OpenEJBSimpleLayoutHandler extends ConsoleHandler {
public OpenEJBSimpleLayoutHandler() {
setFormatter(new SingleLineFormatter());
//setOutputStream(System.out); // don't do it otherwise you'll lost exception etc in the console
Reflections.set(this, "writer", new OutputStreamWriter(System.out));
}
}
private static boolean is(final String classname) {
try {
JuliLogStreamFactory.class.getClassLoader().loadClass(classname);
return true;
} catch (final Exception e) {
return false;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy