mirror of https://github.com/apache/lucene.git
LUCENE-3334: If Java7 is detected, IOUtils.closeSafely() will log suppressed exceptions in the original exception, so stack trace will contain them
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1150405 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
870a4ce9f9
commit
1b8c3f1de9
|
@ -531,6 +531,10 @@ Bug fixes
|
|||
corrupt index if a term with docfreq >= 16 was indexed more than once
|
||||
at the same position. (Robert Muir)
|
||||
|
||||
* LUCENE-3334: If Java7 is detected, IOUtils.closeSafely() will log
|
||||
suppressed exceptions in the original exception, so stack trace
|
||||
will contain them. (Uwe Schindler)
|
||||
|
||||
New Features
|
||||
|
||||
* LUCENE-3290: Added FieldInvertState.numUniqueTerms
|
||||
|
|
|
@ -19,8 +19,11 @@ package org.apache.lucene.util;
|
|||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/** @lucene.internal */
|
||||
/** This class emulates the new Java 7 "Try-With-Resources" statement.
|
||||
* Remove once Lucene is on Java 7.
|
||||
* @lucene.internal */
|
||||
public final class IOUtils {
|
||||
|
||||
private IOUtils() {} // no instance
|
||||
|
@ -55,6 +58,7 @@ public final class IOUtils {
|
|||
object.close();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
addSuppressed((priorException == null) ? th : priorException, t);
|
||||
if (th == null) {
|
||||
th = t;
|
||||
}
|
||||
|
@ -81,6 +85,7 @@ public final class IOUtils {
|
|||
object.close();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
addSuppressed((priorException == null) ? th : priorException, t);
|
||||
if (th == null) {
|
||||
th = t;
|
||||
}
|
||||
|
@ -118,6 +123,7 @@ public final class IOUtils {
|
|||
object.close();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
addSuppressed(th, t);
|
||||
if (th == null)
|
||||
th = t;
|
||||
}
|
||||
|
@ -143,6 +149,7 @@ public final class IOUtils {
|
|||
object.close();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
addSuppressed(th, t);
|
||||
if (th == null)
|
||||
th = t;
|
||||
}
|
||||
|
@ -156,4 +163,30 @@ public final class IOUtils {
|
|||
}
|
||||
}
|
||||
|
||||
/** This reflected {@link Method} is {@code null} before Java 7 */
|
||||
private static final Method SUPPRESS_METHOD;
|
||||
static {
|
||||
Method m;
|
||||
try {
|
||||
m = Throwable.class.getMethod("addSuppressed", Throwable.class);
|
||||
} catch (Exception e) {
|
||||
m = null;
|
||||
}
|
||||
SUPPRESS_METHOD = m;
|
||||
}
|
||||
|
||||
/** adds a Throwable to the list of suppressed Exceptions of the first Throwable (if Java 7 is detected)
|
||||
* @param exception this exception should get the suppressed one added
|
||||
* @param suppressed the suppressed exception
|
||||
*/
|
||||
private static final void addSuppressed(Throwable exception, Throwable suppressed) {
|
||||
if (SUPPRESS_METHOD != null && exception != null && suppressed != null) {
|
||||
try {
|
||||
SUPPRESS_METHOD.invoke(exception, suppressed);
|
||||
} catch (Exception e) {
|
||||
// ignore any exceptions caused by invoking (e.g. security constraints)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
package org.apache.lucene.util;
|
||||
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
* (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
public class TestIOUtils extends LuceneTestCase {
|
||||
|
||||
static final class BrokenCloseable implements Closeable {
|
||||
final int i;
|
||||
|
||||
public BrokenCloseable(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
throw new IOException("TEST-IO-EXCEPTION-" + i);
|
||||
}
|
||||
}
|
||||
|
||||
static final class TestException extends Exception {
|
||||
public TestException() {
|
||||
super("BASE-EXCEPTION");
|
||||
}
|
||||
}
|
||||
|
||||
public void testSuppressedExceptions() {
|
||||
boolean isJava7 = true;
|
||||
try {
|
||||
// this class only exists in Java 7:
|
||||
Class.forName("java.lang.AutoCloseable");
|
||||
} catch (ClassNotFoundException cnfe) {
|
||||
isJava7 = false;
|
||||
}
|
||||
|
||||
if (!isJava7) {
|
||||
System.err.println("WARNING: TestIOUtils.testSuppressedExceptions: Full test coverage only with Java 7, as suppressed exception recording is not supported before.");
|
||||
}
|
||||
|
||||
// test with prior exception
|
||||
try {
|
||||
final TestException t = new TestException();
|
||||
IOUtils.closeSafely(t, new BrokenCloseable(1), new BrokenCloseable(2));
|
||||
} catch (TestException e1) {
|
||||
assertEquals("BASE-EXCEPTION", e1.getMessage());
|
||||
final StringWriter sw = new StringWriter();
|
||||
final PrintWriter pw = new PrintWriter(sw);
|
||||
e1.printStackTrace(pw);
|
||||
pw.flush();
|
||||
final String trace = sw.toString();
|
||||
if (VERBOSE) {
|
||||
System.out.println("TestIOUtils.testSuppressedExceptions: Thrown Exception stack trace:");
|
||||
System.out.println(trace);
|
||||
}
|
||||
if (isJava7) {
|
||||
assertTrue("Stack trace does not contain first suppressed Exception: " + trace,
|
||||
trace.contains("java.io.IOException: TEST-IO-EXCEPTION-1"));
|
||||
assertTrue("Stack trace does not contain second suppressed Exception: " + trace,
|
||||
trace.contains("java.io.IOException: TEST-IO-EXCEPTION-2"));
|
||||
}
|
||||
} catch (IOException e2) {
|
||||
fail("IOException should not be thrown here");
|
||||
}
|
||||
|
||||
// test without prior exception
|
||||
try {
|
||||
IOUtils.closeSafely((TestException) null, new BrokenCloseable(1), new BrokenCloseable(2));
|
||||
} catch (TestException e1) {
|
||||
fail("TestException should not be thrown here");
|
||||
} catch (IOException e2) {
|
||||
assertEquals("TEST-IO-EXCEPTION-1", e2.getMessage());
|
||||
final StringWriter sw = new StringWriter();
|
||||
final PrintWriter pw = new PrintWriter(sw);
|
||||
e2.printStackTrace(pw);
|
||||
pw.flush();
|
||||
final String trace = sw.toString();
|
||||
if (VERBOSE) {
|
||||
System.out.println("TestIOUtils.testSuppressedExceptions: Thrown Exception stack trace:");
|
||||
System.out.println(trace);
|
||||
}
|
||||
if (isJava7) {
|
||||
assertTrue("Stack trace does not contain suppressed Exception: " + trace,
|
||||
trace.contains("java.io.IOException: TEST-IO-EXCEPTION-2"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue