remm 2005/03/02 10:30:45
Modified: . build.xml
catalina/etc bootstrap.MF
Added: juli/src/conf logging.properties
juli/src/java/org/apache/juli ClassLoaderLogManager.java
FileHandler.java
juli build.xml
Log:
- Add JULI, a Java Util Logging Implementation.
- It supports per classloader configuration, using standard JDK properties
files, with optional extensions to be able to flexibly assign handlers to
loggers.
- The package includes a rotating handler, since zillions of people have
lamented its departure in 5.5.x (even if it didn't contain anything useful
anymore).
- This builds a small JAR, which is then added to the classpath by
bootstrap.jar.
- I may need to fix packaging a little after that change; sorry for the
trouble.
- I'll add comments and docs soon.
- This is based on code subimmted by Lachlan O'Dea in bug 33143, and is
likely to move to commons (once I get comfortable enough with svn).
Revision Changes Path
1.1
jakarta-tomcat-connectors/juli/src/conf/logging.properties
Index: logging.properties
===================================================================
handlers = org.apache.juli.FileHandler java.util.logging.ConsoleHandler
############################################################
# Handler specific properties.
# Describes specific configuration info for Handlers.
############################################################
org.apache.juli.FileHandler.level = FINE
org.apache.juli.FileHandler.directory = ${catalina.base}/logs
java.util.logging.ConsoleHandler.level = FINE
java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
############################################################
# Facility specific properties.
# Provides extra control for each logger.
############################################################
# For example, set the com.xyz.foo logger to only log SEVERE
# messages:
#org.apache.catalina.startup.ContextConfig.level = FINE
#org.apache.catalina.startup.HostConfig.level = FINE
#org.apache.catalina.session.ManagerBase.level = FINE
1.223 +23 -0 jakarta-tomcat-5/build.xml
Index: build.xml
===================================================================
RCS file: /home/cvs/jakarta-tomcat-5/build.xml,v
retrieving revision 1.222
retrieving revision 1.223
diff -u -r1.222 -r1.223
--- build.xml 20 Jan 2005 12:00:20 -0000 1.222
+++ build.xml 2 Mar 2005 18:30:45 -0000 1.223
@@ -288,6 +288,27 @@
</target>
+ <target name="build-juli"
+ unless="tomcatjuli.build.notrequired"
+ depends="init" description="builds j-t-c/juli">
+ <echo>========== Building: tomcat-juli </echo>
+
+ <ant dir="${jtc.home}/juli" target="compile-only">
+ <property name="build.home" value="${tomcat.build}"/>
+ </ant>
+
+ <!-- Java.util.logging Implementation -->
+ <jar jarfile="${tomcat.build}/bin/tomcat-juli.jar" index="true">
+ <fileset dir="${tomcat.build}/classes">
+ <include name="org/apache/juli/**" />
+ <!-- Javadoc and i18n exclusions -->
+ <exclude name="**/package.html" />
+ <exclude name="**/LocalStrings_*" />
+ </fileset>
+ </jar>
+
+ </target>
+
<target name="build-jasper"
unless="jasper.build.notrequired"
depends="init" description="build jasper">
@@ -513,6 +534,8 @@
<antcall target="build-tomcathttp11"/>
+ <antcall target="build-juli"/>
+
<antcall target="build-jasper"/>
<antcall target="build-i18n"/>
1.6 +1 -1 jakarta-tomcat-catalina/catalina/etc/bootstrap.MF
Index: bootstrap.MF
===================================================================
RCS file: /home/cvs/jakarta-tomcat-catalina/catalina/etc/bootstrap.MF,v
retrieving revision 1.5
retrieving revision 1.6
diff -u -r1.5 -r1.6
--- bootstrap.MF 2 Mar 2004 12:32:19 -0000 1.5
+++ bootstrap.MF 2 Mar 2005 18:30:45 -0000 1.6
@@ -1,5 +1,5 @@
Manifest-Version: 1.0
Main-Class: org.apache.catalina.startup.Bootstrap
-Class-Path: jmx.jar commons-daemon.jar commons-logging-api.jar
+Class-Path: jmx.jar commons-daemon.jar commons-logging-api.jar
tomcat-juli.jar
Specification-Title: Catalina
Specification-Version: 1.0
\ No newline at end of file
1.1
jakarta-tomcat-connectors/juli/src/java/org/apache/juli/ClassLoaderLogManager.java
Index: ClassLoaderLogManager.java
===================================================================
/*
* Copyright 1999,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.juli;
import java.util.logging.*;
import java.util.*;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* Per classloader LogManager implementation.
*/
public final class ClassLoaderLogManager extends LogManager {
private static void doSetParentLogger(final Logger logger,
final Logger parent) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
logger.setParent(parent);
return null;
}
});
} else {
logger.setParent(parent);
}
}
private final Map classLoaderLoggers = new WeakHashMap();
private Logger rootLogger;
private Logger globalLogger;
private ThreadLocal prefix = new ThreadLocal();
public synchronized boolean addLogger(final Logger logger) {
final String loggerName = logger.getName();
if ("".equals(loggerName)) {
final boolean unset = rootLogger == null;
if (unset) {
rootLogger = logger;
if (globalLogger != null) {
doSetParentLogger(globalLogger, rootLogger);
}
}
return unset;
}
if ("global".equals(loggerName)) {
final boolean unset = globalLogger == null;
if (unset) {
globalLogger = logger;
if (rootLogger != null) {
doSetParentLogger(globalLogger, rootLogger);
}
}
return unset;
}
final ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
final ClassLoaderLogInfo info = getClassLoaderInfo(classLoader);
if (info.loggers.containsKey(loggerName)) {
return false;
}
info.loggers.put(loggerName, logger);
// apply initial level for new logger
final String levelString = getProperty(loggerName + ".level");
final Level level;
if (levelString != null) {
Level parsedLevel = null;
try {
parsedLevel = Level.parse(levelString.trim());
} catch (IllegalArgumentException e) {
// leave level set to null
}
level = parsedLevel;
} else {
level = null;
}
if (level != null) {
if (System.getSecurityManager() == null) {
logger.setLevel(level);
} else {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
logger.setLevel(level);
return null;
}
});
}
}
// if any parent loggers have levels definied, make sure they are
// instantiated
int dotIndex = loggerName.lastIndexOf('.');
while (dotIndex >= 0) {
final String parentName = loggerName.substring(0, dotIndex);
if (getProperty(parentName + ".level") != null) {
Logger.getLogger(parentName);
break;
}
dotIndex = loggerName.lastIndexOf('.', dotIndex - 1);
}
// find node
final LogNode node = info.rootNode.findNode(loggerName);
node.logger = logger;
// set parent logger
final Logger parentLogger = node.findParentLogger();
if (parentLogger != null) {
doSetParentLogger(logger, parentLogger);
}
// tell children we are their new parent
node.setParentLogger(logger);
// Add associated handlers, if any are defined using the .handlers
property.
// In this case, handlers of the parent logger(s) will not be used
final String handlers = getProperty(loggerName + ".handlers");
if (handlers != null) {
logger.setUseParentHandlers(false);
StringTokenizer tok = new StringTokenizer(handlers);
while (tok.hasMoreTokens()) {
String handlerName = (tok.nextToken());
Handler handler = (Handler) info.handlers.get(handlerName);
if (handler != null) {
logger.addHandler(handler);
}
}
}
return true;
}
public synchronized Logger getLogger(final String name) {
if (rootLogger == null && globalLogger == null) {
// this ends up being called during initialization, we don't
// want do anything unless the root logger has been set up.
return null;
}
if (name == null || name.length() == 0) {
return rootLogger;
}
if ("global".equals(name)) {
return globalLogger;
}
final ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
final Map loggers = getClassLoaderInfo(classLoader).loggers;
/*
* Debug: display handler list
Logger logger = (Logger) loggers.get(name);
System.out.println(name);
if (logger != null) {
Handler[] handlers = logger.getHandlers();
for (int i = 0; i < handlers.length; i++) {
System.out.println("H" + i + ":" + handlers[i]);
}
}
*/
return (Logger) loggers.get(name);
}
public synchronized Enumeration getLoggerNames() {
if (rootLogger == null && globalLogger == null) {
// this ends up being called during initialization, we don't
// want do anything unless the root logger has been set up.
return Collections.enumeration(Collections.EMPTY_LIST);
}
final ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
final Map loggers = getClassLoaderInfo(classLoader).loggers;
return Collections.enumeration(loggers.keySet());
}
/**
* Get the value of the specified property in the current classloader
* context.
*/
public String getProperty(String name) {
String prefix = (String) this.prefix.get();
if (prefix != null) {
name = prefix + name;
}
final ClassLoader classLoader = Thread.currentThread()
.getContextClassLoader();
String result =
getClassLoaderInfo(classLoader).props.getProperty(name);
if (result == null) {
// FIXME: Look in parent classloader ? Probably not.
result = super.getProperty(name);
}
// Simple property replacement (mostly for folder names)
if (result != null) {
result = result.trim();
if (result.startsWith("${")) {
int pos = result.indexOf('}');
if (pos != -1) {
String propName = result.substring(2, pos);
String replacement = System.getProperty(propName);
if (replacement != null) {
result = replacement + result.substring(pos + 1);
}
}
}
}
return result;
}
private ClassLoaderLogInfo getClassLoaderInfo(final ClassLoader
classLoader) {
ClassLoaderLogInfo info = (ClassLoaderLogInfo) classLoaderLoggers
.get(classLoader);
if (info == null) {
InputStream is = null;
// Special case for URL classloaders which are used in
containers:
// only look in the local repositories to avoid redefining
loggers 20 times
if ((classLoader instanceof URLClassLoader)
&& (((URLClassLoader)
classLoader).findResource("logging.properties") != null)) {
is = classLoader.getResourceAsStream("logging.properties");
}
Logger localRootLogger = null;
if (is != null) {
localRootLogger = new RootLogger();
} else {
// Retrieve the root logger of the parent classloader instead
if (classLoader.getParent() != null) {
localRootLogger =
getClassLoaderInfo(classLoader.getParent()).rootNode.logger;
} else {
localRootLogger = rootLogger;
}
}
info = new ClassLoaderLogInfo(new LogNode(null, localRootLogger));
info.loggers.put("", localRootLogger);
classLoaderLoggers.put(classLoader, info);
if (is != null) {
try {
info.props.load(is);
} catch (IOException e) {
// FIXME: Report this using the main logger ?
e.printStackTrace();
} finally {
try {
is.close();
} catch (Throwable t) {}
}
// Create handlers for the root logger of this classloader
String rootHandlers = info.props.getProperty(".handlers");
String handlers = info.props.getProperty("handlers");
if (handlers != null) {
StringTokenizer tok = new StringTokenizer(handlers);
while (tok.hasMoreTokens()) {
String handlerName = (tok.nextToken());
String handlerClassName = handlerName;
String prefix = "";
if (handlerClassName.length() <= 0) {
continue;
}
// Parse and remove a prefix (prefix start with a
digit, such as
// "10WebappFooHanlder.")
if (Character.isDigit(handlerClassName.charAt(0))) {
int pos = handlerClassName.indexOf('.');
if (pos >= 0) {
prefix = handlerClassName.substring(0, pos +
1);
handlerClassName =
handlerClassName.substring(pos + 1);
}
}
try {
this.prefix.set(prefix);
Handler handler =
(Handler)
classLoader.loadClass(handlerClassName).newInstance();
this.prefix.set(null);
String handlerLevel =
info.props.getProperty(handlerName +
".level");
if (handlerLevel != null) {
handler.setLevel(Level.parse(handlerLevel.trim()));
}
info.handlers.put(handlerName, handler);
if (rootHandlers == null) {
localRootLogger.addHandler(handler);
}
} catch (Exception e) {
// FIXME: Report this using the main logger ?
e.printStackTrace();
}
}
// Add handlers to the root logger, if any are defined
using the .handlers property.
if (rootHandlers != null) {
StringTokenizer tok2 = new
StringTokenizer(rootHandlers);
while (tok2.hasMoreTokens()) {
String handlerName = (tok2.nextToken());
Handler handler = (Handler)
info.handlers.get(handlerName);
if (handler != null) {
localRootLogger.addHandler(handler);
}
}
}
}
}
}
return info;
}
private static final class LogNode {
Logger logger;
private final Map children = new HashMap();
private final LogNode parent;
LogNode(final LogNode parent, final Logger logger) {
this.parent = parent;
this.logger = logger;
}
LogNode(final LogNode parent) {
this(parent, null);
}
LogNode findNode(String name) {
assert name != null && name.length() > 0;
LogNode currentNode = this;
while (name != null) {
final int dotIndex = name.indexOf('.');
final String nextName;
if (dotIndex < 0) {
nextName = name;
name = null;
} else {
nextName = name.substring(0, dotIndex);
name = name.substring(dotIndex + 1);
}
LogNode childNode = (LogNode) currentNode.children
.get(nextName);
if (childNode == null) {
childNode = new LogNode(currentNode);
currentNode.children.put(nextName, childNode);
}
currentNode = childNode;
}
return currentNode;
}
Logger findParentLogger() {
Logger logger = null;
LogNode node = parent;
while (node != null && logger == null) {
logger = node.logger;
node = node.parent;
}
assert logger != null;
return logger;
}
void setParentLogger(final Logger parent) {
for (final Iterator iter = children.values().iterator(); iter
.hasNext();) {
final LogNode childNode = (LogNode) iter.next();
if (childNode.logger == null) {
childNode.setParentLogger(parent);
} else {
doSetParentLogger(childNode.logger, parent);
}
}
}
}
private static final class ClassLoaderLogInfo {
final LogNode rootNode;
final Map loggers = new HashMap();
final Map handlers = new HashMap();
final Properties props = new Properties();
ClassLoaderLogInfo(final LogNode rootNode) {
this.rootNode = rootNode;
}
}
/**
* This is needed to instantiate the root of each per classloader
hierarchy.
*/
private class RootLogger extends Logger {
public RootLogger() {
super("", null);
}
}
}
1.1
jakarta-tomcat-connectors/juli/src/java/org/apache/juli/FileHandler.java
Index: FileHandler.java
===================================================================
/*
* Copyright 1999,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.juli;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.sql.Timestamp;
import java.util.logging.ErrorManager;
import java.util.logging.Handler;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.SimpleFormatter;
/**
* Implementation of <b>Handler</b> that appends log messages to a file
* named {prefix}.{date}.{suffix} in a configured directory, with an
* optional preceding timestamp.
*
* @version $Revision: 1.1 $ $Date: 2005/03/02 18:30:45 $
*/
public class FileHandler
extends Handler {
// ------------------------------------------------------------
Constructor
public FileHandler() {
configure();
open();
}
// ----------------------------------------------------- Instance
Variables
/**
* The as-of date for the currently open log file, or a zero-length
* string if there is no open log file.
*/
private String date = "";
/**
* The directory in which log files are created.
*/
private String directory = null;
/**
* The prefix that is added to log file filenames.
*/
private String prefix = null;
/**
* The suffix that is added to log file filenames.
*/
private String suffix = null;
/**
* The PrintWriter to which we are currently logging, if any.
*/
private PrintWriter writer = null;
// -------------------------------------------------------------
Properties
/**
* Return the directory in which we create log files.
public String getDirectory() {
return (directory);
}
*/
/**
* Set the directory in which we create log files.
*
* @param directory The new log file directory
public void setDirectory(String directory) {
this.directory = directory;
}
*/
/**
* Return the log file prefix.
public String getPrefix() {
return (prefix);
}
*/
/**
* Set the log file prefix.
*
* @param prefix The new log file prefix
public void setPrefix(String prefix) {
this.prefix = prefix;
}
*/
/**
* Return the log file suffix.
public String getSuffix() {
return (suffix);
}
*/
/**
* Set the log file suffix.
*
* @param suffix The new log file suffix
public void setSuffix(String suffix) {
this.suffix = suffix;
}
*/
// --------------------------------------------------------- Public
Methods
/**
* Format and publish a <tt>LogRecord</tt>.
*
* @param record description of the log event
*/
public void publish(LogRecord record) {
if (!isLoggable(record)) {
return;
}
// Construct the timestamp we will use, if requested
Timestamp ts = new Timestamp(System.currentTimeMillis());
String tsString = ts.toString().substring(0, 19);
String tsDate = tsString.substring(0, 10);
// If the date has changed, switch log files
if (!date.equals(tsDate)) {
synchronized (this) {
if (!date.equals(tsDate)) {
close();
date = tsDate;
open();
}
}
}
String result = null;
try {
result = getFormatter().format(record);
} catch (Exception e) {
reportError(null, e, ErrorManager.FORMAT_FAILURE);
return;
}
try {
writer.write(result);
writer.flush();
} catch (Exception e) {
reportError(null, e, ErrorManager.WRITE_FAILURE);
return;
}
}
// -------------------------------------------------------- Private
Methods
/**
* Close the currently open log file (if any)
*/
public void close() {
try {
if (writer == null)
return;
writer.write(getFormatter().getTail(this));
writer.flush();
writer.close();
writer = null;
date = "";
} catch (Exception e) {
reportError(null, e, ErrorManager.CLOSE_FAILURE);
}
}
/**
* FLush
*/
public void flush() {
try {
writer.flush();
} catch (Exception e) {
reportError(null, e, ErrorManager.FLUSH_FAILURE);
}
}
/**
* Configure from <code>LogManager</code> properties.
*/
private void configure() {
Timestamp ts = new Timestamp(System.currentTimeMillis());
String tsString = ts.toString().substring(0, 19);
date = tsString.substring(0, 10);
LogManager manager = LogManager.getLogManager();
String className = FileHandler.class.getName();
// Retrieve configuration of logging file name
directory = getProperty(className + ".directory", "logs");
prefix = getProperty(className + ".prefix", "juli.");
suffix = getProperty(className + ".suffix", ".log");
// FIXME: Add filter configuration in LogManager ?
//setFilter(manager.getFilterProperty(className + ".filter", null));
// FIXME: Add formatter configuration in LogManager ?
//setFormatter(manager.getFormatterProperty(className + ".formatter",
new SimpleFormatter()));
// Hardcode for now a SimpleFormatter
setFormatter(new SimpleFormatter());
// FIXME: Add encoding configuration in LogManager ?
try {
setEncoding(manager.getProperty(className + ".encoding"));
} catch (UnsupportedEncodingException e) {
try {
setEncoding(null);
} catch (Exception ex) {
}
}
setErrorManager(new ErrorManager());
}
private String getProperty(String name, String defaultValue) {
String value = LogManager.getLogManager().getProperty(name);
if (value == null) {
value = defaultValue;
}
return value.trim();
}
/**
* Open the new log file for the date specified by <code>date</code>.
*/
private void open() {
// Create the directory if necessary
File dir = new File(directory);
dir.mkdirs();
// Open the current log file
try {
String pathname = dir.getAbsolutePath() + File.separator +
prefix + date + suffix;
writer = new PrintWriter(new FileWriter(pathname, true), true);
writer.write(getFormatter().getHead(this));
} catch (Exception e) {
reportError(null, e, ErrorManager.OPEN_FAILURE);
writer = null;
}
}
}
1.1 jakarta-tomcat-connectors/juli/build.xml
Index: build.xml
===================================================================
<project name="Juli" default="compile" basedir=".">
<!--
"Coyote" connector framework for Jakarta Tomcat
$Id: build.xml,v 1.1 2005/03/02 18:30:45 remm Exp $
-->
<!-- ========== Initialize Properties =====================================
-->
<property file="build.properties"/> <!-- Component local
-->
<property file="../build.properties"/> <!-- Commons local
-->
<property file="${user.home}/build.properties"/> <!-- User local
-->
<!-- ========== External Dependencies =====================================
-->
<!-- The directories corresponding to your necessary dependencies -->
<property name="junit.home" value="/usr/local/junit3.5"/>
<!-- ========== Derived Values ============================================
-->
<property name="junit.jar" value="${junit.home}/junit.jar"/>
<property name="jmx.jar" location="../lib/mx4j.jar" />
<!-- ========== Component Declarations ====================================
-->
<!-- The name of this component -->
<property name="component.name" value="juli"/>
<!-- The title of this component -->
<property name="component.title" value="Java Util Logging
Implementation"/>
<!-- The current version number of this component -->
<property name="component.version" value="1.0-dev"/>
<!-- The base directory for compilation targets -->
<property name="build.home" value="build"/>
<!-- The base directory for component configuration files -->
<property name="conf.home" value="src/conf"/>
<!-- The base directory for component sources -->
<property name="source.home" value="src/java"/>
<!-- The base directory for unit test sources -->
<property name="test.home" value="src/test"/>
<!-- ========== Compiler Defaults =========================================
-->
<!-- Should Java compilations set the 'debug' compiler option? -->
<property name="compile.debug" value="true"/>
<!-- Should Java compilations set the 'deprecation' compiler option? -->
<property name="compile.deprecation" value="false"/>
<!-- Should Java compilations set the 'optimize' compiler option? -->
<property name="compile.optimize" value="true"/>
<!-- Construct compile classpath -->
<path id="compile.classpath">
<pathelement location="${build.home}/classes"/>
<pathelement location="${jmx.jar}"/>
</path>
<!-- ========== Test Execution Defaults ===================================
-->
<!-- Construct unit test classpath -->
<path id="test.classpath">
<pathelement location="${build.home}/classes"/>
<pathelement location="${build.home}/tests"/>
<pathelement location="${jmx.jar}"/>
<pathelement location="${junit.jar}"/>
</path>
<!-- Should all tests fail if one does? -->
<property name="test.failonerror" value="true"/>
<!-- ========== Executable Targets ========================================
-->
<target name="init"
description="Initialize and evaluate conditionals">
<echo message="-------- ${component.title} ${component.version}
--------"/>
<filter token="name" value="${component.name}"/>
<filter token="version" value="${component.version}"/>
</target>
<target name="prepare" depends="init"
description="Prepare build directory">
<mkdir dir="${build.home}"/>
<mkdir dir="${build.home}/classes"/>
<mkdir dir="${build.home}/conf"/>
<mkdir dir="${build.home}/lib"/>
<mkdir dir="${build.home}/docs"/>
<mkdir dir="${build.home}/docs/api"/>
<mkdir dir="${build.home}/tests"/>
</target>
<target name="static" depends="prepare"
description="Copy static files to build directory">
<tstamp/>
<copy todir="${build.home}/conf" filtering="on">
<fileset dir="${conf.home}" includes="*.MF"/>
</copy>
</target>
<target name="javadoc" unless="docs-uptodate"
description="Create component Javadoc documentation">
<mkdir dir="${build.home}/docs/api"/>
<javadoc sourcepath="${source.home}"
destdir="${build.home}/docs/api"
packagenames="org.apache.coyote.*"
author="true"
private="true"
version="true"
doctitle="<h1>${component.title}</h1>"
windowtitle="${component.title} (Version ${component.version})"
bottom="Copyright (c) 2005 - Apache Software Foundation">
<classpath refid="compile.classpath"/>
</javadoc>
</target>
<target name="compile-only"
description="Compile shareable components">
<javac srcdir="${source.home}"
destdir="${build.home}/classes"
debug="${compile.debug}"
deprecation="${compile.deprecation}"
source="1.4"
optimize="${compile.optimize}">
<classpath refid="compile.classpath"/>
</javac>
<copy todir="${build.home}/classes" filtering="on">
<fileset dir="${source.home}" excludes="**/*.java"/>
</copy>
<property name="tomcat-juli.jar"
value="${build.home}/lib/tomcat-${component.name}.jar"/>
<jar jarfile="${tomcat-juli.jar}"
index="true"
basedir="${build.home}/classes"
manifest="${build.home}/conf/MANIFEST.MF">
<include name="org/apache/juli/**"/>
</jar>
</target>
<target name="compile" depends="static,compile-only"
description="Compile shareable components">
</target>
<target name="compile.tests" depends="compile"
description="Compile unit test cases">
<javac srcdir="${test.home}/java"
destdir="${build.home}/tests"
debug="${compile.debug}"
deprecation="${compile.deprecation}"
optimize="${compile.optimize}">
<classpath refid="test.classpath"/>
</javac>
<copy todir="${build.home}/tests" filtering="on">
<fileset dir="${test.home}" excludes="**/*.java"/>
</copy>
</target>
<target name="clean"
description="Clean build and distribution directories">
<delete dir="${build.home}"/>
<delete dir="${dist.home}"/>
</target>
<target name="all" depends="clean,compile,compile.tests"
description="Clean and compile all components"/>
<!-- ========== Unit Test Targets =========================================
-->
<target name="test" depends="compile.tests" if="test.entry"
description="Run all unit test cases">
<!--
<junit printsummary="yes" fork="on" haltonfailure="yes">
<formatter type="plain" usefile="false"/>
<test name="${test.entry}"/>
<classpath refid="test.classpath"/>
</junit>
<java classname="${test.runner}" fork="yes"
failonerror="${test.failonerror}">
<jvmarg value="${java.protocol.handler.pkgs}"/>
<arg value="${test.entry}"/>
<classpath refid="test.classpath"/>
</java>
-->
</target>
</project>
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]