The clirr target in build.xml can be used to check for breaking API
changes between versions and should be used to check log4j 1.3
against a representative log4j 1.2 release anytime that you think you
might be affecting binary compatibility. Try to be strict on not
increasing the reported compatibilities and trying to get to zero.
Index: src/java/org/apache/log4j/NDC.java
===================================================================
98,100d97
< static int pushCounter = 0; // the number of times push has
been called
< // after the latest call to lazyRemove
< static final int REAP_THRESHOLD = 5;
These variables were not private in log4j 1.2 so they can't be
removed without breaking compatibility.
Index: src/java/org/apache/log4j/db/DBHelper.java
===================================================================
32,33c32,33
< public static short PROPERTIES_EXIST = 0x01;
< public static short EXCEPTION_EXISTS = 0x02;
---
> public final static short PROPERTIES_EXIST = 0x01;
> public final static short EXCEPTION_EXISTS = 0x02;
Can't add final without breaking compatibility.
Index: src/java/org/apache/log4j/db/DBReceiverJob.java
===================================================================
29a30
> import java.sql.PreparedStatement;
42a44,55
> String sqlException = "SELECT trace_line FROM
logging_event_exception where event_id=? ORDER by i ASC";
> String sqlProperties = "SELECT mapped_key, mapped_value FROM
logging_event_property WHERE event_id=?";
> String sqlSelect =
> "SELECT " +
> "sequence_number, timestamp, rendered_message, logger_name, " +
> "level_string, ndc, thread_name, reference_flag, " +
> "caller_filename, caller_class, caller_method, caller_line, " +
> "event_id " +
> "FROM logging_event " +
> "WHERE event_id > ? ORDER BY event_id ASC";
>
>
57,59d69
< Logger logger;
< LoggerRepository loggerRepository = parentDBReceiver
< .getLoggerRepository();
61,84c71,73
<
< StringBuffer sql = new StringBuffer();
< sql.append("SELECT ");
< sql.append("sequence_number, ");
< sql.append("timestamp, ");
< sql.append("rendered_message, ");
< sql.append("logger_name, ");
< sql.append("level_string, ");
< sql.append("ndc, ");
< sql.append("thread_name, ");
< sql.append("reference_flag, ");
< sql.append("caller_filename, ");
< sql.append("caller_class, ");
< sql.append("caller_method, ");
< sql.append("caller_line, ");
< sql.append("event_id ");
< sql.append("FROM logging_event ");
<
< // have subsequent SELECTs start from we left off last time
< sql.append(" WHERE event_id > " + lastId);
< sql.append(" ORDER BY event_id ASC");
<
< Statement statement = connection.createStatement();
< ResultSet rs = statement.executeQuery(sql.toString());
---
> PreparedStatement statement = connection.prepareStatement
(sqlSelect);
> statement.setLong(1, lastId);
> ResultSet rs = statement.executeQuery();
165,168d153
< String sql = "SELECT mapped_key, mapped_value FROM
logging_event_property WHERE event_id='"
< + id + "'";
<
< Statement statement = null;
169a155
> PreparedStatement statement = connection.prepareStatement
(sqlProperties);
171,174c157,158
< statement = connection.createStatement();
<
< ResultSet rs = statement.executeQuery(sql);
< //rs.beforeFirst();
---
> statement.setLong(1, id);
> ResultSet rs = statement.executeQuery();
182d165
< if (statement != null) {
186d168
< }
199,200d180
< String sql = "SELECT trace_line FROM logging_event_exception
where event_id='"
< + id + "' ORDER by i ASC";
202c182
< Statement statement = null;
---
> PreparedStatement statement = null;
205,207c185,187
< statement = connection.createStatement();
<
< ResultSet rs = statement.executeQuery(sql);
---
> statement = connection.prepareStatement(sqlException);
> statement.setLong(1, id);
> ResultSet rs = statement.executeQuery();
This looks like a pretty substantial rewrite (at least from the
diffs) what was the complaint that was being addressed.
Index: src/java/org/apache/log4j/db/DBReceiver.java
===================================================================
41d40
< private static final LoggerRepository Hierarchy = null;
Index: src/java/org/apache/log4j/DailyRollingFileAppender.java
===================================================================
178,179d177
< int checkPeriod = TOP_OF_TROUBLE;
<
Not private in log4j 1.2, can't be removed.
Index: src/java/org/apache/log4j/spi/LocationInfo.java
===================================================================
150a151,155
> public int hashCode() {
> return getClassName().hashCode() + getLineNumber().hashCode();
> }
>
>
log4j's doesn't override LocationInfo.equal, so this is strictly a
log4j 1.3 issue. If you don't have Joshua Bloch's "Effective Java",
I would strongly recommend getting a copy (there is a second edition
coming this summer). equals and hashCode are addressed in items 7
and 8. This implementation would seem to violate the suggestion "Do
not be tempted to exclude significant parts of an object from the
hash code computation to improve performance" and would throw a
NullPointerException if className or lineNumber were null. It is
definitely an improvement from not overriding hashCode(), but it
could be better. The recipe in Effective Java would result something
like:
public int hashCode() {
int result = 17;
result = 37*result + (lineNumber == null ? 0 :
lineNumber.hashCode());
result = 37*result + (fileName == null ? 0 : fileName.hashCode());
result = 37*result + (className == null ? 0 : className.hashCode
());
result = 37*result + (methodName == null ? 0 :
methodName.hashCode());
return result;
}
LocationInfo.equals also NPEs if any of the fields are null, but
nothing prevents them from being null.
Index: src/java/org/apache/log4j/spi/LoggingEvent.java
===================================================================
85c85
< static long sequenceCount = 1;
---
> private static long sequenceCount = 1;
107,114c107
< * The LoggerRepository in which this event was created.
< *
< * @since 1.3
< */
< private transient LoggerRepository loggerRepository;
<
<
< /** The logger name.
---
> * The logger name.
188,189c181
< *
< * Each logging event bears a sequence number.
---
> * A unique sequence number for this logging event.
193c185
< long sequenceNumber;
---
> private long sequenceNumber;
201c193,194
< * @return The current sequenceCount for this JVM.
---
> * Returns the sequence count for this JVM.
> * @return the current sequence count for this JVM
203,204c196
<
< public static long getSequenceCount() {
---
> public static synchronized long getSequenceCount() {
206a199
>
216d208
<
231,238c223
< this.fqnOfCategoryClass = fqnOfLoggerClass;
< this.logger = logger;
< this.categoryName = logger.getName();
< this.level = level;
< this.message = message;
<
< if (throwable != null) {
< this.throwableInfo = new ThrowableInformation(throwable);
---
> this(fqnOfLoggerClass, logger, System.currentTimeMillis(),
level, message, throwable);
241,248d225
< timeStamp = System.currentTimeMillis();
<
< synchronized(LoggingEvent.class) {
< sequenceNumber = sequenceCount++;
< }
< }
<
<
707d683
<
709c685
< *
---
> * Returns the sequence number.
716d691
<
718c693
< *
---
> * Sets the sequence number.
725c700,702
<
---
> /**
> * Returns the current thread name, or a past thread name
returned by this method.
> */
730d706
<
734d709
<
735a711
> * Sets the thread name.
747d722
<
966a942
>
sequenceCount has been much discussed on the list and has been long
slated to be removed due to the many issues involving it and its
inability to accomplish its original design goal.
Index: src/java/org/apache/log4j/watchdog/WatchdogSkeleton.java
===================================================================
125,141c125
<
< // if able to create configurator, then reconfigure using
input stream
< if (configurator != null) {
< configurator.doConfigure(srcURL, this.getLoggerRepository());
< if (configurator instanceof ConfiguratorBase) {
< ConfiguratorBase baseConfigurator = (ConfiguratorBase)
configurator;
< List errorList = baseConfigurator.getErrorList();
< if (errorList.size() != 0) {
< getLogger().error("errors reported during
reconfiguration: ");
< for (int x = 0; x < errorList.size(); x++) {
< getLogger().debug("error " + x + ": " + errorList.get
(x));
< }
< return false;
< }
< }
< }
< else {
---
> if (configurator == null) {
148c132,133
< return true;
---
> configurator.doConfigure(srcURL, this.getLoggerRepository());
> return configure(configurator);
165d149
< ConfiguratorEx configuratorEx = null;
168c152,154
< configuratorEx = (ConfiguratorEx)configurator;
---
> ConfiguratorEx configuratorEx = (ConfiguratorEx)configurator;
> configuratorEx.doConfigure(stream, this.getLoggerRepository
());
> return configure(configurator);
172a159
> return false;
175,179c162,166
< // if able to create configurator, then reconfigure using
input stream
< if (configuratorEx != null) {
< configuratorEx.doConfigure(stream, this.getLoggerRepository
());
< if (configuratorEx instanceof ConfiguratorBase) {
< ConfiguratorBase baseConfigurator = (ConfiguratorBase)
configuratorEx;
---
> }
>
> private boolean configure(Configurator configurator) {
> if (configurator instanceof ConfiguratorBase) {
> ConfiguratorBase baseConfigurator = (ConfiguratorBase)
configurator;
181d167
< getLogger().error("errors reported during
reconfiguration: ");
182a169
> getLogger().error("errors reported during
reconfiguration: ");
189,196d175
< }
< else {
< getLogger().error(
< "watchdog \"{}\" could not create configurator, ignoring
new configuration settings",
< this.getName());
< return false;
< }
<
So, dead code path elimination?
Index: src/java/org/apache/log4j/Priority.java
===================================================================
150a151,158
> * Returns a hash code based on the level.
> */
> public
> int hashCode() {
> return level;
> }
>
> /**
Looks okay.
Index: src/java/org/apache/log4j/helpers/SyslogWriter.java
===================================================================
41,42c41
< final int SYSLOG_PORT = 514;
< String syslogHost;
---
> static final int SYSLOG_PORT = 514;
59d57
< this.syslogHost = syslogHost;
Can't switch an non-private instance member to a class member without
breaking compatibility.
Index: src/java/org/apache/log4j/helpers/UtilLoggingLevel.java
===================================================================
33a34,35
> private static final long serialVersionUID = 909301162611820211L;
>
Index: src/java/org/apache/log4j/helpers/PatternParser.java
===================================================================
472c472
< private class LocationPatternConverter extends PatternConverter {
---
> private static class LocationPatternConverter extends
PatternConverter {
Index: src/java/org/apache/log4j/jdbc/JDBCAppender.java
===================================================================
268a269
> super.finalize();
Index: src/java/org/apache/log4j/varia/StringMatchFilter.java
===================================================================
63c63
< this.setAcceptOnMatch(new Boolean(value).booleanValue());
---
> this.setAcceptOnMatch(Boolean.valueOf(value).booleanValue
());
Boolean.valueOf was added in JDK 1.4 and can't be used without
breaking log4j on earlier JDK's.
Index: src/java/org/apache/log4j/rolling/RollingFileAppender.java
===================================================================
409c409
< public void incrementFileLength(int increment) {
---
> public synchronized void incrementFileLength(int increment) {
Index: src/java/org/apache/log4j/rolling/FixedWindowRollingPolicy.java
===================================================================
64,74d63
< /**
< * Error message.
< */
< private static final String FNP_NOT_SET =
< "The FileNamePattern option must be set before using
FixedWindowRollingPolicy. ";
<
< /**
< * Link for error message.
< */
< private static final String SEE_FNP_NOT_SET =
< "See also http://logging.apache.org/log4j/
codes.html#tbr_fnp_not_set";
Index: src/java/org/apache/log4j/joran/spi/Pattern.java
===================================================================
22c22
< public class Pattern {
---
> public class Pattern implements Cloneable {
32,33c32,38
< Pattern p = new Pattern();
< p.components.addAll(this.components);
---
> Pattern p;
> try {
> p = (Pattern)super.clone();
> } catch (CloneNotSupportedException e) {
> throw new Error();
> }
> p.components = new ArrayList(components);
Index: src/java/org/apache/log4j/joran/action/LoggerFactoryAction.java
===================================================================
45d44
< @Override
Index: src/java/org/apache/log4j/joran/action/LevelAction.java
===================================================================
25,26d24
< boolean inError = false;
<
32d29
< inError = true;
Index: src/java/org/apache/log4j/joran/action/LayoutAction.java
===================================================================
76,79c76
< if (layout instanceof OptionHandler) {
< ((OptionHandler) layout).activateOptions();
< }
<
---
> layout.activateOptions();
Index: src/java/org/apache/log4j/joran/action/
ConversionRuleAction.java
===================================================================
22,23d21
<
< import org.apache.log4j.Layout;
36,37d33
< Layout layout;
< boolean inError = false;
44,45d39
< // Let us forget about previous errors (in this object)
< inError = false;
54d47
< inError = true;
63d55
< inError = true;
88d79
< inError = true;
Index: src/java/org/apache/log4j/joran/action/NewRuleAction.java
===================================================================
28d27
< boolean inError = false;
35,36d33
< // Let us forget about previous errors (in this object)
< inError = false;
42d38
< inError = true;
50d45
< inError = true;
61d55
< inError = true;
Index: src/java/org/apache/log4j/joran/action/AppenderRefAction.java
===================================================================
34d33
< boolean inError = false;
38,41d36
< // Let us forget about previous errors (in this object)
< inError = false;
<
< //logger.debug("begin called");
51d45
< inError = true;
66d59
< inError = true;
81d73
< inError = true;
Index: src/java/org/apache/log4j/joran/action/PluginAction.java
===================================================================
91,94c91
< if (plugin instanceof OptionHandler) {
< ((OptionHandler) plugin).activateOptions();
< }
<
---
> plugin.activateOptions();
Index: src/java/org/apache/log4j/joran/action/ParamAction.java
===================================================================
30d29
< boolean inError = false;
38d36
< inError = true;
45d42
< inError = true;
Index: src/java/org/apache/log4j/nt/NTEventLogAppender.java
===================================================================
21d20
< import org.apache.log4j.Level;
23d21
< import org.apache.log4j.helpers.LogLog;
26d23
<
40,44d36
< private static final int FATAL = Level.FATAL.toInt();
< private static final int ERROR = Level.ERROR.toInt();
< private static final int WARN = Level.WARN.toInt();
< private static final int INFO = Level.INFO.toInt();
< private static final int DEBUG = Level.DEBUG.toInt();
146a139
> super.finalize();
Index: src/java/org/apache/log4j/net/test/SocketMin.java
===================================================================
23a24,25
>
> import java.io.IOException;
81a84
> try {
90,91c93
< try {i = in.read(); }
< catch(Exception e) { return; }
---
> i = in.read();
98a101,102
> } catch (IOException e) {
> }
Index: src/java/org/apache/log4j/net/UDPAppender.java
===================================================================
55,56d54
< private static final int PACKET_LENGTH = 16384;
<
69d66
< int count = 0;
Index: src/java/org/apache/log4j/net/SocketReceiver.java
===================================================================
56d55
< private boolean shutdown;
116d114
< setShutdown(false);
152,153d149
<
< setShutdown(true);
207d202
< setShutdown(true);
332,346d326
< /**
< * Returns the shutdown property of this Receiver
< * @return
< */
< private boolean isShutdown() {
< return shutdown;
< }
<
< /**
< * @param b
< */
< private void setShutdown(boolean b) {
< shutdown = b;
< }
<
Index: src/java/org/apache/log4j/net/JMSSink.java
===================================================================
80c80
< // Loop until the word "exit" is typed
---
> // Loop until the word "exit" is typed or EOF
84c84
< if (s.equalsIgnoreCase("exit")) {
---
> if (s == null || s.equalsIgnoreCase("exit")) {
Index: src/java/org/apache/log4j/net/JMSReceiver.java
===================================================================
204a205
> FileInputStream is = new FileInputStream(jndiPath);
206c207,208
< p.load(new FileInputStream(jndiPath));
---
> p.load(is);
> is.close();
Index: src/java/org/apache/log4j/net/MulticastAppender.java
===================================================================
56,57d55
< private static final int PACKET_LENGTH = 16384;
<
70d67
< int count = 0;
Index: src/java/org/apache/log4j/Hierarchy.java
===================================================================
98d97
< boolean emittedNoResourceBundleWarning = false;
Index: src/java/org/apache/log4j/jmx/LayoutDynamicMBean.java
===================================================================
24d23
< import org.apache.log4j.spi.OptionHandler;
155,158c154,155
< if(operationName.equals("activateOptions") &&
< layout instanceof OptionHandler) {
< OptionHandler oh = (OptionHandler) layout;
< oh.activateOptions();
---
> if(operationName.equals("activateOptions")) {
> layout.activateOptions();
Index: src/java/org/apache/log4j/jmx/AbstractDynamicMBean.java
===================================================================
19d18
< //import java.lang.reflect.Constructor;
34c33
< String dClassName;
---
> private String dClassName = getClass().getName();
124d122
< this.server = server;
Can't make restrict visibility of member without breaking compatibility.
Index: src/java/org/apache/log4j/config/PropertyGetter.java
===================================================================
19a20
> import org.apache.log4j.spi.ComponentBase;
31c32
< public class PropertyGetter {
---
> public class PropertyGetter extends ComponentBase {
63a65
> String name = props[i].getName();
65c67
< //System.err.println("Ignoring " + props[i].getName() +"
" + getter.getReturnType());
---
> getLogger().warn("Ignoring " + name +" " +
getter.getReturnType());
68d69
< String name = props[i].getName();
72c73
< //System.err.println("PROP " + name +": " + result);
---
> getLogger().debug("PROP " + name +": " + result);
76,77c77,78
< } catch (Exception ex) {
< //LogLog.warn("Failed to get value of property " + name);
---
> } catch (Exception e) {
> getLogger().warn("Failed to get value of property " +
name, e);
What did findbugs say that suggested that you change the inheritance
hierarchy of the class?
Index: src/java/org/apache/log4j/lbel/Parser.java
===================================================================
4d3
< import java.util.Stack;
55d53
< Stack stack = new Stack();
Index: src/java/org/apache/log4j/scheduler/Scheduler.java
===================================================================
203a204
> while (jobList.isEmpty() && !shutdown)
Index: tests/input/watchdog/watchdog.FileWatchdog.test2_1.properties
===================================================================
14c14
< log4j.appender.A2.layout.ConversionPattern=%d{ABSOLUTE} %c [%p] -
%m%n
---
> log4j.appender.A2.layout.ConversionPattern=%d{ABSOLUTE} - TEST2_1
- %c{1} [%p] - %m%n
Index: tests/input/watchdog/watchdog.FileWatchdog.test2_2.properties
===================================================================
2a3
> log4j.rootLogger=DEBUG,A2
9a11,14
> log4j.appender.A2=org.apache.log4j.ConsoleAppender
> log4j.appender.A2.layout=org.apache.log4j.PatternLayout
> log4j.appender.A2.layout.ConversionPattern=%d{ABSOLUTE} - TEST2_2
- %c{1} [%p] - %m%n
>
Index: tests/src/java/org/apache/log4j/concurrent/
FileAppenderTest.java
===================================================================
71a72,75
> readHI();
> }
>
> private void readHI() throws Exception {
73a78
> r.close();
83,84c88
< BufferedReader r = new BufferedReader(new FileReader(f1));
< assertEquals("DEBUG - HI", r.readLine());
---
> readHI();
Index: tests/src/java/org/apache/log4j/db/
BindDataSourceToJNDIAction.java
===================================================================
50d49
< private boolean inError = false;
91,94c90,91
< } catch (Exception oops) {
< inError = true;
< logger.error(
< "Could not bind datasource. Reported error follows.",
oops);
---
> } catch (Exception e) {
> logger.error("Could not bind datasource", e);
97c94
< "Could not not bind datasource of type [" +
dsClassName + "]."));
---
> "Could not not bind datasource of type [" + dsClassName
+ "]"));
Index: tests/src/java/org/apache/log4j/spi/
ThrowableInformationTest.java
===================================================================
58a59,61
>
> assertEquals(te1.hashCode(), te1.hashCode());
> assertEquals(te2.hashCode(), te2.hashCode());
Index: tests/src/java/org/apache/log4j/watchdog/
FileWatchdogTestCase.java
===================================================================
46a47,52
> protected void setUp() throws Exception {
> LogManager.getLoggerRepository().resetConfiguration();
> logger.setLevel(Level.DEBUG);
> Thread.sleep(100);
> }
>
113,114d118
< LogManager.getLoggerRepository().resetConfiguration();
< logger.setLevel(Level.DEBUG);
197,199d200
< LogManager.getLoggerRepository().resetConfiguration();
< logger.setLevel(Level.DEBUG);
<
201,203c202
< if (outFile.exists()) {
< assertTrue(outFile.delete());
< }
---
> delete(outFile);
281,283d279
< LogManager.getLoggerRepository().resetConfiguration();
< logger.setLevel(Level.DEBUG);
<
285,287c281
< if (outFile.exists()) {
< assertTrue(outFile.delete());
< }
---
> delete(outFile);
297c291
< assertFalse(configFile.exists());
---
> delete(configFile);
360,362c354,358
< public void testPropertyConfigurationError() throws Exception {
< LogManager.getLoggerRepository().resetConfiguration();
< logger.setLevel(Level.DEBUG);
---
> private void delete(File f) {
> if (f.exists()) {
> assertTrue(f.delete());
> }
> }
363a360
> public void testPropertyConfigurationError() throws Exception {
365,367c362
< if (outFile.exists()) {
< assertTrue(outFile.delete());
< }
---
> delete(outFile);
376d370
< // config file should not exist yet
378c372,373
< assertFalse(configFile.exists());
---
> delete(configFile);
> // assertFalse(configFile.exists());
444,446d438
< LogManager.getLoggerRepository().resetConfiguration();
< logger.setLevel(Level.DEBUG);
<
517,519d508
< LogManager.getLoggerRepository().resetConfiguration();
< logger.setLevel(Level.DEBUG);
<
Index: tests/src/java/org/apache/log4j/html/Loop.java
===================================================================
28c28
< *
---
> * Tests HTML layout.
32c32
< public static Logger logger = Logger.getLogger(Loop.class);
---
> public static final Logger logger = Logger.getLogger(Loop.class);
Index: tests/src/java/org/apache/log4j/joran/action/TouchAction.java
===================================================================
27c27
< public static String KEY = "touched";
---
> public static final String KEY = "touched";
Index: tests/src/java/org/apache/log4j/joran/action/
StackCounterAction.java
===================================================================
19,20d18
< import org.apache.log4j.Layout;
< import org.apache.log4j.Logger;
26d23
<
28,30d24
< static final Logger logger = Logger.getLogger(HelloAction.class);
< Layout layout;
<
34,37c28
< /**
< * Instantiates an layout of the given class and sets its name.
< *
< */
---
>
39d29
< String str = "Pushing "+name+"-begin";
43,46d32
< /**
< * Once the children elements are also parsed, now is the time
to activate
< * the appender options.
< */
48d33
< String str = "Pushing "+name+"-end";
Index: tests/src/java/org/apache/log4j/xml/XLevel.java
===================================================================
27a28,30
>
> private static final long serialVersionUID = 7288304330257085144L;
>
Index: tests/src/java/org/apache/log4j/xml/XMLLayoutTest.java
===================================================================
141c141
< assertEquals(msg, messageNode.getNodeValue().substring(0,
msg.length()));
---
> assertEquals("Got " + messageNode.getNodeValue(), msg,
messageNode.getNodeValue().substring(0, msg.length()));
Index: tests/src/java/org/apache/log4j/util/Transformer.java
===================================================================
19,21c19,24
< import java.io.*;
<
< import org.apache.oro.text.perl.Perl5Util;
---
> import java.io.BufferedReader;
> import java.io.FileNotFoundException;
> import java.io.FileOutputStream;
> import java.io.FileReader;
> import java.io.IOException;
> import java.io.PrintStream;
31d33
< Perl5Util util = new Perl5Util();
35a38
> try {
45a49,52
> } finally {
> input.close();
> output.close();
> }
56d62
< Perl5Util util = new Perl5Util();
60a67
> try {
65a73,76
> } finally {
> input.close();
> output.close();
> }
Index: tests/src/java/org/apache/log4j/util/Compare.java
===================================================================
35a36,44
> try {
> return compare(file1, file2, in1, in2);
> } finally {
> in1.close();
> in2.close();
> }
> }
>
> public static boolean compare(String file1, String file2,
BufferedReader in1, BufferedReader in2) throws IOException {
100a110
> in1.close();
106a117,125
> try {
> return gzCompare(file1, file2, in1, in2);
> } finally {
> in1.close();
> in2.close();
> }
> }
>
> public static boolean gzCompare(String file1, String file2,
BufferedReader in1, BufferedReader in2) throws IOException {
Index: tests/src/java/org/apache/log4j/util/BinaryCompare.java
===================================================================
21a22
> import java.io.InputStream;
30a32,40
> /**
> * Compares two files using binary comparison.
> *
> * @param file1
> * @param file2
> * @return true if they are the same
> * @throws FileNotFoundException
> * @throws IOException
> */
36a47,54
> try {
> return compare(file1, file2, in1, in2);
> } finally {
> in1.close();
> in2.close();
> }
>
> }
37a56
> private static boolean compare(final String file1, final
String file2, InputStream in1, InputStream in2) throws IOException {
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]