Refactoring jetty-centralized-logger to be more real-world.

* Moving jetty specific pieces out to jetty-webapp-logging so that the
  core logging implementation can exist in places such as JVM endorsed
  library paths and still function, without bringin in all of Jetty in
  the process.
* Removing dependency on any jetty components from
  jetty-centralized-logging per reasons above.
* Establishing jetty-webapp-logging as central place to house the webapp
  logging integration bits and pieces.

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@883 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Joakim Erdfelt 2009-09-11 17:43:18 +00:00
parent 576ee80d2a
commit c148b97ffc
53 changed files with 1132 additions and 221 deletions

View File

@ -50,33 +50,11 @@
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-deploy</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.5.6</version>
</dependency>
<!--
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.5.6</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jul-to-slf4j</artifactId>
<version>1.5.6</version>
</dependency>
-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>jcl-over-slf4j</artifactId>

View File

@ -1,40 +0,0 @@
#!/bin/bash
M2REPO=$HOME/.m2/repository
function jettydep()
{
echo "$M2REPO/org/eclipse/jetty/$1/7.0.1-SNAPSHOT/$1-7.0.1-SNAPSHOT.jar"
}
function slf4jdep()
{
echo "$M2REPO/org/slf4j/$1/1.5.6/$1-1.5.6.jar"
}
CP="target/classes:target/test-classes"
CP="$CP:"`jettydep "jetty-util"`
CP="$CP:"`jettydep "jetty-io"`
CP="$CP:"`jettydep "jetty-http"`
CP="$CP:"`jettydep "jetty-xml"`
CP="$CP:"`jettydep "jetty-server"`
CP="$CP:"`jettydep "jetty-security"`
CP="$CP:"`jettydep "jetty-servlet"`
CP="$CP:"`jettydep "jetty-webapp"`
CP="$CP:"`jettydep "jetty-deploy"`
CP="$CP:"`jettydep "jetty-continuation"`
CP="$CP:$M2REPO/javax/servlet/servlet-api/2.5/servlet-api-2.5.jar"
CP="$CP:"`slf4jdep "slf4j-api"`
CP="$CP:"`slf4jdep "jcl-over-slf4j"`
CP="$CP:"`slf4jdep "log4j-over-slf4j"`
CP="$CP:$M2REPO/junit/junit/3.8.2/junit-3.8.2.jar"
TESTBASEDIR=`pwd`
EXTRA=""
# EXTRA="-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005"
java -cp $CP $EXTRA \
"-Dbasedir=$TESTBASEDIR" \
junit.textui.TestRunner \
org.eclipse.jetty.logging.CentralizedLoggingTest

View File

@ -33,6 +33,7 @@ public class CentralLoggerFactory implements ILoggerFactory
{
this.root = root;
this.loggers = new HashMap<String, CentralLogger>();
JavaUtilLoggingRouting.init();
}
public void setRoot(CentralLoggerConfig root)

View File

@ -13,89 +13,19 @@
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.logging;
package org.eclipse.jetty.logging.impl;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import org.eclipse.jetty.logging.impl.CentralLoggerConfig;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Slf4jLog;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* WebAppContext {@link Configuration} for Centralized Logging.
* Setup Routing in {@link java.util.logging.LogManager} to Centralized Logger.
*/
public class CentralizedWebAppLoggingConfiguration implements Configuration
public class JavaUtilLoggingRouting
{
private static boolean loggerConfigured = false;
public static CentralLoggerConfig getLoggerRoot()
public static void init()
{
loggerConfigured = true;
return org.slf4j.impl.StaticLoggerBinder.getSingleton().getRoot();
}
public static boolean isLoggerConfigured()
{
return loggerConfigured;
}
public static void setConfiguredLoggerRoot(CentralLoggerConfig root)
{
loggerConfigured = true;
org.slf4j.impl.StaticLoggerBinder.getSingleton().setRoot(root);
try
{
// Reset jetty logger.
Slf4jLog jettyLogger = new Slf4jLog();
Log.setLog(jettyLogger);
}
catch (Exception ignore)
{
// ignore
}
}
public static void setLoggerConfigurationFilename(String filename) throws IOException
{
FileInputStream stream = null;
try
{
stream = new FileInputStream(filename);
CentralLoggerConfig root = CentralLoggerConfig.load(stream);
setConfiguredLoggerRoot(root);
loggerConfigured = true;
}
finally
{
IO.close(stream);
}
}
public void configure(WebAppContext context) throws Exception
{
context.addSystemClass("org.apache.log4j.");
context.addSystemClass("org.slf4j.");
context.addSystemClass("org.apache.commons.logging.");
initializeJavaUtilLogRouting();
}
private static boolean javaUtilLoggingInitialized = false;
private static void initializeJavaUtilLogRouting()
{
if (javaUtilLoggingInitialized)
{
return;
}
// Get root logger.
java.util.logging.Logger rootLogger = java.util.logging.Logger.getLogger("");
@ -229,22 +159,5 @@ public class CentralizedWebAppLoggingConfiguration implements Configuration
// Tweak levels.
rootLogger.setLevel(java.util.logging.Level.ALL);
javaUtilLoggingInitialized = true;
}
public void deconfigure(WebAppContext context) throws Exception
{
/* do nothing */
}
public void postConfigure(WebAppContext context) throws Exception
{
/* do nothing */
}
public void preConfigure(WebAppContext context) throws Exception
{
/* do nothing */
}
}

