Skip to content

Commit

Permalink
Merge branch 'jruby-logger-ng'
Browse files Browse the repository at this point in the history
* jruby-logger-ng: (21 commits)
  make SLF4J dependency optional
  simply use isDebug() instead of getDebug().isTrue()
  do not remove backtrace's last new line as others don't
  make sure printed caller/warning backtraces are not printed as (hard to read) array.to_s
  no need to double check for null ... printBacktraceJRuby does the very same
  remove DEBUG field - LOG.setDebugEnable will do better in enabling detailed logs
  use debug level to log + setDebugEnable on JIT_LOADING_DEBUG this way logging will work as expected with delegated logging such as SLF4J as well
  refactor DEBUG field into setDebugEnable + log at the debug level
  no need to use Logger in InvokerGenerator ... only invoked from cmd-line
  unused logger field
  cleanup - adjust some of the logging calls (most importantly to happen in one stmnt)
  refactor to using the new preferred way of getting a logger - by passing a class down
  support getLogger with a Class parameter - where package name is not skipped
  SLF4J JRuby logger implementation (which delegates all logs to a SLF4J impl)
  introduce a java.util.logging JRuby logger implementation (which delegates all logs)
  re-use OutputStreamLogger test-cases test with StandardErrorLogger
  cleanup LoggerFactory (for later extension)
  include current thread-name as well as level in logger's formatted message e.g. :
  cleanup asserts around exception with stack-trace being logged
  make sure redirected System.err is picked up - not uncommon to happen on Ruby land
  ...
kares committed Apr 25, 2016
2 parents c0faa0c + 74f0d4f commit a513b5c
Showing 55 changed files with 1,391 additions and 474 deletions.
4 changes: 4 additions & 0 deletions core/pom.rb
Original file line number Diff line number Diff line change
@@ -75,6 +75,10 @@
jar 'org.jruby:joda-timezones:${tzdata.version}', :scope => '${tzdata.scope}'
jar 'joda-time:joda-time:${joda.time.version}'

# SLF4J only used within SLF4JLogger (JRuby logger impl) class
jar 'org.slf4j:slf4j-api:1.7.12', :scope => 'provided', :optional => true
jar 'org.slf4j:slf4j-simple:1.7.12', :scope => 'test'