View File

@ -13,7 +13,7 @@
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.logging;
package org.eclipse.jetty.logging.impl;
/**
* Basic System Property string expansion "${user.home}"

View File

@ -21,8 +21,7 @@ import java.io.IOException;
import java.io.PrintStream;
import java.util.TimeZone;
import org.eclipse.jetty.logging.PropertyExpansion;
import org.eclipse.jetty.util.RolloverFileOutputStream;
import org.eclipse.jetty.logging.impl.io.RolloverFileOutputStream;
/**
* Rolling File Appender

View File

@ -0,0 +1,119 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.logging.impl.io;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
/**
* Simplified IO for logging reasons only.
*/
public class LogIO
{
public static void close(InputStream stream)
{
try
{
if (stream != null)
stream.close();
}
catch (IOException ignore)
{
/* ignore */
}
}
public static void close(OutputStream stream)
{
try
{
if (stream != null)
stream.close();
}
catch (IOException ignore)
{
/* ignore */
}
}
public static void close(Reader reader)
{
try
{
if (reader != null)
reader.close();
}
catch (IOException ignore)
{
/* ignore */
}
}
public static void close(Writer writer)
{
try
{
if (writer != null)
writer.close();
}
catch (IOException ignore)
{
/* ignore */
}
}
public static void copy(Reader in, Writer out) throws IOException
{
final int bufferSize = 8096;
char buffer[] = new char[bufferSize];
int len = bufferSize;
if (out instanceof PrintWriter)
{
PrintWriter pout = (PrintWriter)out;
while (!pout.checkError())
{
len = in.read(buffer,0,bufferSize);
if (len == -1)
break;
out.write(buffer,0,len);
}
}
else
{
while (true)
{
len = in.read(buffer,0,bufferSize);
if (len == -1)
break;
out.write(buffer,0,len);
}
}
}
public static String toString(Reader in) throws IOException
{
StringWriter writer = new StringWriter();
copy(in,writer);
return writer.toString();
}
}

View File