plugin_management do
plugin( 'org.eclipse.m2e:lifecycle-mapping:1.0.0',
'lifecycleMappingMetadata' => {
13 changes: 13 additions & 0 deletions core/pom.xml
Original file line number Diff line number Diff line change
@@ -263,6 +263,19 @@ DO NOT MODIFIY - GENERATED CODE
<artifactId>joda-time</artifactId>
<version>${joda.time.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.12</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>package</defaultGoal>
15 changes: 9 additions & 6 deletions core/src/main/java/org/jruby/Main.java
Original file line number Diff line number Diff line change
@@ -76,7 +76,7 @@
* @author jpetersen
*/
public class Main {
private static final Logger LOG = LoggerFactory.getLogger("Main");
private static final Logger LOG = LoggerFactory.getLogger(Main.class);

public Main(RubyInstanceConfig config) {
this(config, false);
@@ -143,11 +143,14 @@ private static void loadJRubyProperties(File dotfile) {
for (Map.Entry entry : newProps.entrySet()) {
sysProps.put("jruby." + entry.getKey(), entry.getValue());
}
} catch (IOException ioe) {
LOG.debug("exception loading " + dotfile, ioe);
} catch (SecurityException se) {
LOG.debug("exception loading " + dotfile, se);
} finally {
}
catch (IOException ioe) {
if (LOG.isDebugEnabled()) LOG.debug("exception loading " + dotfile, ioe);
}
catch (SecurityException se) {
if (LOG.isDebugEnabled()) LOG.debug("exception loading " + dotfile, se);
}
finally {
if (fis != null) try {fis.close();} catch (Exception e) {}
}
}
46 changes: 26 additions & 20 deletions core/src/main/java/org/jruby/Ruby.java
Original file line number Diff line number Diff line change
@@ -224,7 +224,10 @@ public final class Ruby implements Constantizable {
/**
* The logger used to log relevant bits.
*/
private static final Logger LOG = LoggerFactory.getLogger("Ruby");
private static final Logger LOG = LoggerFactory.getLogger(Ruby.class);
static { // enable DEBUG output
if (RubyInstanceConfig.JIT_LOADING_DEBUG) LOG.setDebugEnable(true);
}

/**
* Create and initialize a new JRuby runtime. The properties of the
@@ -655,13 +658,15 @@ public IRubyObject runWithGetsLoop(RootNode scriptNode, boolean printing, boolea
try {
script = tryCompile(scriptNode);
if (Options.JIT_LOGGING.load()) {
LOG.info("Successfully compiled: " + scriptNode.getFile());
LOG.info("Successfully compiled: {}", scriptNode.getFile());
}
} catch (Throwable e) {
if (Options.JIT_LOGGING.load()) {
LOG.error("Failed to compile: " + scriptNode.getFile());
if (Options.JIT_LOGGING_VERBOSE.load()) {
LOG.error(e);
LOG.error("Failed to compile: " + scriptNode.getFile(), e);
}
else {
LOG.error("Failed to compile: " + scriptNode.getFile());
}
}
}
@@ -805,9 +810,12 @@ private ScriptAndCode tryCompile(RootNode root, ClassDefiningClassLoader classLo
return Compiler.getInstance().execute(this, root, classLoader);
} catch (NotCompilableException e) {
if (Options.JIT_LOGGING.load()) {
LOG.error("failed to compile target script " + root.getFile() + ": " + e.getLocalizedMessage());

if (Options.JIT_LOGGING_VERBOSE.load()) LOG.error(e);
if (Options.JIT_LOGGING_VERBOSE.load()) {
LOG.error("failed to compile target script " + root.getFile() + ": ", e);
}
else {
LOG.error("failed to compile target script " + root.getFile() + ": " + e.getLocalizedMessage());
}
}
return null;
}
@@ -3016,22 +3024,22 @@ public void compileAndLoadFile(String filename, InputStream in, boolean wrap) {
Class contents;
try {
contents = getJRubyClassLoader().loadClass(className);
if (RubyInstanceConfig.JIT_LOADING_DEBUG) {
LOG.info("found jitted code for " + filename + " at class: " + className);
if (LOG.isDebugEnabled()) { // RubyInstanceConfig.JIT_LOADING_DEBUG
LOG.debug("found jitted code for " + filename + " at class: " + className);
}
script = (Script) contents.newInstance();
readStream = new ByteArrayInputStream(buffer);
} catch (ClassNotFoundException cnfe) {
if (RubyInstanceConfig.JIT_LOADING_DEBUG) {
LOG.info("no jitted code in classloader for file " + filename + " at class: " + className);
if (LOG.isDebugEnabled()) { // RubyInstanceConfig.JIT_LOADING_DEBUG
LOG.debug("no jitted code in classloader for file " + filename + " at class: " + className);
}
} catch (InstantiationException ie) {
if (RubyInstanceConfig.JIT_LOADING_DEBUG) {
LOG.info("jitted code could not be instantiated for file " + filename + " at class: " + className);
} catch (InstantiationException ex) {
if (LOG.isDebugEnabled()) { // RubyInstanceConfig.JIT_LOADING_DEBUG
LOG.debug("jitted code could not be instantiated for file " + filename + " at class: " + className + ' ' + ex);
}
} catch (IllegalAccessException iae) {
if (RubyInstanceConfig.JIT_LOADING_DEBUG) {
LOG.info("jitted code could not be instantiated for file " + filename + " at class: " + className);
} catch (IllegalAccessException ex) {
if (LOG.isDebugEnabled()) { // RubyInstanceConfig.JIT_LOADING_DEBUG
LOG.debug("jitted code could not be instantiated for file " + filename + " at class: " + className + ' ' + ex);
}
}
} catch (IOException ioe) {
@@ -4018,9 +4026,7 @@ public RaiseException newSystemStackError(String message) {
}

public RaiseException newSystemStackError(String message, StackOverflowError soe) {
if (getDebug().isTrue()) {
LOG.debug(soe.getMessage(), soe);
}
if ( isDebug() ) LOG.debug(soe);
return newRaiseException(getSystemStackError(), message);
}

4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/RubyBasicObject.java
Original file line number Diff line number Diff line change
@@ -110,9 +110,9 @@
*/
public class RubyBasicObject implements Cloneable, IRubyObject, Serializable, Comparable<IRubyObject>, CoreObjectType, InstanceVariables, InternalVariables {

private static final Logger LOG = LoggerFactory.getLogger("RubyBasicObject");
//private static final Logger LOG = LoggerFactory.getLogger(RubyBasicObject.class);

private static final boolean DEBUG = false;
//private static final boolean DEBUG = false;

/** The class of this object */
protected transient RubyClass metaClass;
7 changes: 3 additions & 4 deletions core/src/main/java/org/jruby/RubyClass.java
Original file line number Diff line number Diff line change
@@ -100,7 +100,7 @@
@JRubyClass(name="Class", parent="Module")
public class RubyClass extends RubyModule {

private static final Logger LOG = LoggerFactory.getLogger("RubyClass");
private static final Logger LOG = LoggerFactory.getLogger(RubyClass.class);

public static void createClassClass(Ruby runtime, RubyClass classClass) {
classClass.setClassIndex(ClassIndex.CLASS);
@@ -1634,9 +1634,8 @@ private boolean isVarArgsSignature(final String method, final Class[] methodSign

private void logReifyException(final Throwable failure, final boolean error) {
if (RubyInstanceConfig.REIFY_LOG_ERRORS) {
final String msg = "failed to reify class " + getName() + " due to: ";
if ( error ) LOG.error(msg, failure);
else LOG.info(msg, failure);
if ( error ) LOG.error("failed to reify class " + getName() + " due to: ", failure);
else LOG.info("failed to reify class " + getName() + " due to: ", failure);
}
}

17 changes: 8 additions & 9 deletions core/src/main/java/org/jruby/RubyModule.java
Original file line number Diff line number Diff line change
@@ -128,9 +128,9 @@
@JRubyClass(name="Module")
public class RubyModule extends RubyObject {

private static final Logger LOG = LoggerFactory.getLogger("RubyModule");
private static final Logger LOG = LoggerFactory.getLogger(RubyModule.class);
// static { LOG.setDebugEnable(true); } // enable DEBUG output

private static final boolean DEBUG = false;
protected static final String ERR_INSECURE_SET_CONSTANT = "Insecure: can't modify constant";

public static final ObjectAllocator MODULE_ALLOCATOR = new ObjectAllocator() {
@@ -1016,23 +1016,22 @@ public final Map<String, List<JavaMethodDescriptor>> getStaticAnnotatedMethods()
public static TypePopulator loadPopulatorFor(Class<?> type) {
if (Options.DEBUG_FULLTRACE.load() || Options.REFLECTED_HANDLES.load()) {
// we want non-generated invokers or need full traces, use default (slow) populator
if (DEBUG) LOG.info("trace mode, using default populator");
LOG.debug("trace mode, using default populator");
} else {
try {
String qualifiedName = "org.jruby.gen." + type.getCanonicalName().replace('.', '$');
String fullName = qualifiedName + AnnotationBinder.POPULATOR_SUFFIX;
String fullPath = fullName.replace('.', '/') + ".class";

if (DEBUG) LOG.info("looking for " + fullName);
if (LOG.isDebugEnabled()) LOG.debug("looking for populator " + fullName);

if (Ruby.getClassLoader().getResource(fullPath) == null) {
if (DEBUG) LOG.info("Could not find it, using default populator");
LOG.debug("could not find it, using default populator");
} else {
Class populatorClass = Class.forName(qualifiedName + AnnotationBinder.POPULATOR_SUFFIX);
return (TypePopulator) populatorClass.newInstance();
}
} catch (Throwable t) {
if (DEBUG) LOG.info("Could not find it, using default populator");
} catch (Throwable ex) {
if (LOG.isDebugEnabled()) LOG.debug("could not find populator, using default (" + ex + ')');
}
}

@@ -1439,7 +1438,7 @@ protected DynamicMethod searchMethodCommon(String name) {
}

public void invalidateCacheDescendants() {
if (DEBUG) LOG.debug("invalidating descendants: {}", baseName);
LOG.debug("{} invalidating descendants", baseName);

if (includingHierarchies.isEmpty()) {
// it's only us; just invalidate directly
6 changes: 3 additions & 3 deletions core/src/main/java/org/jruby/RubyThread.java
Original file line number Diff line number Diff line change
@@ -103,7 +103,8 @@
@JRubyClass(name="Thread")
public class RubyThread extends RubyObject implements ExecutionContext {

private static final Logger LOG = LoggerFactory.getLogger("RubyThread");
private static final Logger LOG = LoggerFactory.getLogger(RubyThread.class);
// static { LOG.setDebugEnable(true); }

/** The thread-like think that is actually executing */
private volatile ThreadLike threadImpl;
@@ -151,7 +152,6 @@ public class RubyThread extends RubyObject implements ExecutionContext {
/** Thread-local tuple used for sleeping (semaphore, millis, nanos) */
private final SleepTask2 sleepTask = new SleepTask2();

private static final boolean DEBUG = false;
public static final int RUBY_MIN_THREAD_PRIORITY = -3;
public static final int RUBY_MAX_THREAD_PRIORITY = 3;

@@ -1516,7 +1516,7 @@ public void dieFromFinalizer() {
}

private static void debug(RubyThread thread, String message) {
if (DEBUG) LOG.debug(Thread.currentThread() + "(" + thread.status + "): " + message);
if (LOG.isDebugEnabled()) LOG.debug( "{} ({}): {}", Thread.currentThread(), thread.status, message );
}

@JRubyMethod
28 changes: 13 additions & 15 deletions core/src/main/java/org/jruby/anno/InvokerGenerator.java
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@
* rights and limitations under the License.
*
* Copyright (C) 2008-2012 Charles Oliver Nutter <headius@headius.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -39,25 +39,22 @@
import org.jruby.RubyModule.MethodClumper;
import org.jruby.internal.runtime.methods.DumpingInvocationMethodFactory;
import org.jruby.util.ClassDefiningJRubyClassLoader;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

public class InvokerGenerator {

private static final Logger LOG = LoggerFactory.getLogger("InvokerGenerator");
private static final boolean DEBUG = false;

public static final boolean DEBUG = false;

public static void main(String[] args) throws Exception {
FileReader fr = null;
final FileReader fileReader;
try {
fr = new FileReader(args[0]);
} catch(FileNotFoundException e) {
fileReader = new FileReader(args[0]);
}
catch (FileNotFoundException e) {
System.err.println(args[0] + " - not found. skip generator." );
return;
}
BufferedReader br = new BufferedReader(fr);
BufferedReader br = new BufferedReader(fileReader);

List<String> classNames = new ArrayList<String>();
try {
String line;
@@ -72,9 +69,9 @@ public static void main(String[] args) throws Exception {

for (String name : classNames) {
MethodClumper clumper = new MethodClumper();

try {
if (DEBUG) LOG.debug("generating for class {}", name);
if (DEBUG) System.err.println("generating for class " + name);
Class cls = Class.forName(name, false, InvokerGenerator.class.getClassLoader());

clumper.clump(cls);
@@ -86,8 +83,9 @@ public static void main(String[] args) throws Exception {
for (Map.Entry<String, List<JavaMethodDescriptor>> entry : clumper.getAnnotatedMethods().entrySet()) {
dumper.getAnnotatedMethodClass(entry.getValue());
}
} catch (Exception e) {
e.printStackTrace();
}
catch (Exception e) {
e.printStackTrace(System.err);
throw e;
}
}
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/compiler/JITCompiler.java
Original file line number Diff line number Diff line change
@@ -70,7 +70,7 @@
import java.util.concurrent.atomic.AtomicLong;

public class JITCompiler implements JITCompilerMBean {
private static final Logger LOG = LoggerFactory.getLogger("JITCompiler");
private static final Logger LOG = LoggerFactory.getLogger(JITCompiler.class);

public static final String RUBY_JIT_PREFIX = "rubyjit";

Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
* rights and limitations under the License.
*
* Copyright (C) 2002-2011 JRuby Community
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -46,17 +46,17 @@
/**
* Closest thing to JRubyClassLoader's addURL but for OSGi bundles.
* Used as the parent classloader the usual jruby's bundle's classloader.
*
*
* @author hmalphettes
*
*/
public class JRubyOSGiBundleClassLoader extends ClassLoader implements BundleReference {

private static final Logger LOG = LoggerFactory.getLogger(JRubyOSGiBundleClassLoader.class.getName());
private static final Logger LOG = LoggerFactory.getLogger(JRubyOSGiBundleClassLoader.class);
private static final IOSGiClassLoaderAdapter ADAPTER;

static {
IOSGiClassLoaderAdapter chosenAdapter = null;
IOSGiClassLoaderAdapter chosenAdapter;
try {
Bundle b = FrameworkUtil.getBundle(JRubyOSGiBundleClassLoader.class);
// I don't want to actually reference this class, in case it's unavailable
@@ -76,11 +76,11 @@ public class JRubyOSGiBundleClassLoader extends ClassLoader implements BundleRef
* we could look in jruby first if that makes more sense.
*/
private boolean _lookInOsgiFirst = true;

private LinkedHashMap<Bundle,ClassLoader> _libraries;

/**
* @param
* @param
* @throws IOException
*/
public JRubyOSGiBundleClassLoader()
@@ -89,7 +89,7 @@ public JRubyOSGiBundleClassLoader()
_libraries = new LinkedHashMap<Bundle, ClassLoader>();
}
/**
* @param
* @param
* @throws IOException
*/
public JRubyOSGiBundleClassLoader(Bundle creator)
@@ -98,7 +98,7 @@ public JRubyOSGiBundleClassLoader(Bundle creator)
addBundle(creator);
}
/**
* @param
* @param
* @throws IOException
*/
public void addBundle(Class<?> classInOsgiBundle)
@@ -122,7 +122,7 @@ public boolean addBundle(Bundle bundle)
{
return _libraries.put(bundle, ADAPTER.getClassLoader(bundle)) != null;
}

/**
* @param parent The parent classloader. In this case jrubyLoader
* @param context The WebAppContext
@@ -134,10 +134,10 @@ public boolean removeBundle(Bundle bundle)
{
return _libraries.remove(bundle) != null;
}

/**
* Returns the <code>Bundle</code> that defined this web-application.
*
*
* @return The <code>Bundle</code> object associated with this
* <code>BundleReference</code>.
*/
@@ -168,37 +168,37 @@ public Enumeration<URL> getResources(String name) throws IOException
}
return Collections.enumeration(toList(enums));
}

@Override
public URL getResource(String name)
{
if (_lookInOsgiFirst)
{
URL url = null;
for (ClassLoader cl : _libraries.values()) {
for (ClassLoader cl : _libraries.values()) {
url = cl.getResource(name);
if (url != null) {
return url;
}
}
return super.getResource(name);
}
else
else
{
URL url = super.getResource(name);
if (url != null) {
return url;
}
for (ClassLoader cl : _libraries.values()) {
for (ClassLoader cl : _libraries.values()) {
url = cl.getResource(name);
if (url != null) {
return url;
}
}
return null;
}
}
}

private List<URL> toList(List<Enumeration<URL>> l)
{
List<URL> list = new LinkedList<URL>();
@@ -211,7 +211,7 @@ private List<URL> toList(List<Enumeration<URL>> l)
}

/**
*
*
*/
protected Class<?> findClass(String name) throws ClassNotFoundException
{
@@ -235,7 +235,7 @@ protected Class<?> findClass(String name) throws ClassNotFoundException
}
throw cne;
}

}
}

2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ext/digest/RubyDigest.java
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ public class RubyDigest {
}
}

private static Logger logger() { return LoggerFactory.getLogger("RubyDigest"); }
private static Logger logger() { return LoggerFactory.getLogger(RubyDigest.class); }

private static final String PROVIDER = "org.bouncycastle.jce.provider.BouncyCastleProvider";
private static Provider provider = null;
20 changes: 10 additions & 10 deletions core/src/main/java/org/jruby/internal/runtime/RubyRunnable.java
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@
* rights and limitations under the License.
*
* Copyright (C) 2007 Charles O Nutter <headius@headius.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -43,38 +43,38 @@

public class RubyRunnable implements ThreadedRunnable {

private static final Logger LOG = LoggerFactory.getLogger("RubyRunnable");
private static final Logger LOG = LoggerFactory.getLogger(RubyRunnable.class);

private final Ruby runtime;
private final RubyProc proc;
private final IRubyObject[] arguments;
private final RubyThread rubyThread;

private Thread javaThread;
private static boolean warnedAboutTC = false;

public RubyRunnable(RubyThread rubyThread, IRubyObject[] args, Block currentBlock) {
this.rubyThread = rubyThread;
this.runtime = rubyThread.getRuntime();

proc = runtime.newProc(Block.Type.THREAD, currentBlock);
this.arguments = args;
}

@Deprecated
public RubyThread getRubyThread() {
return rubyThread;
}

public Thread getJavaThread() {
return javaThread;
}

@Override
public void run() {
javaThread = Thread.currentThread();
ThreadContext context = runtime.getThreadService().registerNewThread(rubyThread);

// set thread context JRuby classloader here, for Ruby-owned thread
ClassLoader oldContextClassLoader = null;
try {
@@ -87,7 +87,7 @@ public void run() {
LOG.info("WARNING: Security restrictions disallowed setting context classloader for Ruby threads.");
}
}

rubyThread.beforeStart();

// uber-ThreadKill catcher, since it should always just mean "be dead"
Original file line number Diff line number Diff line change
@@ -24,7 +24,7 @@
* Method for -X-C (interpreted only execution). See MixedModeIRMethod for inter/JIT method impl.
*/
public class InterpretedIRMethod extends AbstractIRMethod implements Compilable<InterpreterContext> {
private static final Logger LOG = LoggerFactory.getLogger("InterpretedIRMethod");
private static final Logger LOG = LoggerFactory.getLogger(InterpretedIRMethod.class);

private boolean displayedCFG = false; // FIXME: Remove when we find nicer way of logging CFG

Original file line number Diff line number Diff line change
@@ -10,10 +10,10 @@
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
*
* Copyright (C) 2006 The JRuby Community <www.jruby.org>
* Copyright (C) 2006 Ola Bini <ola@ologix.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -77,7 +77,7 @@
*/
public class InvocationMethodFactory extends MethodFactory implements Opcodes {

private static final Logger LOG = LoggerFactory.getLogger("InvocationMethodFactory");
private static final Logger LOG = LoggerFactory.getLogger(InvocationMethodFactory.class);

private static final boolean DEBUG = false;

Original file line number Diff line number Diff line change
@@ -10,9 +10,9 @@
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
*
* Copyright (C) 2012 The JRuby Community <www.jruby.org>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -55,16 +55,16 @@
/**
* This invoker uses MethodHandle for all bindings to Java code, rather than generating
* stubs or using reflection.
*
*
* @see org.jruby.runtime.MethodFactory
* @see HandleMethod
*/
public class InvokeDynamicMethodFactory extends InvocationMethodFactory {

private static final Logger LOG = LoggerFactory.getLogger("InvokeDynamicMethodFactory");
private static final Logger LOG = LoggerFactory.getLogger(InvokeDynamicMethodFactory.class);

private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();

/**
*/
public InvokeDynamicMethodFactory(ClassLoader classLoader) {
@@ -75,7 +75,7 @@ public InvokeDynamicMethodFactory(ClassLoader classLoader) {
public DynamicMethod getAnnotatedMethod(final RubyModule implementationClass, final List<JavaMethodDescriptor> descs) {
JavaMethodDescriptor desc1 = descs.get(0);
DescriptorInfo info = new DescriptorInfo(desc1);

if (desc1.anno.frame()) {
// super logic does not work yet because we need to take impl class
// and method name from the DynamicMethod#call call, so punt to
@@ -116,7 +116,7 @@ public DynamicMethod getAnnotatedMethod(final RubyModule implementationClass, fi
}

Callable<MethodHandle>[] generators = buildAnnotatedMethodHandles(implementationClass.getRuntime(), descs, implementationClass);

return new HandleMethod(
implementationClass,
desc1.anno.visibility(),
@@ -150,7 +150,7 @@ private Callable<MethodHandle>[] buildAnnotatedMethodHandles(Ruby runtime, List<
}

Callable<MethodHandle>[] targets = new Callable[5];

for (JavaMethodDescriptor desc: descs) {
MethodHandle method;

@@ -187,7 +187,7 @@ private Callable<MethodHandle>[] buildAnnotatedMethodHandles(Ruby runtime, List<
targets[4] = target;
}
}

return targets;
}

@@ -317,14 +317,14 @@ public MethodHandle call() throws Exception {
/**
* Use code generation to provide a method handle based on an annotated Java
* method.
*
*
* @see org.jruby.runtime.MethodFactory#getAnnotatedMethod
*/
@Override
public DynamicMethod getAnnotatedMethod(RubyModule implementationClass, JavaMethodDescriptor desc) {
return getAnnotatedMethod(implementationClass, Collections.singletonList(desc));
}

public static final Signature VARIABLE_ARITY_SIGNATURE = Signature
.returning(IRubyObject.class)
.appendArg("context", ThreadContext.class)
@@ -333,7 +333,7 @@ public DynamicMethod getAnnotatedMethod(RubyModule implementationClass, JavaMeth
.appendArg("name", String.class)
.appendArg("args", IRubyObject[].class)
.appendArg("block", Block.class);

public static final Signature[] SPECIFIC_ARITY_SIGNATURES;
static {
Signature[] specifics = new Signature[4];
@@ -343,17 +343,17 @@ public DynamicMethod getAnnotatedMethod(RubyModule implementationClass, JavaMeth
.appendArg("self", IRubyObject.class)
.appendArg("class", RubyModule.class)
.appendArg("name", String.class);

specifics[0] = specific.appendArg("block", Block.class);

for (int i = 0; i < 3; i++) {
specific = specific
.appendArg("arg" + i, IRubyObject.class);
specifics[i + 1] = specific.appendArg("block", Block.class);
}
SPECIFIC_ARITY_SIGNATURES = specifics;
}

private static final SmartBinder[] SPREAD_BINDERS = new SmartBinder[4];
static {
for (int i = 0; i < 4; i++) {
Original file line number Diff line number Diff line change
@@ -21,7 +21,7 @@
import java.io.ByteArrayOutputStream;

public class MixedModeIRMethod extends AbstractIRMethod implements Compilable<DynamicMethod> {
private static final Logger LOG = LoggerFactory.getLogger("InterpretedIRMethod");
private static final Logger LOG = LoggerFactory.getLogger(MixedModeIRMethod.class);

private boolean displayedCFG = false; // FIXME: Remove when we find nicer way of logging CFG

2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/IRScope.java
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@
* and so on ...
*/
public abstract class IRScope implements ParseResult {
public static final Logger LOG = LoggerFactory.getLogger("IRScope");
public static final Logger LOG = LoggerFactory.getLogger(IRScope.class);

private static final Collection<IRClosure> NO_CLOSURES = Collections.unmodifiableCollection(new ArrayList<IRClosure>(0));

4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/ir/interpreter/Interpreter.java
Original file line number Diff line number Diff line change
@@ -33,7 +33,7 @@
import org.jruby.util.log.LoggerFactory;

public class Interpreter extends IRTranslator<IRubyObject, IRubyObject> {
public static final Logger LOG = LoggerFactory.getLogger("Interpreter");
public static final Logger LOG = LoggerFactory.getLogger(Interpreter.class);
public static final String ROOT = "(root)";
static int interpInstrsCount = 0;

@@ -71,7 +71,7 @@ protected IRubyObject execute(Ruby runtime, IRScriptBody irScope, IRubyObject se
ThreadContext context = runtime.getCurrentContext();
String name = ROOT;

if (IRRuntimeHelpers.isDebug()) LOG.info("Executing " + ic);
if (IRRuntimeHelpers.isDebug()) LOG.info("Executing {}", ic);

// We get the live object ball rolling here.
// This give a valid value for the top of this lexical tree.
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
import java.util.Map;

public class BasicCompilerPassListener implements CompilerPassListener {
private static final Logger LOG = LoggerFactory.getLogger("BasicCompilerPassListener");
private static final Logger LOG = LoggerFactory.getLogger(BasicCompilerPassListener.class);

private Map<CompilerPass, Long> times = new HashMap<CompilerPass, Long>();

14 changes: 7 additions & 7 deletions core/src/main/java/org/jruby/ir/passes/CompilerPass.java
Original file line number Diff line number Diff line change
@@ -99,7 +99,7 @@ protected Object run(IRScope scope, boolean force, boolean childScope) {
listener.startExecute(this, scope, childScope);
}

// Record this pass
// Record this pass
scope.getExecutedPasses().add(this);

Object passData = execute(scope, data);
@@ -137,17 +137,17 @@ public static CompilerPass createPassInstance(Class<? extends CompilerPass> pass
try {
return (CompilerPass) passClass.getDeclaredConstructor().newInstance();
} catch (InstantiationException ex) {
LoggerFactory.getLogger(CompilerPass.class.getName()).error(null, ex);
LoggerFactory.getLogger(CompilerPass.class).error(ex);
} catch (IllegalAccessException ex) {
LoggerFactory.getLogger(CompilerPass.class.getName()).error(null, ex);
LoggerFactory.getLogger(CompilerPass.class).error(ex);
} catch (IllegalArgumentException ex) {
LoggerFactory.getLogger(CompilerPass.class.getName()).error(null, ex);
LoggerFactory.getLogger(CompilerPass.class).error(ex);
} catch (InvocationTargetException ex) {
LoggerFactory.getLogger(CompilerPass.class.getName()).error(null, ex);
LoggerFactory.getLogger(CompilerPass.class).error(ex);
} catch (NoSuchMethodException ex) {
LoggerFactory.getLogger(CompilerPass.class.getName()).error(null, ex);
LoggerFactory.getLogger(CompilerPass.class).error(ex);
} catch (SecurityException ex) {
LoggerFactory.getLogger(CompilerPass.class.getName()).error(null, ex);
LoggerFactory.getLogger(CompilerPass.class).error(ex);
}

return null;
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
/* SSS: Currently unused code. Will be useful for some SSA building algos. */
public class DominatorTreeBuilder extends CompilerPass {
private static int NULL = -1;
private static final Logger LOG = LoggerFactory.getLogger("DominatorTreeBuilder");
private static final Logger LOG = LoggerFactory.getLogger(DominatorTreeBuilder.class);

@Override
public String getLabel() {
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/representations/CFG.java
Original file line number Diff line number Diff line change
@@ -30,7 +30,7 @@ public enum EdgeType {
EXIT // Edge to dummy exit BB
}

private static final Logger LOG = LoggerFactory.getLogger("CFG");
private static final Logger LOG = LoggerFactory.getLogger(CFG.class);

private IRScope scope;
private Map<Label, BasicBlock> bbMap;
Original file line number Diff line number Diff line change
@@ -50,7 +50,7 @@
import java.util.Map;

public class IRRuntimeHelpers {
private static final Logger LOG = LoggerFactory.getLogger("IRRuntimeHelpers");
private static final Logger LOG = LoggerFactory.getLogger(IRRuntimeHelpers.class);

public static boolean inProfileMode() {
return RubyInstanceConfig.IR_PROFILE;
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/targets/Bootstrap.java
Original file line number Diff line number Diff line change
@@ -61,7 +61,7 @@ public class Bootstrap {
RubyObjectVar8.class,
RubyObjectVar9.class,
};
private static final Logger LOG = LoggerFactory.getLogger("Bootstrap");
private static final Logger LOG = LoggerFactory.getLogger(Bootstrap.class);
static final Lookup LOOKUP = MethodHandles.lookup();

public static CallSite string(Lookup lookup, String name, MethodType type, String value, String encodingName, int cr) {
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/targets/InvokeSite.java
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@ public abstract class InvokeSite extends MutableCallSite {
private boolean boundOnce;
CacheEntry cache = CacheEntry.NULL_CACHE;

private static final Logger LOG = LoggerFactory.getLogger("InvokeSite");
private static final Logger LOG = LoggerFactory.getLogger(InvokeSite.class);

public String name() {
return methodName;
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/ir/targets/JVM.java
Original file line number Diff line number Diff line change
@@ -25,7 +25,7 @@
// This class represents JVM as the target of compilation
// and outputs bytecode
public abstract class JVM {
private static final Logger LOG = LoggerFactory.getLogger("IRBuilder");
//private static final Logger LOG = LoggerFactory.getLogger(JVM.class);

Stack<ClassData> clsStack = new Stack();
ClassWriter writer;
4 changes: 2 additions & 2 deletions core/src/main/java/org/jruby/ir/targets/JVMVisitor.java
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@
*/
public class JVMVisitor extends IRVisitor {

private static final Logger LOG = LoggerFactory.getLogger("JVMVisitor");
private static final Logger LOG = LoggerFactory.getLogger(JVMVisitor.class);
public static final String DYNAMIC_SCOPE = "$dynamicScope";
private static final boolean DEBUG = false;
public static final String BLOCK_ARG_NAME = "blockArg";
@@ -895,7 +895,7 @@ public void CallInstr(CallInstr callInstr) {
if (callInstr.getCallSite() instanceof RefinedCachingCallSite) {
throw new NotCompilableException("refinements are unsupported in JIT");
}

IRBytecodeAdapter m = jvmMethod();
String name = callInstr.getName();
Operand[] args = callInstr.getCallArgs();
Original file line number Diff line number Diff line change
@@ -41,7 +41,7 @@ public abstract class Initializer {
protected final JavaSupport javaSupport;
protected final Class javaClass;

private static final Logger LOG = LoggerFactory.getLogger("Initializer");
private static final Logger LOG = LoggerFactory.getLogger(Initializer.class);

private static final int ACC_BRIDGE = 0x00000040;

Original file line number Diff line number Diff line change
@@ -62,7 +62,7 @@
import org.objectweb.asm.commons.GeneratorAdapter;

public class JavaProxyClassFactory {
private static final Logger LOG = LoggerFactory.getLogger("JavaProxyClassFactory");
private static final Logger LOG = LoggerFactory.getLogger(JavaProxyClassFactory.class);

static final Type[] EMPTY_TYPE_ARRAY = new Type[0];

72 changes: 36 additions & 36 deletions core/src/main/java/org/jruby/javasupport/util/ObjectProxyCache.java
Original file line number Diff line number Diff line change
@@ -14,65 +14,65 @@
* Maps Java objects to their proxies. Combines elements of WeakHashMap and
* ConcurrentHashMap to permit unsynchronized reads. May be configured to
* use either Weak (the default) or Soft references.<p>
*
*
* Note that both Java objects and their proxies are held by weak/soft
* references; because proxies (currently) keep strong references to their
* Java objects, if we kept strong references to them the Java objects would
* never be gc'ed. This presents a problem in the case where a user passes
* a Rubified Java object out to Java but keeps no reference in Ruby to the
* a Rubified Java object out to Java but keeps no reference in Ruby to the
* proxy; if the object is returned to Ruby after its proxy has been gc'ed,
* a new (and possibly very wrong, in the case of JRuby-defined subclasses)
* proxy will be created. Use of soft references may help reduce the
* likelihood of this occurring; users may be advised to keep Ruby-side
* references to prevent it occurring altogether.
*
*
* @author <a href="mailto:bill.dortch@gmail.com">Bill Dortch</a>
*
*
*/
public abstract class ObjectProxyCache<T,A> {

private static final Logger LOG = LoggerFactory.getLogger("ObjectProxyCache");
private static final Logger LOG = LoggerFactory.getLogger(ObjectProxyCache.class);

public static enum ReferenceType { WEAK, SOFT }

private static final int DEFAULT_SEGMENTS = 16; // must be power of 2
private static final int DEFAULT_SEGMENT_SIZE = 8; // must be power of 2
private static final float DEFAULT_LOAD_FACTOR = 0.75f;
private static final int MAX_CAPACITY = 1 << 30;
private static final int MAX_SEGMENTS = 1 << 16;
private static final int VULTURE_RUN_FREQ_SECONDS = 5;

private static int _nextId = 0;

private static synchronized int nextId() {
return ++_nextId;
}


private final ReferenceType referenceType;
private final Segment<T,A>[] segments;
private final int segmentShift;
private final int segmentMask;
private Thread vulture;
private final int id;

public ObjectProxyCache() {
this(DEFAULT_SEGMENTS, DEFAULT_SEGMENT_SIZE, ReferenceType.WEAK);
}

public ObjectProxyCache(ReferenceType refType) {
this(DEFAULT_SEGMENTS, DEFAULT_SEGMENT_SIZE, refType);
}


public ObjectProxyCache(int numSegments, int initialSegCapacity, ReferenceType refType) {
if (numSegments <= 0 || initialSegCapacity <= 0 || refType == null) {
throw new IllegalArgumentException();
}
this.id = nextId();
this.referenceType = refType;
if (numSegments > MAX_SEGMENTS) numSegments = MAX_SEGMENTS;

// Find power-of-two sizes best matching arguments
int sshift = 0;
int ssize = 1;
@@ -81,18 +81,18 @@ public ObjectProxyCache(int numSegments, int initialSegCapacity, ReferenceType r
ssize <<= 1;
}
// note segmentShift differs from ConcurrentHashMap's calculation due to
// issues with System.identityHashCode (upper n bits always 0, at least
// issues with System.identityHashCode (upper n bits always 0, at least
// under Java 1.6 / WinXP)
this.segmentShift = 24 - sshift;
this.segmentMask = ssize - 1;
this.segments = Segment.newArray(ssize);

if (initialSegCapacity > MAX_CAPACITY) {
initialSegCapacity = MAX_CAPACITY;
}
int cap = 1;
while (cap < initialSegCapacity) cap <<= 1;

for (int i = ssize; --i >= 0; ) {
segments[i] = new Segment<T,A>(cap, this);
}
@@ -138,38 +138,38 @@ public void run() {
this.vulture = null;
}


// FIXME: vulture daemon thread prevents finalization,
// find alternative approach.
// vulture.start();

// System.err.println("***ObjectProxyCache " + id + " started at "+ new java.util.Date());
}

// protected void finalize() throws Throwable {
// System.err.println("***ObjectProxyCache " + id + " finalized at "+ new java.util.Date());
// }

public abstract T allocateProxy(Object javaObject, A allocator);

public T get(Object javaObject) {
if (javaObject == null) return null;
int hash = hash(javaObject);
return segmentFor(hash).get(javaObject, hash);
}

public T getOrCreate(Object javaObject, A allocator) {
if (javaObject == null || allocator == null) return null;
int hash = hash(javaObject);
return segmentFor(hash).getOrCreate(javaObject, hash, allocator);
}

public void put(Object javaObject, T proxy) {
if (javaObject == null || proxy == null) return;
int hash = hash(javaObject);
segmentFor(hash).put(javaObject, hash, proxy);
}

private static int hash(Object javaObject) {
int h = System.identityHashCode(javaObject);
h ^= (h >>> 20) ^ (h >>> 12);
@@ -179,13 +179,13 @@ private static int hash(Object javaObject) {
private Segment<T,A> segmentFor(int hash) {
return segments[(hash >>> segmentShift) & segmentMask];
}

/**
* Returns the approximate size (elements in use) of the cache. The
* sizes of the segments are summed. No effort is made to synchronize
* across segments, so the value returned may differ from the actual
* size at any point in time.
*
*
* @return
*/
public int size() {
@@ -195,7 +195,7 @@ public int size() {
}
return size;
}

public String stats() {
StringBuilder b = new StringBuilder();
int n = 0;
@@ -221,7 +221,7 @@ public String stats() {
.append(" alloc: ").append(alloc).append("\n");
return b.toString();
}

// EntryRefs include hash with key to facilitate lookup by Segment#expunge
// after ref is removed from ReferenceQueue
private static interface EntryRef<T> {
@@ -261,7 +261,7 @@ static class Entry<T> {
final int hash;
final EntryRef<T> proxyRef;
final Entry<T> next;

Entry(Object object, int hash, T proxy, ReferenceType type, Entry<T> next, ReferenceQueue<Object> queue) {
this.hash = hash;
this.next = next;
@@ -277,21 +277,21 @@ static class Entry<T> {
this.proxyRef = new SoftEntryRef<T>(hash, proxy, queue);
}
}

// ctor used by remove/rehash
Entry(EntryRef<Object> objectRef, int hash, EntryRef<T> proxyRef, Entry<T> next) {
this.objectRef = objectRef;
this.hash = hash;
this.proxyRef = proxyRef;
this.next = next;
}

@SuppressWarnings("unchecked")
static final <T> Entry<T>[] newArray(int size) {
return new Entry[size];
}
}

// lame generics issues: making Segment class static and manually
// inserting cache reference to work around various problems generically
// referencing methods/vars across classes.
@@ -308,7 +308,7 @@ static class Segment<T,A> extends ReentrantLock {
entryTable = Entry.newArray(capacity);
this.cache = cache;
}

// must be called under lock
private void expunge() {
Entry<T>[] table = entryTable;
@@ -327,7 +327,7 @@ private void expunge() {
}
}
}

// must be called under lock
private void remove(Entry<T>[] table, int hash, Entry<T> e) {
int index = hash & (table.length - 1);
@@ -476,7 +476,7 @@ T getOrCreate(Object object, int hash, A allocator) {
unlock();
}
}

T get(Object object, int hash) {
Entry<T>[] table;
for (Entry<T> e = (table = entryTable)[hash & table.length - 1]; e != null; e = e.next) {
20 changes: 10 additions & 10 deletions core/src/main/java/org/jruby/management/BeanManagerImpl.java
Original file line number Diff line number Diff line change
@@ -20,36 +20,36 @@

public class BeanManagerImpl implements BeanManager {

private static final Logger LOG = LoggerFactory.getLogger("BeanManagerImpl");
private static final Logger LOG = LoggerFactory.getLogger(BeanManagerImpl.class);

private static final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyyMMddHHmmssSSS");

public final String base;

private final boolean managementEnabled;

public BeanManagerImpl(Ruby ruby, boolean managementEnabled) {
this.managementEnabled = managementEnabled;
this.base = "org.jruby:type=Runtime,name=" + FORMAT.format(new Date()) +
ruby.getRuntimeNumber() + ",";
}

public void register(JITCompilerMBean jitCompiler) {
if (managementEnabled) register(base + "service=JITCompiler", jitCompiler);
}

public void register(ConfigMBean config) {
if (managementEnabled) register(base + "service=Config", config);
}

public void register(ParserStatsMBean parserStats) {
if (managementEnabled) register(base + "service=ParserStats", parserStats);
}

public void register(MethodCacheMBean methodCache) {
if (managementEnabled) register(base + "service=MethodCache", methodCache);
}

public void register(Runtime runtime) {
if (managementEnabled) register(base + "service=Runtime", runtime);
}
@@ -94,7 +94,7 @@ public boolean tryRestartAgent() {
private void register(String name, Object bean) {
try {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

ObjectName beanName = new ObjectName(name);
mbs.registerMBean(bean, beanName);
} catch (InstanceAlreadyExistsException ex) {
@@ -123,7 +123,7 @@ private void register(String name, Object bean) {
private void unregister(String name) {
try {
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

ObjectName beanName = new ObjectName(name);
mbs.unregisterMBean(beanName);
} catch (InstanceNotFoundException ex) {
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
import java.io.ByteArrayOutputStream;

public class InterpretedIRBlockBody extends IRBlockBody implements Compilable<InterpreterContext> {
private static final Logger LOG = LoggerFactory.getLogger("InterpretedIRBlockBody");
private static final Logger LOG = LoggerFactory.getLogger(InterpretedIRBlockBody.class);
protected boolean pushScope;
protected boolean reuseParentScope;
private boolean displayedCFG = false; // FIXME: Remove when we find nicer way of logging CFG
24 changes: 12 additions & 12 deletions core/src/main/java/org/jruby/runtime/MethodIndex.java
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@
*
* Copyright (C) 2006-2007 Thomas E Enebo <enebo@acm.org>
* Copyright (C) 2006-2007 Charles Nutter <headius@headius.com>
*
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
@@ -67,7 +67,7 @@
public class MethodIndex {
private static final boolean DEBUG = false;

private static final Logger LOG = LoggerFactory.getLogger("MethodIndex");
private static final Logger LOG = LoggerFactory.getLogger(MethodIndex.class);

@Deprecated
public static final int NO_METHOD = MethodNames.DUMMY.ordinal();
@@ -104,7 +104,7 @@ public static CallSite getCallSite(String name) {

return new NormalCachingCallSite(name);
}

private static final Map<String, String> FIXNUM_OPS = new HashMap<String, String>();
private static final String[][] fastFixnumOps = {
{"+", "op_plus"},
@@ -122,11 +122,11 @@ public static CallSite getCallSite(String name) {
{">>", "op_rshift"},
{"<<", "op_lshift"}
};

static {
for (String[] fastOp : fastFixnumOps) FIXNUM_OPS.put(fastOp[0], fastOp[1]);
}

private static final Map<String, String> FLOAT_OPS = new HashMap<String, String>();
private static final String[][] fastFloatOps = {
{"+", "op_plus"},
@@ -139,15 +139,15 @@ public static CallSite getCallSite(String name) {
{">=", "op_ge"},
{"<=>", "op_cmp"}
};

static {
for (String[] fastOp : fastFloatOps) FLOAT_OPS.put(fastOp[0], fastOp[1]);
}

public static boolean hasFastFixnumOps(String name) {
return FIXNUM_OPS.containsKey(name);
}

public static String getFastFixnumOpsMethod(String name) {
return FIXNUM_OPS.get(name);
}
@@ -185,11 +185,11 @@ public static CallSite getFastFixnumOpsCallSite(String name) {

return new NormalCachingCallSite(name);
}

public static boolean hasFastFloatOps(String name) {
return FLOAT_OPS.containsKey(name);
}

public static String getFastFloatOpsMethod(String name) {
return FLOAT_OPS.get(name);
}
@@ -217,11 +217,11 @@ public static CallSite getFastFloatOpsCallSite(String name) {

return new NormalCachingCallSite(name);
}

public static CallSite getFunctionalCallSite(String name) {
return new FunctionalCachingCallSite(name);
}

public static CallSite getVariableCallSite(String name) {
return new VariableCachingCallSite(name);
}
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@
import java.io.ByteArrayOutputStream;

public class MixedModeIRBlockBody extends IRBlockBody implements Compilable<CompiledIRBlockBody> {
private static final Logger LOG = LoggerFactory.getLogger("InterpretedIRBlockBody");
private static final Logger LOG = LoggerFactory.getLogger(InterpretedIRBlockBody.class);
protected boolean pushScope;
protected boolean reuseParentScope;
private boolean displayedCFG = false; // FIXME: Remove when we find nicer way of logging CFG
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/runtime/ThreadContext.java
Original file line number Diff line number Diff line change
@@ -70,7 +70,7 @@

public final class ThreadContext {

private static final Logger LOG = LoggerFactory.getLogger("ThreadContext");
private static final Logger LOG = LoggerFactory.getLogger(ThreadContext.class);

public static ThreadContext newContext(Ruby runtime) {
return new ThreadContext(runtime);
72 changes: 50 additions & 22 deletions core/src/main/java/org/jruby/runtime/backtrace/TraceType.java
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@

public class TraceType {

private static final Logger LOG = LoggerFactory.getLogger("TraceType");
private static final Logger LOG = LoggerFactory.getLogger(TraceType.class);

private final Gather gather;
private final Format format;
@@ -64,13 +64,21 @@ public String printBacktrace(RubyException exception, boolean console) {

public static void logBacktrace(RubyStackTraceElement[] trace) {
if (trace == null) trace = RubyStackTraceElement.EMPTY_ARRAY;
final StringBuilder buffer = new StringBuilder(128);

final StringBuilder buffer = new StringBuilder(64 + trace.length * 48);

buffer.append("Backtrace generated:\n");

renderBacktraceJRuby(trace, buffer, false);
final int len = buffer.length();
if ( len > 0 && buffer.charAt(len - 1) == '\n' ) {
buffer.setLength(len - 1); // remove last '\n'
}
LOG.info("Backtrace generated:\n{}", buffer);

// NOTE: other logXxx method do not remove the new-line
// ... but if this is desired they should do so as well
//final int len = buffer.length();
//if ( len > 0 && buffer.charAt(len - 1) == '\n' ) {
// buffer.setLength(len - 1); // remove last '\n'
//}

LOG.info(buffer.toString());
}

public static void logException(RubyException exception) {
@@ -90,7 +98,16 @@ public static void dumpBacktrace(RubyException exception) {
}

public static void logCaller(RubyArray trace) {
LOG.info("Caller backtrace generated:\n{}", trace);
StringBuilder buffer = new StringBuilder(64 + trace.size() * 48);

buffer.append("Caller backtrace generated:\n");

for (int i = 0; i < trace.size(); i++) {
// elements are already rendered as its an Array<RubyString>
buffer.append(" ").append(trace.eltInternal(i)).append('\n');
}

LOG.info(buffer.toString());
}

/**
@@ -101,7 +118,19 @@ public static void dumpCaller(RubyArray trace) {
}

public static void logCaller(RubyStackTraceElement[] trace) {
LOG.info("Caller backtrace generated:\n{}", Arrays.toString(trace));
if (trace == null) trace = RubyStackTraceElement.EMPTY_ARRAY;

LOG.info( formatWithMRIBacktrace("Caller backtrace generated:\n", trace).toString() );
}

private static StringBuilder formatWithMRIBacktrace(final String message, RubyStackTraceElement[] trace) {
StringBuilder buffer = new StringBuilder(64 + trace.length * 48);

buffer.append(message);

renderBacktraceMRI(trace, " ", buffer, false);

return buffer;
}

/**
@@ -112,7 +141,9 @@ public static void dumpCaller(RubyStackTraceElement[] trace) {
}

public static void logWarning(RubyStackTraceElement[] trace) {
LOG.info("Warning backtrace generated:\n{}", Arrays.toString(trace));
if (trace == null) trace = RubyStackTraceElement.EMPTY_ARRAY;

LOG.info( formatWithMRIBacktrace("Warning backtrace generated:\n", trace).toString() );
}

/**
@@ -355,18 +386,13 @@ protected static String printBacktraceMRI(RubyException exception, boolean conso
private static final String CLEAR_COLOR = "\033[0m";

public static String printBacktraceJRuby(RubyStackTraceElement[] frames, String type, String message, boolean color) {
StringBuilder buffer = new StringBuilder();
if (frames == null) frames = RubyStackTraceElement.EMPTY_ARRAY;

// exception line
buffer
.append(type)
.append(": ")
.append(message)
.append('\n');
StringBuilder buffer = new StringBuilder(64 + frames.length * 48);

if (frames == null) frames = RubyStackTraceElement.EMPTY_ARRAY;
renderBacktraceJRuby(frames, buffer, color);
buffer.append(type).append(": ").append(message).append('\n');

renderBacktraceJRuby(frames, buffer, color);

return buffer.toString();
}
@@ -385,8 +411,6 @@ protected static String printBacktraceJRuby(RubyException exception, boolean con
String type = exception.getMetaClass().getName();

RubyStackTraceElement[] frames = exception.getBacktraceElements();
if (frames == null) frames = RubyStackTraceElement.EMPTY_ARRAY;

return printBacktraceJRuby(frames, type, message, color);
}

@@ -435,10 +459,14 @@ private static void renderBacktraceJRuby(RubyStackTraceElement[] frames, StringB
}

private static void renderBacktraceMRI(RubyStackTraceElement[] trace, StringBuilder buffer, boolean color) {
renderBacktraceMRI(trace, "", buffer, color);
}

private static void renderBacktraceMRI(RubyStackTraceElement[] trace, String linePrefix, StringBuilder buffer, boolean color) {
for (int i = 0; i < trace.length; i++) {
RubyStackTraceElement element = trace[i];

buffer
.append(linePrefix)
.append(element.getFileName())
.append(':')
.append(element.getLineNumber())
Original file line number Diff line number Diff line change
@@ -49,8 +49,8 @@
import org.jruby.util.log.LoggerFactory;

public class MathLinker {
private static final Logger LOG = LoggerFactory.getLogger("MathLinker");
private static final Logger LOG = LoggerFactory.getLogger(MathLinker.class);

public static CallSite fixnumOperatorBootstrap(Lookup lookup, String name, MethodType type, long value, String file, int line) throws NoSuchMethodException, IllegalAccessException {
String[] names = name.split(":");
String operator = JavaNameMangler.demangleMethodName(names[1]);
7 changes: 2 additions & 5 deletions core/src/main/java/org/jruby/runtime/load/DebugLog.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package org.jruby.runtime.load;

import org.jruby.RubyInstanceConfig;
import org.jruby.util.log.Logger;
import org.jruby.util.log.LoggerFactory;

class DebugLog {
private static final Logger LOG = LoggerFactory.getLogger("LoadService");

private final String typeMessage;

@@ -15,13 +12,13 @@ private DebugLog(String typeMessage) {

public void logTry(String path) {
if (RubyInstanceConfig.DEBUG_LOAD_SERVICE) {
LOG.info("trying " + typeMessage + ": " + path);
LoadService.LOG.info("trying {}: {}", typeMessage, path);
}
}

public void logFound(String path) {
if (RubyInstanceConfig.DEBUG_LOAD_SERVICE) {
LOG.info("found " + typeMessage + ": " + path);
LoadService.LOG.info("found {}: {}", typeMessage, path);
}
}

16 changes: 7 additions & 9 deletions core/src/main/java/org/jruby/runtime/load/LoadService.java
Original file line number Diff line number Diff line change
@@ -139,7 +139,7 @@
* @author jpetersen
*/
public class LoadService {
private static final Logger LOG = LoggerFactory.getLogger("LoadService");
static final Logger LOG = LoggerFactory.getLogger(LoadService.class);

private final LoadTimer loadTimer;
private boolean canGetAbsolutePath = true;
@@ -568,14 +568,13 @@ private StringBuilder getIndentString() {
@Override
public long startLoad(String file) {
indent.incrementAndGet();
LOG.info(getIndentString() + "-> " + file);
LOG.info( "{}-> {}", getIndentString(), file );
return System.currentTimeMillis();
}

@Override
public void endLoad(String file, long startTime) {
LOG.info(getIndentString() + "<- " + file + " - "
+ (System.currentTimeMillis() - startTime) + "ms");
LOG.info( "{}<- {} - {}ms", getIndentString(), file, (System.currentTimeMillis() - startTime) );
indent.decrementAndGet();
}
}
@@ -955,14 +954,14 @@ protected void checkEmptyLoad(String file) throws RaiseException {
@Deprecated
protected final void debugLogTry(String what, String msg) {
if (RubyInstanceConfig.DEBUG_LOAD_SERVICE) {
LOG.info( "trying " + what + ": " + msg );
LOG.info( "trying {}: {}", what, msg );
}
}

@Deprecated
protected final void debugLogFound(String what, String msg) {
if (RubyInstanceConfig.DEBUG_LOAD_SERVICE) {
LOG.info( "found " + what + ": " + msg );
LOG.info( "found {}: {}", what, msg );
}
}

@@ -975,7 +974,7 @@ protected final void debugLogFound( LoadServiceResource resource ) {
} catch (IOException e) {
resourceUrl = e.getMessage();
}
LOG.info( "found: " + resourceUrl );
LOG.info( "found: {}", resourceUrl );
}
}

@@ -1333,8 +1332,7 @@ public JarFile getJarFile(String jarFileName) {
jarFiles.put(jarFileName, jarFile);
} catch (ZipException ignored) {
if (runtime.getInstanceConfig().isDebug()) {
LOG.info("ZipException trying to access " + jarFileName + ", stack trace follows:");
ignored.printStackTrace(runtime.getErr());
LOG.info("ZipException trying to access " + jarFileName, ignored);
}
} catch (FileNotFoundException ignored) {
} catch (IOException e) {
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/util/JRubyClassLoader.java
Original file line number Diff line number Diff line change
@@ -56,7 +56,7 @@
*/
public class JRubyClassLoader extends ClassDefiningJRubyClassLoader {

private static final Logger LOG = LoggerFactory.getLogger("JRubyClassLoader");
private static final Logger LOG = LoggerFactory.getLogger(JRubyClassLoader.class);

private Runnable unloader;

Original file line number Diff line number Diff line change
@@ -73,7 +73,7 @@
*/
@Deprecated
public class ChannelDescriptor {
private static final Logger LOG = LoggerFactory.getLogger("ChannelDescriptor");
private static final Logger LOG = LoggerFactory.getLogger(ChannelDescriptor.class);

/** Whether to log debugging information */
private static final boolean DEBUG = false;
2 changes: 1 addition & 1 deletion core/src/main/java/org/jruby/util/io/ChannelStream.java
Original file line number Diff line number Diff line change
@@ -63,7 +63,7 @@
@Deprecated
public class ChannelStream implements Stream, Finalizable {

private static final Logger LOG = LoggerFactory.getLogger("ChannelStream");
private static final Logger LOG = LoggerFactory.getLogger(ChannelStream.class);

private final static boolean DEBUG = false;

160 changes: 160 additions & 0 deletions core/src/main/java/org/jruby/util/log/JULLogger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
/***** BEGIN LICENSE BLOCK *****
* Version: EPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 1.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.eclipse.org/legal/epl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2015-2015 The JRuby Community (and contribs)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/
package org.jruby.util.log;

import java.util.logging.Level;

/**
* Logger which delegates to {@link java.util.logging.Logger}.
*
* @author kares
*/
public class JULLogger implements Logger {

private final java.util.logging.Logger logger; // our delegate

public JULLogger(final String loggerName) {
this( java.util.logging.Logger.getLogger(loggerName) );
}

public JULLogger(final Class<?> loggerClass) {
this( java.util.logging.Logger.getLogger(loggerClass.getName()) );
}

protected JULLogger(final java.util.logging.Logger logger) {
this.logger = logger;
}

public String getName() {
return logger.getName();
}

public void warn(String message, Object... args) {
log(Level.WARNING, adjustPattern(message), args);
}

public void warn(Throwable throwable) {
log(Level.WARNING, null, throwable);
}

public void warn(String message, Throwable throwable) {
log(Level.WARNING, message, throwable);
}

public void error(String message, Object... args) {
log(Level.SEVERE, adjustPattern(message), args);
}

public void error(Throwable throwable) {
log(Level.SEVERE, null, throwable);
}

public void error(String message, Throwable throwable) {
log(Level.SEVERE, message, throwable);
}

public void info(String message, Object... args) {
if (logger.isLoggable(Level.INFO)) {
log(Level.INFO, adjustPattern(message), args);
}
}

public void info(Throwable throwable) {
log(Level.INFO, null, throwable);
}

public void info(String message, Throwable throwable) {
log(Level.INFO, message, throwable);
}

public void debug(String message, Object... args) {
if (logger.isLoggable(Level.FINE)) {
log(Level.FINE, adjustPattern(message), args);
}
}

public void debug(Throwable throwable) {
log(Level.FINE, null, throwable);
}

public void debug(String message, Throwable throwable) {
log(Level.FINE, message, throwable);
}


protected void log(Level level, String message, Object... args) {
final String souceClass = null;
final String souceMethod = null;
logger.logp(level, souceClass, souceMethod, message, args);
}

protected void log(Level level, String message, Throwable ex) {
final String souceClass = null;
final String souceMethod = null;
logger.logp(level, souceClass, souceMethod, message, ex);
}

public boolean isDebugEnabled() {
return logger.isLoggable(Level.FINE);
}

public void setDebugEnable(boolean debug) {
logger.setLevel(debug ? Level.FINE : Level.INFO);
}

// adjust {} to JUL conventions e.g. "hello {} {}" -> "hello {0} {1}"
static String adjustPattern(final String messagePattern) {
if (messagePattern == null) return null;

StringBuilder julPattern = null;
final int len = messagePattern.length(); int last = 0; int counter = 0;
for ( int i = 0; i < len; i++ ) {
if ( messagePattern.charAt(i) == '{' &&
( i == 0 || (i > 0 && messagePattern.charAt(i - 1) != '\\' ) ) &&
( i < len - 1 && messagePattern.charAt(i + 1) == '}' ) ) {
if (julPattern == null) {
julPattern = new StringBuilder(len + 8);
}
julPattern.
append(messagePattern, last, i).
append('{').append(counter++).append('}');
last = i + 2;
}
}

if (julPattern != null) {
if (last < len) {
julPattern.append(messagePattern, last, len);
}
return julPattern.toString();
}

return messagePattern; // no {} place holders
}

}
110 changes: 82 additions & 28 deletions core/src/main/java/org/jruby/util/log/LoggerFactory.java
Original file line number Diff line number Diff line change
@@ -32,49 +32,103 @@

public class LoggerFactory {

private static final String LOGGER_CLASS = Options.LOGGER_CLASS.load();
private static final String BACKUP_LOGGER_CLASS = "org.jruby.util.log.StandardErrorLogger";
static final String LOGGER_CLASS = Options.LOGGER_CLASS.load();
static final String BACKUP_LOGGER_CLASS = "org.jruby.util.log.StandardErrorLogger";

static final Constructor<? extends Logger> LOGGER; // (Class)
static final Constructor<? extends Logger> LOGGER_OLD; // (String)

private static final Constructor<?> CTOR;
static {
Constructor<?> ctor;
Logger log;

LOGGER = resolveLoggerConstructor(LOGGER_CLASS, Class.class, true);
// due backwards compatibility (if someone implemented the Logger iface)
if ( LOGGER == null ) {
LOGGER_OLD = resolveLoggerConstructor(LOGGER_CLASS, String.class, false);
}
else {
LOGGER_OLD = resolveLoggerConstructor(LOGGER_CLASS, String.class, true);
}
}

static Constructor<? extends Logger> resolveLoggerConstructor(
final String className, final Class<?> paramType, boolean allowNoSuchMethod) {
Constructor<? extends Logger> loggerCtor;
final Object param = paramType == String.class ?
LoggerFactory.class.getSimpleName() : LoggerFactory.class;
try {
final Class<?> cls = Class.forName(LOGGER_CLASS);
ctor = cls.getDeclaredConstructor(String.class);
log = (Logger)ctor.newInstance("LoggerFactory");
} catch (Exception e1) {
@SuppressWarnings("unchecked")
Class<? extends Logger> klass = (Class<? extends Logger>) Class.forName(className);
loggerCtor = klass.getDeclaredConstructor(paramType);
loggerCtor.newInstance(param); // check its working
}
catch (Exception ex) {
if ( allowNoSuchMethod && ex instanceof NoSuchMethodException ) {
return null;
}
try {
final Class<?> cls = Class.forName(BACKUP_LOGGER_CLASS);
ctor = cls.getDeclaredConstructor(String.class);
log = (Logger)ctor.newInstance("LoggerFactory");

log.debug("failed to create logger \"" + LOGGER_CLASS + "\", using \"" + BACKUP_LOGGER_CLASS + "\"");
} catch (Exception e2) {
throw new IllegalStateException("unable to instantiate any logger", e1);
@SuppressWarnings("unchecked")
Class<? extends Logger> klass = (Class<? extends Logger>) Class.forName(BACKUP_LOGGER_CLASS);
loggerCtor = klass.getDeclaredConstructor(paramType);
Logger log = loggerCtor.newInstance(param);
// log failure to load passeed -Djruby.logger.class :
log.info("failed to create logger \"" + className + "\", using \"" + BACKUP_LOGGER_CLASS + "\"");
}
catch (Exception e2) {
throw new IllegalStateException("unable to instantiate any logger", ex);
}
}
return loggerCtor;
}

public static Logger getLogger(Class<?> loggerClass) {
if ( LOGGER == null ) {
return getLogger(loggerClass.getName());
}
try {
return LOGGER.newInstance(loggerClass);
}
catch (Exception ex) {
return getLoggerFallback(loggerClass, ex);
}
CTOR = ctor;
}

/**
* @deprecated prefer using {@link #getLogger(java.lang.Class)} if possible
*/
public static Logger getLogger(String loggerName) {
try {
Logger logger = (Logger) CTOR.newInstance(loggerName);
return logger;
} catch (Exception e) {
Throwable rootCause = e;
return LOGGER_OLD.newInstance(loggerName);
}
catch (Exception ex) {
return getLoggerFallback(loggerName, ex);
}
}

// Unwrap reflection exception wrappers
while (rootCause.getCause() != null) {
private static Logger getLoggerFallback(final String loggerName, final Exception ex) {
Throwable rootCause = ex;
// unwrap reflection exception wrappers
while (rootCause.getCause() != null) {
rootCause = rootCause.getCause();
}
}

if (rootCause instanceof SecurityException) {
if (rootCause instanceof SecurityException) {
return new StandardErrorLogger(loggerName);
}
}

throw new IllegalStateException("unable to instantiate logger", e);
throw new IllegalStateException("unable to instantiate logger", ex);
}

private static Logger getLoggerFallback(final Class loggerClass, final Exception ex) {
Throwable rootCause = ex;
// unwrap reflection exception wrappers
while (rootCause.getCause() != null) {
rootCause = rootCause.getCause();
}

if (rootCause instanceof SecurityException) {
return new StandardErrorLogger(loggerClass);
}

throw new IllegalStateException("unable to instantiate logger", ex);
}

}
198 changes: 198 additions & 0 deletions core/src/main/java/org/jruby/util/log/OutputStreamLogger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
/***** BEGIN LICENSE BLOCK *****
* Version: EPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 1.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.eclipse.org/legal/epl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2015-2015 The JRuby Community (and contribs)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/
package org.jruby.util.log;

import java.io.PrintStream;

import org.joda.time.DateTime;

/**
* Logger logging to an output (print) stream.
* @author kares
*/
public class OutputStreamLogger implements Logger {

private final String loggerName;
private boolean debug = false;
protected PrintStream stream; // volatile?

public OutputStreamLogger(String loggerName) {
this.loggerName = loggerName;
}

public OutputStreamLogger(String loggerName, PrintStream stream) {
this.loggerName = loggerName;
this.stream = stream;
}

public String getName() {
return loggerName;
}

public PrintStream getStream() {
return stream;
}

public void setStream(PrintStream stream) {
this.stream = stream;
}

public void warn(String message, Object... args) {
write(message, "WARN", args);
}

public void warn(Throwable throwable) {
write("", "WARN", throwable);
}

public void warn(String message, Throwable throwable) {
write(message, "WARN", throwable);
}

public void error(String message, Object... args) {
write(message, "ERROR", args);
}

public void error(Throwable throwable) {
write("", "ERROR", throwable);
}

public void error(String message, Throwable throwable) {
write(message, "ERROR", throwable);
}

public void info(String message, Object... args) {
write(message, "INFO", args);
}

public void info(Throwable throwable) {
write("", "INFO", throwable);
}

public void info(String message, Throwable throwable) {
write(message, "INFO", throwable);
}

public void debug(String message, Object... args) {
if (debug) write(message, "DEBUG", args);
}

public void debug(Throwable throwable) {
if (debug) write("", "DEBUG", throwable);
}

public void debug(String message, Throwable throwable) {
if (debug) write(message, "DEBUG", throwable);
}

public boolean isDebugEnabled() {
return debug;
}

public void setDebugEnable(boolean debug) {
this.debug = debug;
}

protected void write(String message, String level, Object[] args) {
CharSequence suble = substitute(message, args);
stream.println(formatMessage(suble, level));
}

protected void write(String message, String level, Throwable throwable) {
synchronized (stream) {
stream.println(formatMessage(message, level));
//if ( message == null || message.length() > 0 ) stream.print(' ');
writeStackTrace(stream, throwable);
}
}

protected static void writeStackTrace(PrintStream stream, Throwable throwable) {
if (throwable == null) {
throw new IllegalArgumentException("null throwable");
}

throwable.printStackTrace(stream);
}

protected String formatMessage(CharSequence message, String level) {
// 2015-11-04T11:29:41.759+01:00 [main] INFO SampleLogger : hello world
return new StringBuilder(64)
.append(new DateTime(System.currentTimeMillis()))
.append(' ')
.append('[').append(Thread.currentThread().getName()).append(']')
.append(' ')
.append(level)
.append(' ')
.append(loggerName)
.append(" : ")
.append(message)
.toString();
}

/**
* Message pattern {} substitution.
* @param messagePattern
* @param args
*/
static CharSequence substitute(final String messagePattern, Object... args) {
if (messagePattern == null) {
final StringBuilder msg = new StringBuilder();
for (int i = 0; i < args.length; i++) msg.append( args[i] );
return msg;
}

StringBuilder msg = null;
final int len = messagePattern.length(); int s = 0; int a = 0;
for ( int i = 0; i < len; i++ ) {
if ( messagePattern.charAt(i) == '{' &&
( i == 0 || (i > 0 && messagePattern.charAt(i - 1) != '\\' ) ) &&
( i < len - 1 && messagePattern.charAt(i + 1) == '}' ) ) {

if (msg == null) {
msg = new StringBuilder(len + 48);
}

msg.append(messagePattern, s, i); s = i + 2;

if ( a < args.length ) {
msg.append( args[a++] );
}
else { // invalid e.g. ("hello {} {}", "world")
msg.append( "{!abs-arg!}" ); // absent argument
}
}
}

if ( msg != null ) {
if ( s < len ) msg.append(messagePattern, s, len);
return msg;
}
return messagePattern; // no substitution place-holders
}

}
38 changes: 0 additions & 38 deletions core/src/main/java/org/jruby/util/log/ParameterizedWriter.java

This file was deleted.

110 changes: 110 additions & 0 deletions core/src/main/java/org/jruby/util/log/SLF4JLogger.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/***** BEGIN LICENSE BLOCK *****
* Version: EPL 1.0/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Eclipse Public
* License Version 1.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.eclipse.org/legal/epl-v10.html
*
* Software distributed under the License is distributed on an "AS
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2015-2015 The JRuby Community (and contribs)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
* or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the EPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the EPL, the GPL or the LGPL.
***** END LICENSE BLOCK *****/
package org.jruby.util.log;

/**
* Using SLF4J API as a logging backend.
* @author kares
*/
public class SLF4JLogger implements Logger {

private final org.slf4j.Logger logger;

public SLF4JLogger(final String loggerName) {
this( org.slf4j.LoggerFactory.getLogger(loggerName) );
}

public SLF4JLogger(final Class<?> loggerClass) {
this( org.slf4j.LoggerFactory.getLogger(loggerClass) );
}

protected SLF4JLogger(final org.slf4j.Logger logger) {
this.logger = logger;
}

public String getName() {
return logger.getName();
}

public void warn(String message, Object... args) {
logger.warn(message, args);
}

public void warn(Throwable throwable) {
logger.warn("", throwable);
}

public void warn(String message, Throwable throwable) {
logger.warn(message, throwable);
}

public void error(String message, Object... args) {
logger.error(message, args);
}

public void error(Throwable throwable) {
logger.error("", throwable);
}

public void error(String message, Throwable throwable) {
logger.error(message, throwable);
}

public void info(String message, Object... args) {
logger.info(message, args);
}

public void info(Throwable throwable) {
logger.info("", throwable);
}

public void info(String message, Throwable throwable) {
logger.info(message, throwable);
}

public void debug(String message, Object... args) {
logger.debug(message, args);
}

public void debug(Throwable throwable) {
logger.debug("", throwable);
}

public void debug(String message, Throwable throwable) {
logger.debug(message, throwable);
}

public boolean isDebugEnabled() {
return logger.isDebugEnabled();
}

public void setDebugEnable(boolean debug) {
// no-op ignore
}

}
121 changes: 27 additions & 94 deletions core/src/main/java/org/jruby/util/log/StandardErrorLogger.java
Original file line number Diff line number Diff line change
@@ -11,7 +11,7 @@
* implied. See the License for the specific language governing
* rights and limitations under the License.
*
* Copyright (C) 2001-2011 The JRuby Community (and contribs)
* Copyright (C) 2001-2015 The JRuby Community (and contribs)
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@@ -29,112 +29,45 @@

import java.io.PrintStream;

import org.joda.time.DateTime;

public class StandardErrorLogger implements Logger {

private final String loggerName;
private boolean debug = false;
private ParameterizedWriter writer;
/**
* Default JRuby logger implementation, using {@link System.err}.
*/
public class StandardErrorLogger extends OutputStreamLogger {

public StandardErrorLogger(String loggerName) {
this.loggerName = loggerName;
this.writer = new ParameterizedWriter(System.err);
}

public StandardErrorLogger(String loggerName, PrintStream stream) {
this.loggerName = loggerName;
this.writer = new ParameterizedWriter(stream);
}

public String getName() {
return loggerName;
}

public void warn(String message, Object... args) {
write(message, args);
super(loggerName);
}

public void warn(Throwable throwable) {
writeStackTrace(throwable);
public StandardErrorLogger(Class<?> loggerClass) {
super(loggerClass.getSimpleName());
}

public void warn(String message, Throwable throwable) {
write(message, throwable);
}

public void error(String message, Object... args) {
write(message, args);
}

public void error(Throwable throwable) {
writeStackTrace(throwable);
}

public void error(String message, Throwable throwable) {
write(message, throwable);
}

public void info(String message, Object... args) {
write(message, args);
}

public void info(Throwable throwable) {
writeStackTrace(throwable);
public StandardErrorLogger(String loggerName, PrintStream stream) {
super(loggerName, stream);
}

public void info(String message, Throwable throwable) {
write(message, throwable);
}
@Override
protected void write(String message, String level, Object[] args) {
// NOTE: stream is intentionally not set to System.err
// thus when its programatically redirected it works !
PrintStream stream = this.stream;
if ( stream == null ) stream = System.err;

public void debug(String message, Object... args) {
if (debug) {
write(message, args);
}
CharSequence suble = substitute(message, args);
stream.println(formatMessage(suble, level));
}

public void debug(Throwable throwable) {
if (debug) {
writeStackTrace(throwable);
}
}
@Override
protected void write(String message, String level, Throwable throwable) {
// NOTE: stream is intentionally not set to System.err
// thus when its programatically redirected it works !
PrintStream stream = this.stream;
if ( stream == null ) stream = System.err;

public void debug(String message, Throwable throwable) {
if (debug) {
write(message, throwable);
synchronized (stream) {
stream.println(formatMessage(message, level));
writeStackTrace(stream, throwable);
}
}

public boolean isDebugEnabled() {
return debug;
}

public void setDebugEnable(boolean debug) {
this.debug = debug;
}

private void write(String message, Object[] args) {
writer.write(format(message), args);
}

private void write(String message, Throwable throwable) {
writer.write(format(message));
writeStackTrace(throwable);
}

private void writeStackTrace(Throwable throwable) {
throwable.printStackTrace(writer.getStream());
}

private String format(String message){
StringBuilder sb = new StringBuilder();
sb
.append(new DateTime(System.currentTimeMillis()).toString())
.append(": ")
.append(loggerName)
.append(": ")
.append(message);
return sb.toString();
}

}
4 changes: 2 additions & 2 deletions core/src/test/java/org/jruby/test/MainTestSuite.java
Original file line number Diff line number Diff line change
@@ -44,7 +44,7 @@
import org.jruby.util.JRubyThreadContextTest;
import org.jruby.util.ShellLauncherTest;
import org.jruby.util.RubyTimeOutputFormatterTest;
import org.jruby.util.log.ParameterizedWriterTest;
import org.jruby.util.log.ParameterSubstitutionTest;
import org.jruby.util.log.StandardErrorLoggerTest;

/**
@@ -89,7 +89,7 @@ public static Test suite() throws Throwable {
suite.addTestSuite(TestRubyString.class);
suite.addTestSuite(TestRubyNKF.class);
suite.addTestSuite(StandardErrorLoggerTest.class);
suite.addTestSuite(ParameterizedWriterTest.class);
suite.addTestSuite(ParameterSubstitutionTest.class);
suite.addTestSuite(TestRubyRational.class);
suite.addTestSuite(TestRecursiveCheck.class);
suite.addTestSuite(TestEncodingAPI.class);
225 changes: 225 additions & 0 deletions core/src/test/java/org/jruby/util/log/LoggerFactoryTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
/*
* Copyright (c) 2015 JRuby.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* JRuby - initial API and implementation and/or initial documentation
*/
package org.jruby.util.log;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

import org.junit.After;
import org.junit.Test;
import static org.junit.Assert.*;

/**
* @author kares
*/
public class LoggerFactoryTest {

@Test
public void hasCorrectBackupLoggerClassName() {
assertEquals( StandardErrorLogger.class.getName(), LoggerFactory.BACKUP_LOGGER_CLASS );
}

@Test
@SuppressWarnings("deprecation")
public void usesStandardErrorLoggerByDefault() {
if ( LoggerFactory.LOGGER_CLASS != null ) return; // skip test

Logger logger = LoggerFactory.getLogger(LoggerFactoryTest.class);
assertTrue( logger instanceof StandardErrorLogger );
assertFalse( logger.isDebugEnabled() );
logger.debug("not-logged", new IllegalStateException("if you're reading this - smt is BAD"));
// try if it works without throwing :
logger.info("hello {}", "world");

logger = LoggerFactory.getLogger("LoggerFactoryTest");
assertTrue( logger instanceof StandardErrorLogger );
}

@Test
public void usingJULLogger() throws Exception {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
java.util.logging.Logger julLogger = java.util.logging.Logger.getLogger("JULLogger");
java.util.logging.SimpleFormatter fmt = new java.util.logging.SimpleFormatter() {

@Override
public synchronized String format(java.util.logging.LogRecord record) {
final String format = "%2$s %4$s: %5$s%6$s%n";
String source;
if (record.getSourceClassName() != null) {
source = record.getSourceClassName();
if (record.getSourceMethodName() != null) {
source += " " + record.getSourceMethodName();
}
} else {
source = record.getLoggerName();
}
String message = formatMessage(record);
String throwable = "";
if (record.getThrown() != null) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.println();
record.getThrown().printStackTrace(pw);
pw.close();
throwable = sw.toString();
}
return String.format(format,
"", // no timestamp
source,
record.getLoggerName(),
record.getLevel().getLocalizedName(),
message,
throwable);
}

};
java.util.logging.StreamHandler handler = new java.util.logging.StreamHandler(out, fmt);
handler.setLevel(java.util.logging.Level.ALL);
julLogger.addHandler(handler);
julLogger.setUseParentHandlers(false);

julLogger.setLevel(java.util.logging.Level.INFO);

changeLoggerImpl(JULLogger.class);

Logger logger = LoggerFactory.getLogger("JULLogger");
assertFalse( logger.isDebugEnabled() );

logger.debug("ignored debug stuff");
logger.debug("more ignored debug stuff {}", 10);
handler.flush();
assertEquals("", out.toString());

String log = "";

logger.info("logged at info level");
handler.flush();
assertEquals(log += "JULLogger INFO: logged at info level\n", out.toString());

logger.warn("logged at {} {}", "warn", new StringBuilder("level"));
handler.flush();
assertEquals(log += "JULLogger WARNING: logged at warn level\n", out.toString());

julLogger.setLevel(java.util.logging.Level.WARNING);

logger.info("more at info level {}", 'z');
handler.flush(); assertEquals(log, out.toString());
logger.info("even more at info level", new RuntimeException("ex"));
handler.flush(); assertEquals(log, out.toString());

logger.error("bad news", new RuntimeException("exception happened"));
handler.flush();
assertStartsWith(log += "JULLogger SEVERE: bad news\njava.lang.RuntimeException: exception happened", out.toString());
}

@Test
public void usingSLF4JLogger() throws Exception {
final PrintStream defaultErr = System.err;
try {
System.setProperty("org.slf4j.simpleLogger.logFile", "System.err");
System.setProperty("org.slf4j.simpleLogger.dateTimeFormat", "yyyy");
System.setProperty("org.slf4j.simpleLogger.showThreadName", "false");

final ByteArrayOutputStream out = new ByteArrayOutputStream();
final PrintStream printOut = new PrintStream(out);
System.setErr(printOut);

//org.slf4j.Logger slf4jLogger = org.sqlf4j.LoggerFactory.getLogger("SLF4JLogger");

changeLoggerImpl(SLF4JLogger.class);

Logger logger = LoggerFactory.getLogger(SLF4JLogger.class);
assertFalse( logger.isDebugEnabled() );

logger.debug("ignored debug stuff");
logger.debug("more ignored debug stuff {}", 10);
printOut.flush();
assertEquals("", out.toString());

String log = "";

logger.info("logged at info level");
printOut.flush();
assertEquals(log += "INFO org.jruby.util.log.SLF4JLogger - logged at info level\n", out.toString());

logger.warn("logged at {} {}", "warn", new StringBuilder("level"));
printOut.flush();
assertEquals(log += "WARN org.jruby.util.log.SLF4JLogger - logged at warn level\n", out.toString());

logger.debug("more debug", new RuntimeException("ex"));
printOut.flush(); assertEquals(log, out.toString());

logger.error("bad news", new RuntimeException("exception happened"));
printOut.flush();
assertStartsWith(log += "ERROR org.jruby.util.log.SLF4JLogger - bad news\njava.lang.RuntimeException: exception happened", out.toString());

}
finally {
System.setErr(defaultErr);
}
}

final static Constructor DEFAULT_LOGGER = LoggerFactory.LOGGER;
final static Constructor DEFAULT_LOGGER_OLD = LoggerFactory.LOGGER_OLD;

@After
public void restoreLoggerImpl() throws Exception {
if ( LoggerFactory.LOGGER != DEFAULT_LOGGER ) {
setLoggerImpl(DEFAULT_LOGGER, DEFAULT_LOGGER_OLD);
}
}

static void changeLoggerImpl(final Class<? extends Logger> type) throws NoSuchFieldException, IllegalAccessException {
final String klass = type.getName();
Constructor LOGGER = LoggerFactory.resolveLoggerConstructor(klass, Class.class, true);
Constructor LOGGER_OLD;
if ( LOGGER == null ) {
LOGGER_OLD = LoggerFactory.resolveLoggerConstructor(klass, String.class, false);
}
else {
LOGGER_OLD = LoggerFactory.resolveLoggerConstructor(klass, String.class, true);
}
setLoggerImpl( LOGGER, LOGGER_OLD );
}

static void setLoggerImpl(final Constructor logger, final Constructor loggerOld)
throws NoSuchFieldException, IllegalAccessException {
final Field LOGGER = LoggerFactory.class.getDeclaredField("LOGGER");
LOGGER.setAccessible(true);
changeModifiers(LOGGER, LOGGER.getModifiers() & (~Modifier.FINAL));

LOGGER.set(null, logger);

final Field LOGGER_OLD = LoggerFactory.class.getDeclaredField("LOGGER_OLD");
LOGGER_OLD.setAccessible(true);
changeModifiers(LOGGER_OLD, LOGGER_OLD.getModifiers() & (~Modifier.FINAL));

LOGGER_OLD.set(null, loggerOld);
}

private static void changeModifiers(final Field field, final int mod)
throws NoSuchFieldException, IllegalAccessException {
Field modifiers = Field.class.getDeclaredField("modifiers");
modifiers.setAccessible(true);
modifiers.setInt(field, mod);
}

static void assertStartsWith(String expected, String actual) {
final String begPart = actual.substring(0, expected.length());
assertEquals("expected: \"" + actual + "\" to start with: \"" + expected + "\"", expected, begPart);
}

}
154 changes: 154 additions & 0 deletions core/src/test/java/org/jruby/util/log/OutputStreamLoggerTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/*
* Copyright (c) 2015 JRuby.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* JRuby - initial API and implementation and/or initial documentation
*/
package org.jruby.util.log;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;

import org.junit.Assert;
import org.junit.Test;
import org.junit.After;

/**
* @author kares
*/
public class OutputStreamLoggerTest extends junit.framework.TestCase {

static final String LINE_SEPARATOR = System.getProperty("line.separator");

protected final ByteArrayOutputStream baos = new ByteArrayOutputStream();
protected final PrintStream stream = new PrintStream(baos);

protected final Logger logger = newLogger();

protected Logger newLogger() {
return new OutputStreamLogger(OutputStreamLoggerTest.class.getSimpleName(), stream);
}

@After
public void resetStream() throws IOException {
baos.reset();
}

@Test
public void testPlainMessage() {
logger.info("test");
assertStreamEndsWith("test");
}

@Test
public void testMessageWithPlaceholder() {
logger.warn("hello {}", "world");
assertStreamEndsWith("hello world");
}

@Test
public void testMessageWithPlaceholders() {
logger.warn("{} {}", 1, new StringBuilder("23"));
assertStreamEndsWith("1 23\n", false);
}

@Test
public void testWithDebuggingDisabled() {
final boolean debug = logger.isDebugEnabled();
try {
logger.setDebugEnable(false);
logger.debug("debug-test-1");
logger.debug("debug-test-{}", 2);
logger.debug("debug-test-x", new RuntimeException());
assertStreamEmpty();
}
finally {
logger.setDebugEnable(debug);
}
}

@Test
public void testWithDebuggingEnabled() {
final boolean debug = logger.isDebugEnabled();
try {
logger.setDebugEnable(true);
String arg = null;
logger.debug("debug-test-{}", arg);
assertStreamNotEmpty();
assertStreamEndsWith("debug-test-null");
}
finally {
logger.setDebugEnable(debug);
}
}

@Test
public void testIncludesLevel() {
final boolean debug = logger.isDebugEnabled();
try {
logger.setDebugEnable(true);
logger.debug("{} message", "a debug");
assertStreamNotEmpty();
assertStreamEndsWith("DEBUG OutputStreamLoggerTest : a debug message");

logger.info("hello!");
assertStreamNotEmpty();
assertStreamEndsWith("INFO OutputStreamLoggerTest : hello!");

logger.warn("red-{}", "alert");
assertStreamNotEmpty();
assertStreamEndsWith("WARN OutputStreamLoggerTest : red-alert");
}
finally {
logger.setDebugEnable(debug);
}
}

@Test
public void testWithException() {
logger.error("debug-test-x", new RuntimeException("42"));
assertStreamNotEmpty();

assertStreamContains("debug-test-x\njava.lang.RuntimeException: 42");
// with stack trace :
assertStreamContains("at org.jruby.util.log.OutputStreamLoggerTest.testWithException");
}

protected void assertStreamEmpty() {
stream.flush();
Assert.assertEquals("", baos.toString());
}

protected void assertStreamNotEmpty() {
stream.flush();
Assert.assertNotEquals("", baos.toString());
}

protected void assertStreamEndsWith(String expected) {
assertStreamEndsWith(expected, true);
}

protected void assertStreamEndsWith(String expected, final boolean newLine) {
stream.flush();
if ( newLine ) expected = expected + LINE_SEPARATOR;

final String actual = baos.toString();
final String endPart = actual.substring(actual.length() - expected.length());

Assert.assertEquals("expected: \"" + actual + "\" to end with: \"" + expected + "\"", expected, endPart);
}

protected void assertStreamContains(String expected) {
stream.flush();

final String actual = baos.toString();

Assert.assertTrue("expected: \"" + actual + "\" to contain: \"" + expected + "\"", actual.contains(expected));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.jruby.util.log;

import junit.framework.TestCase;

import static org.jruby.util.log.OutputStreamLogger.substitute;

public class ParameterSubstitutionTest extends TestCase {

public void testWithNoPlaceholder() {
CharSequence actual = substitute("test");
assertEquals("test", actual.toString());
}

public void testWithEmptyString() {
CharSequence actual = substitute("");
assertEquals("", actual.toString());
}

public void testWithNonEmptyString() {
CharSequence actual = substitute(" ");
assertEquals(" ", actual.toString());
}

public void testWithEmptyStringAndArg() {
CharSequence actual = substitute("", "arg");
assertEquals("", actual.toString());
}

public void testWithJustOnePlaceholder() {
CharSequence actual = substitute("{}", "a");
assertEquals("a", actual.toString());
}

public void testWithOnePlaceholder() {
CharSequence actual = substitute("a {}", "test");
assertEquals("a test", actual.toString());
}

public void testWithTwoPlaceholders() {
CharSequence actual = substitute("{} and {}", "test1", "test2");
assertEquals("test1 and test2", actual.toString());
}

public void testWithPlaceholdersCallsToString() {
CharSequence actual = substitute("{} and {}", new StringBuilder("test"), new java.util.ArrayList());
assertEquals("test and []", actual.toString());
}

public void testWithTwoPlaceholdersAfterAnother() {
CharSequence actual = substitute("{}{}", "1", Integer.valueOf(2));
assertEquals("12", actual.toString());
}

public void testWithPlaceholdersAndNullArg() {
CharSequence actual = substitute("{} and {}", 0, null);
assertEquals("0 and null", actual.toString());

actual = substitute("the {} {}!{some}", null, null);
assertEquals("the null null!{some}", actual.toString());
}

public void testPlaceholderEscaping() {
CharSequence actual = substitute("\\{} & {}", 0, null);
assertEquals("\\{} & 0", actual.toString());
}

public void testMorePlaceholdersThanArgs() {
CharSequence actual = substitute("hello {}, {} and {}", 'A', 'B');
assertEquals("hello A, B and {!abs-arg!}", actual.toString());

String arg = null;
actual = substitute("{} {} {xxx}", arg);
assertEquals("null {!abs-arg!} {xxx}", actual.toString());
}

}
53 changes: 0 additions & 53 deletions core/src/test/java/org/jruby/util/log/ParameterizedWriterTest.java

This file was deleted.

103 changes: 78 additions & 25 deletions core/src/test/java/org/jruby/util/log/StandardErrorLoggerTest.java
Original file line number Diff line number Diff line change
@@ -1,41 +1,94 @@
package org.jruby.util.log;

import junit.framework.TestCase;
import org.junit.Assert;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;

public class StandardErrorLoggerTest extends TestCase {
import org.junit.Test;

public class StandardErrorLoggerTest extends OutputStreamLoggerTest {

private ByteArrayOutputStream baos;
private StandardErrorLogger logger;
private PrintStream stream;
private static final PrintStream defaultErr = System.err;

public void setUp() {
baos = new ByteArrayOutputStream();
stream = new PrintStream(baos);
logger = new StandardErrorLogger("test", stream);
protected Logger newLogger() {
return new StandardErrorLogger(OutputStreamLoggerTest.class.getSimpleName(), stream);
}

public void tearDown() throws IOException {
baos.reset();
baos.close();
@Test
public void testWithDebuggingDisabledUsingSystemErr() {
try {
System.setErr(stream);

StandardErrorLogger logger = new StandardErrorLogger("StandardErrorLoggerTest");

logger.setDebugEnable(false);
logger.debug("test");
stream.flush();
assertStreamEmpty();
}
finally {
System.setErr(defaultErr);
}
}

public void testWithDebuggingDisabled() {
logger.setDebugEnable(false);
logger.debug("test");
stream.flush();
Assert.assertEquals("", baos.toString());
@Test
public void testWithDebuggingEnabledUsingSystemErr() {
try {
System.setErr(stream);

StandardErrorLogger logger = new StandardErrorLogger("StandardErrorLoggerTest");

logger.setDebugEnable(true);
String arg = null;
logger.debug("debug-test-{}", arg);
assertStreamNotEmpty();
assertStreamEndsWith("debug-test-null");
}
finally {
System.setErr(defaultErr);
}
}

@Test
public void testIncludesLevelUsingSystemErr() {
try {
System.setErr(stream);

StandardErrorLogger logger = new StandardErrorLogger("StandardErrorLoggerTest");

logger.setDebugEnable(true);
logger.debug("{} message", "a debug");
assertStreamNotEmpty();
assertStreamEndsWith("DEBUG StandardErrorLoggerTest : a debug message");

logger.info("hello!");
assertStreamNotEmpty();
assertStreamEndsWith("INFO StandardErrorLoggerTest : hello!");

logger.warn("red-{}", "alert");
assertStreamNotEmpty();
assertStreamEndsWith("WARN StandardErrorLoggerTest : red-alert");
}
finally {
System.setErr(defaultErr);
}
}

@Override @Test
public void testWithException() {
logger.setDebugEnable(true);
logger.debug(new IllegalStateException());
stream.flush();
Assert.assertTrue(baos.toString().contains(IllegalStateException.class.getName()));
try {
System.setErr(stream);

StandardErrorLogger logger = new StandardErrorLogger("StandardErrorLoggerTest");

logger.error("debug-test-x", new RuntimeException("42"));
assertStreamNotEmpty();

assertStreamContains("debug-test-x\njava.lang.RuntimeException: 42");
// with stack trace :
assertStreamContains("at org.jruby.util.log.StandardErrorLoggerTest.testWithException");
}
finally {
System.setErr(defaultErr);
}
}

}

0 comments on commit a513b5c

Please sign in to comment.