@ -0,0 +1,330 @@
// ========================================================================
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.logging.impl.io;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;
/**
* Log specific RolloverFileOutputStream
*
* This output stream puts content in a file that is rolled over every 24 hours. The filename must include the string
* "yyyy_mm_dd", which is replaced with the actual date when creating and rolling over the file.
*
* Old files are retained for a number of days before being deleted.
*/
public class RolloverFileOutputStream extends FilterOutputStream
{
private static Timer __rollover;
final static String YYYY_MM_DD="yyyy_mm_dd";
final static String ROLLOVER_FILE_DATE_FORMAT = "yyyy_MM_dd";
final static String ROLLOVER_FILE_BACKUP_FORMAT = "HHmmssSSS";
final static int ROLLOVER_FILE_RETAIN_DAYS = 31;
private RollTask _rollTask;
private SimpleDateFormat _fileBackupFormat;
private SimpleDateFormat _fileDateFormat;
private String _filename;
private File _file;
private boolean _append;
private int _retainDays;
/* ------------------------------------------------------------ */
/**
* @param filename The filename must include the string "yyyy_mm_dd",
* which is replaced with the actual date when creating and rolling over the file.
* @throws IOException
*/
public RolloverFileOutputStream(String filename)
throws IOException
{
this(filename,true,ROLLOVER_FILE_RETAIN_DAYS);
}
/* ------------------------------------------------------------ */
/**
* @param filename The filename must include the string "yyyy_mm_dd",
* which is replaced with the actual date when creating and rolling over the file.
* @param append If true, existing files will be appended to.
* @throws IOException
*/
public RolloverFileOutputStream(String filename, boolean append)
throws IOException
{
this(filename,append,ROLLOVER_FILE_RETAIN_DAYS);
}
/* ------------------------------------------------------------ */
/**
* @param filename The filename must include the string "yyyy_mm_dd",
* which is replaced with the actual date when creating and rolling over the file.
* @param append If true, existing files will be appended to.
* @param retainDays The number of days to retain files before deleting them. 0 to retain forever.
* @throws IOException
*/
public RolloverFileOutputStream(String filename,
boolean append,
int retainDays)
throws IOException
{
this(filename,append,retainDays,TimeZone.getDefault());
}
/* ------------------------------------------------------------ */
/**
* @param filename The filename must include the string "yyyy_mm_dd",
* which is replaced with the actual date when creating and rolling over the file.
* @param append If true, existing files will be appended to.
* @param retainDays The number of days to retain files before deleting them. 0 to retain forever.
* @throws IOException
*/
public RolloverFileOutputStream(String filename,
boolean append,
int retainDays,
TimeZone zone)
throws IOException
{
this(filename,append,retainDays,zone,null,null);
}
/* ------------------------------------------------------------ */
/**
* @param filename The filename must include the string "yyyy_mm_dd",
* which is replaced with the actual date when creating and rolling over the file.
* @param append If true, existing files will be appended to.
* @param retainDays The number of days to retain files before deleting them. 0 to retain forever.
* @param dateFormat The format for the date file substitution. The default is "yyyy_MM_dd".
* @param backupFormat The format for the file extension of backup files. The default is "HHmmssSSS".
* @throws IOException
*/
public RolloverFileOutputStream(String filename,
boolean append,
int retainDays,
TimeZone zone,
String dateFormat,
String backupFormat)
throws IOException
{
super(null);
if (dateFormat==null)
dateFormat=ROLLOVER_FILE_DATE_FORMAT;
_fileDateFormat = new SimpleDateFormat(dateFormat);
if (backupFormat==null)
backupFormat=ROLLOVER_FILE_BACKUP_FORMAT;
_fileBackupFormat = new SimpleDateFormat(backupFormat);
_fileBackupFormat.setTimeZone(zone);
_fileDateFormat.setTimeZone(zone);
if (filename!=null)
{
filename=filename.trim();
if (filename.length()==0)
filename=null;
}
if (filename==null)
throw new IllegalArgumentException("Invalid filename");
_filename=filename;
_append=append;
_retainDays=retainDays;
setFile();
synchronized(RolloverFileOutputStream.class)
{
if (__rollover==null)
__rollover=new Timer(RolloverFileOutputStream.class.getName(),true);
_rollTask=new RollTask();
Calendar now = Calendar.getInstance();
now.setTimeZone(zone);
GregorianCalendar midnight =
new GregorianCalendar(now.get(Calendar.YEAR),
now.get(Calendar.MONTH),
now.get(Calendar.DAY_OF_MONTH),
23,0);
midnight.setTimeZone(zone);
midnight.add(Calendar.HOUR,1);
__rollover.scheduleAtFixedRate(_rollTask,midnight.getTime(),1000L*60*60*24);
}
}
/* ------------------------------------------------------------ */
public String getFilename()
{
return _filename;
}
/* ------------------------------------------------------------ */
public String getDatedFilename()
{
if (_file==null)
return null;
return _file.toString();
}
/* ------------------------------------------------------------ */
public int getRetainDays()
{
return _retainDays;
}
/* ------------------------------------------------------------ */
private synchronized void setFile()
throws IOException
{
// Check directory
File file = new File(_filename);
_filename=file.getCanonicalPath();
file=new File(_filename);
File dir= new File(file.getParent());
if (!dir.isDirectory() || !dir.canWrite())
throw new IOException("Cannot write log directory "+dir);
Date now=new Date();
// Is this a rollover file?
String filename=file.getName();
int i=filename.toLowerCase().indexOf(YYYY_MM_DD);
if (i>=0)
{
file=new File(dir,
filename.substring(0,i)+
_fileDateFormat.format(now)+
filename.substring(i+YYYY_MM_DD.length()));
}
if (file.exists()&&!file.canWrite())
throw new IOException("Cannot write log file "+file);
// Do we need to change the output stream?
if (out==null || !file.equals(_file))
{
// Yep
_file=file;
if (!_append && file.exists())
file.renameTo(new File(file.toString()+"."+_fileBackupFormat.format(now)));
OutputStream oldOut=out;
out=new FileOutputStream(file.toString(),_append);
if (oldOut!=null)
oldOut.close();
//if(log.isDebugEnabled())log.debug("Opened "+_file);
}
}
/* ------------------------------------------------------------ */
private void removeOldFiles()
{
if (_retainDays>0)
{
long now = System.currentTimeMillis();
File file= new File(_filename);
File dir = new File(file.getParent());
String fn=file.getName();
int s=fn.toLowerCase().indexOf(YYYY_MM_DD);
if (s<0)
return;
String prefix=fn.substring(0,s);
String suffix=fn.substring(s+YYYY_MM_DD.length());
String[] logList=dir.list();
for (int i=0;i<logList.length;i++)
{
fn = logList[i];
if(fn.startsWith(prefix)&&fn.indexOf(suffix,prefix.length())>=0)
{
File f = new File(dir,fn);
long date = f.lastModified();
if ( ((now-date)/(1000*60*60*24))>_retainDays)
f.delete();
}
}
}
}
/* ------------------------------------------------------------ */
@Override
public void write (byte[] buf)
throws IOException
{
out.write (buf);
}
/* ------------------------------------------------------------ */
@Override
public void write (byte[] buf, int off, int len)
throws IOException
{
out.write (buf, off, len);
}
/* ------------------------------------------------------------ */
/**
*/
@Override
public void close()
throws IOException
{
synchronized(RolloverFileOutputStream.class)
{
try{super.close();}
finally
{
out=null;
_file=null;
}
_rollTask.cancel();
}
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
private class RollTask extends TimerTask
{
@Override
public void run()
{
try
{
RolloverFileOutputStream.this.setFile();
RolloverFileOutputStream.this.removeOldFiles();
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
}

View File

@ -18,9 +18,9 @@ package org.eclipse.jetty.logging;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import junit.framework.TestCase;
import org.eclipse.jetty.logging.impl.io.LogIO;
import org.eclipse.jetty.util.IO;
import junit.framework.TestCase;
/**
* Common utility methods for working with JUnit tests cases in a maven friendly way.
@ -30,7 +30,6 @@ public class MavenTestingUtils
private static File basedir;
private static File testResourcesDir;
private static File targetDir;
private static Boolean surefireRunning;
public static File getBasedir()
{
@ -168,29 +167,11 @@ public class MavenTestingUtils
try
{
reader = new FileReader(file);
return IO.toString(reader);
return LogIO.toString(reader);
}
finally
{
IO.close(reader);
LogIO.close(reader);
}
}
public static boolean isSurefireExecuting()
{
if (surefireRunning == null)
{
String val = System.getProperty("surefire.test.class.path");
if (val != null)
{
surefireRunning = Boolean.TRUE;
}
else
{
surefireRunning = Boolean.FALSE;
}
}
return surefireRunning;
}
}

View File

@ -19,6 +19,9 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.logging.impl.Appender;
import org.eclipse.jetty.logging.impl.Severity;
/**
* Test Appender, records the logging events.
*/

View File

@ -0,0 +1,155 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
// ========================================================================
// Copyright (c) Webtide LLC
//
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.1-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp-logging</artifactId>
<name>Jetty :: Centralized WebApp Logging</name>
<packaging>jar</packaging>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<forkMode>always</forkMode>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>config.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-centralized-logging</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-deploy</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
</plugin>
</plugins>
</reporting>
<profiles>
<profile>
<id>copy-fresh-webapps</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy-testing-wars</id>
<phase>validate</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-webapp-logging-commons</artifactId>
<version>${project.version}</version>
<type>war</type>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-webapp-logging-java</artifactId>
<version>${project.version}</version>
<type>war</type>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-webapp-logging-log4j</artifactId>
<version>${project.version}</version>
<type>war</type>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-webapp-logging-slf4j</artifactId>
<version>${project.version}</version>
<type>war</type>
</artifactItem>
</artifactItems>
<outputDirectory>${basedir}/src/test/resources/webapps</outputDirectory>
<overWriteIfNewer>true</overWriteIfNewer>
<stripVersion>true</stripVersion>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -13,7 +13,7 @@
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.logging;
package org.eclipse.jetty.webapp.logging;
import java.util.ArrayList;
import java.util.List;

View File

@ -0,0 +1,98 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.logging;
import java.io.FileInputStream;
import java.io.IOException;
import org.eclipse.jetty.logging.impl.CentralLoggerConfig;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Slf4jLog;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* WebAppContext {@link Configuration} for Centralized Logging.
*/
public class CentralizedWebAppLoggingConfiguration implements Configuration
{
private static boolean loggerConfigured = false;
public static CentralLoggerConfig getLoggerRoot()
{
loggerConfigured = true;
return org.slf4j.impl.StaticLoggerBinder.getSingleton().getRoot();
}
public static boolean isLoggerConfigured()
{
return loggerConfigured;
}
public static void setConfiguredLoggerRoot(CentralLoggerConfig root)
{
loggerConfigured = true;
org.slf4j.impl.StaticLoggerBinder.getSingleton().setRoot(root);
try
{
// Reset jetty logger.
Slf4jLog jettyLogger = new Slf4jLog();
Log.setLog(jettyLogger);
}
catch (Exception ignore)
{
// ignore
}
}
public static void setLoggerConfigurationFilename(String filename) throws IOException
{
FileInputStream stream = null;
try
{
stream = new FileInputStream(filename);
CentralLoggerConfig root = CentralLoggerConfig.load(stream);
setConfiguredLoggerRoot(root);
loggerConfigured = true;
}
finally
{
IO.close(stream);
}
}
public void configure(WebAppContext context) throws Exception
{
context.addSystemClass("org.apache.log4j.");
context.addSystemClass("org.slf4j.");
context.addSystemClass("org.apache.commons.logging.");
}
public void deconfigure(WebAppContext context) throws Exception
{
/* do nothing */
}
public void postConfigure(WebAppContext context) throws Exception
{
/* do nothing */
}
public void preConfigure(WebAppContext context) throws Exception
{
/* do nothing */
}
}

View File

@ -0,0 +1,9 @@
target/
.classpath
.project
.settings
*.swp
*.patch
*.diff
*.log
cobertura.ser

View File

@ -13,7 +13,7 @@
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.logging;
package org.eclipse.jetty.webapp.logging;
import java.io.IOException;
@ -21,8 +21,7 @@ import junit.framework.TestCase;
import org.eclipse.jetty.logging.impl.CentralLoggerConfig;
import org.eclipse.jetty.logging.impl.Severity;
import org.eclipse.jetty.logging.impl.TestAppender;
import org.eclipse.jetty.logging.impl.TestAppender.LogEvent;
import org.eclipse.jetty.webapp.logging.TestAppender.LogEvent;
public class CentralizedLoggingTest extends TestCase
{
@ -69,30 +68,12 @@ public class CentralizedLoggingTest extends TestCase
TestAppender testAppender = (TestAppender)root.findAppender(TestAppender.class);
assertNotNull("Should have found TestAppender in configuration",testAppender);
boolean isSurefireExecuting = MavenTestingUtils.isSurefireExecuting();
// HACK: causes failures within surefire.
if (!isSurefireExecuting)
{
SimpleRequest.get(jetty,"/dummy-webapp-logging-log4j/logging");
SimpleRequest.get(jetty,"/dummy-webapp-logging-commons/logging");
}
SimpleRequest.get(jetty,"/dummy-webapp-logging-slf4j/logging");
SimpleRequest.get(jetty,"/dummy-webapp-logging-java/logging");
TestAppender.LogEvent expectedLogs[];
if (isSurefireExecuting)
{
expectedLogs = new LogEvent[]
{ new LogEvent(Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(slf4j) initialized"),
new LogEvent(Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(slf4j) GET requested"),
new LogEvent(Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(java) initialized"),
new LogEvent(Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(java) GET requested") };
}
else
{
expectedLogs = new LogEvent[]
TestAppender.LogEvent expectedLogs[] =
{ new LogEvent(Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(log4j) initialized"),
new LogEvent(Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(log4j) GET requested"),
new LogEvent(Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(slf4j) initialized"),
@ -101,7 +82,6 @@ public class CentralizedLoggingTest extends TestCase
new LogEvent(Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(commons-logging) GET requested"),
new LogEvent(Severity.DEBUG,LOGGING_SERVLET_ID,"LoggingServlet(java) initialized"),
new LogEvent(Severity.INFO,LOGGING_SERVLET_ID,"LoggingServlet(java) GET requested") };
}
assertContainsLogEvents(testAppender,expectedLogs);
}

View File

@ -13,7 +13,7 @@
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.logging;
package org.eclipse.jetty.webapp.logging;
import java.io.File;
import java.util.ArrayList;
@ -23,8 +23,6 @@ import junit.framework.TestCase;
import org.eclipse.jetty.logging.impl.CentralLoggerConfig;
import org.eclipse.jetty.logging.impl.Severity;
import org.eclipse.jetty.logging.impl.TestAppender;
import org.eclipse.jetty.logging.impl.TestAppender.LogEvent;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
@ -32,6 +30,7 @@ import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.logging.TestAppender.LogEvent;
/**
* Test centralized logging in an embedded scenario

View File

@ -0,0 +1,199 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.logging;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import junit.framework.TestCase;
import org.eclipse.jetty.util.IO;
/**
* Common utility methods for working with JUnit tests cases in a maven friendly way.
*/
public class MavenTestingUtils
{
private static File basedir;
private static File testResourcesDir;
private static File targetDir;
// private static Boolean surefireRunning;
public static File getBasedir()
{
if (basedir == null)
{
String cwd = System.getProperty("basedir");
if (cwd == null)
{
cwd = System.getProperty("user.dir");
}
basedir = new File(cwd);
}
return basedir;
}
/**
* Get the directory to the /target directory for this project.
*
* @return the directory path to the target directory.
*/
public static File getTargetDir()
{
if (targetDir == null)
{
targetDir = new File(basedir,"target");
PathAssert.assertDirExists("Target Dir",targetDir);
}
return targetDir;
}
/**
* Create a {@link File} object for a path in the /target directory.
*
* @param path
* the path desired, no validation of existence is performed.
* @return the File to the path.
*/
public static File getTargetFile(String path)
{
return new File(getTargetDir(),path.replace("/",File.separator));
}
public static File getTargetTestingDir()
{
File dir = new File(getTargetDir(),"testing");
if (!dir.exists())
{
dir.mkdirs();
}
return dir;
}
public static File getTargetTestingDir(TestCase test)
{
File dir = new File(getTargetDir(),"test-" + test.getName());
if (!dir.exists())
{
dir.mkdirs();
}
return dir;
}
/**
* Get a dir from the src/test/resource directory.
*
* @param name
* the name of the path to get (it must exist as a dir)
* @return the dir in src/test/resource
*/
public static File getTestResourceDir(String name)
{
File dir = new File(getTestResourcesDir(),name);
PathAssert.assertDirExists("Test Resource Dir",dir);
return dir;
}
/**
* Get a file from the src/test/resource directory.
*
* @param name
* the name of the path to get (it must exist as a file)
* @return the file in src/test/resource
*/
public static File getTestResourceFile(String name)
{
File file = new File(getTestResourcesDir(),name);
PathAssert.assertFileExists("Test Resource File",file);
return file;
}
/**
* Get a path resource (File or Dir) from the src/test/resource directory.
*
* @param name
* the name of the path to get (it must exist)
* @return the path in src/test/resource
*/
public static File getTestResourcePath(String name)
{
File path = new File(getTestResourcesDir(),name);
PathAssert.assertExists("Test Resource Path",path);
return path;
}
/**
* Get the directory to the src/test/resource directory
*
* @return the directory {@link File} to the src/test/resources directory
*/
public static File getTestResourcesDir()
{
if (testResourcesDir == null)
{
testResourcesDir = new File(basedir,"src/test/resources".replace("/",File.separator));
PathAssert.assertDirExists("Test Resources Dir",testResourcesDir);
}
return testResourcesDir;
}
/**
* Read the contents of a file into a String and return it.
*
* @param file
* the file to read.
* @return the contents of the file.
* @throws IOException
* if unable to read the file.
*/
public static String readToString(File file) throws IOException
{
FileReader reader = null;
try
{
reader = new FileReader(file);
return IO.toString(reader);
}
finally
{
IO.close(reader);
}
}
/*
public static boolean isSurefireExecuting()
{
if (surefireRunning == null)
{
String val = System.getProperty("surefire.test.class.path");
if (val != null)
{
surefireRunning = Boolean.TRUE;
}
else
{
surefireRunning = Boolean.FALSE;
}
}
return surefireRunning;
}
*/
}

View File

@ -0,0 +1,40 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.logging;
import java.io.File;
import junit.framework.Assert;
public class PathAssert
{
public static void assertDirExists(String msg, File path)
{
assertExists(msg,path);
Assert.assertTrue(msg + " path should be a Dir : " + path.getAbsolutePath(),path.isDirectory());
}
public static void assertFileExists(String msg, File path)
{
assertExists(msg,path);
Assert.assertTrue(msg + " path should be a File : " + path.getAbsolutePath(),path.isFile());
}
public static void assertExists(String msg, File path)
{
Assert.assertTrue(msg + " path should exist: " + path.getAbsolutePath(),path.exists());
}
}

View File

@ -13,7 +13,7 @@
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.logging;
package org.eclipse.jetty.webapp.logging;
import java.io.IOException;
import java.io.InputStream;

View File

@ -0,0 +1,146 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.logging;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.logging.impl.Appender;
import org.eclipse.jetty.logging.impl.Severity;
/**
* Test Appender, records the logging events.
*/
public class TestAppender implements Appender
{
public static class LogEvent
{
String date;
Severity severity;
String name;
String message;
Throwable t;
public LogEvent(String date, Severity severity, String name, String message, Throwable t)
{
super();
this.date = date;
this.severity = severity;
this.name = name;
this.message = message;
this.t = t;
}
public LogEvent(Severity severity, String name, String message)
{
this(null,severity,name,message,null);
}
@Override
public String toString()
{
StringBuffer buf = new StringBuffer();
buf.append(severity.name()).append("|");
buf.append(name).append("|");
buf.append(message);
return buf.toString();
}
}
private List<LogEvent> events = new ArrayList<LogEvent>();
private String id;
public String getId()
{
return id;
}
public void setId(String id)
{
this.id = id;
}
public void append(String date, Severity severity, String name, String message, Throwable t)
{
if (name.equals("org.eclipse.jetty.util.log")) // standard jetty logger
{
if (t != null)
{
// Still interested in seeing throwables (HACK)
t.printStackTrace(System.err);
}
return; // skip storing it.
}
events.add(new LogEvent(date,severity,name,message,t));
}
public void close() throws IOException
{
/* nothing to do here */
}
public boolean contains(LogEvent expectedEvent)
{
// System.out.println("Looking for: " + expectedEvent);
for (LogEvent event : events)
{
// System.out.println("Event: " + event);
if (!event.name.equals(expectedEvent.name))
{
continue; // not a match. skip.
}
if (!event.severity.equals(expectedEvent.severity))
{
continue; // not a match. skip.
}
if (event.message.equals(expectedEvent.message))
{
return true;
}
}
return false;
}
public List<LogEvent> getEvents()
{
return events;
}
public void open() throws IOException
{
/* nothing to do here */
}
public void reset()
{
events.clear();
}
public void setProperty(String key, String value) throws Exception
{
/* nothing to do here */
}
public void dump()
{
System.out.printf("Captured %s event(s)%n",events.size());
for (LogEvent event : events)
{
System.out.println(event);
}
}
}

View File

@ -14,7 +14,7 @@
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.logging;
package org.eclipse.jetty.webapp.logging;
import java.io.File;
import java.io.FileOutputStream;

View File

@ -2,4 +2,4 @@ root.level=DEBUG
root.appenders=testing
appender.console.class=org.eclipse.jetty.logging.impl.ConsoleAppender
appender.testing.class=org.eclipse.jetty.logging.impl.TestAppender
appender.testing.class=org.eclipse.jetty.webapp.logging.TestAppender

View File

@ -133,6 +133,7 @@
<module>jetty-servlet</module>
<module>jetty-webapp</module>
<module>jetty-webapp-verifier</module>
<module>jetty-webapp-logging</module>
<module>jetty-centralized-logging</module>
<module>jetty-servlets</module>
<module>jetty-deploy</module>