Skip to content

Commit b77e576

Browse files
author
David R. MacIver
committed
merge default into branch
2 parents 88ac53d + 0c06613 commit b77e576

File tree

10 files changed

+139
-20
lines changed

10 files changed

+139
-20
lines changed

src/com/rabbitmq/client/Channel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
*
6262
*/
6363

64-
public interface Channel extends ShutdownNotifier{
64+
public interface Channel extends ShutdownNotifier {
6565
/**
6666
* Retrieve this channel's channel number.
6767
* @return the channel number

src/com/rabbitmq/client/ShutdownSignalException.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
//
3131
package com.rabbitmq.client;
3232

33+
import com.rabbitmq.utility.SensibleClone;
34+
3335
/**
3436
* Encapsulates a shutdown condition for a connection to an AMQP broker.
3537
* Depending on HardError when calling
@@ -38,7 +40,7 @@
3840
* this exception.
3941
*/
4042

41-
public class ShutdownSignalException extends RuntimeException {
43+
public class ShutdownSignalException extends RuntimeException implements SensibleClone<ShutdownSignalException> {
4244
/** True if the connection is shut down, or false if this signal refers to a channel */
4345
private final boolean _hardError;
4446

@@ -92,6 +94,14 @@ public ShutdownSignalException(boolean hardError,
9294
/** @return Reference to Connection or Channel object that fired the signal **/
9395
public Object getReference() { return _ref; }
9496

97+
public ShutdownSignalException sensibleClone() {
98+
try {
99+
return (ShutdownSignalException)super.clone();
100+
} catch (CloneNotSupportedException e) {
101+
// You've got to be kidding me
102+
throw new Error(e);
103+
}
104+
}
95105
}
96106

97107

src/com/rabbitmq/utility/BlockingValueOrException.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
import java.util.concurrent.TimeoutException;
3434

35-
public class BlockingValueOrException<V, E extends Throwable>
35+
public class BlockingValueOrException<V, E extends Throwable & SensibleClone<E>>
3636
extends BlockingCell<ValueOrException<V, E>>
3737
{
3838
public void setValue(V v) {
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// The contents of this file are subject to the Mozilla Public License
2+
// Version 1.1 (the "License"); you may not use this file except in
3+
// compliance with the License. You may obtain a copy of the License at
4+
// http://www.mozilla.org/MPL/
5+
//
6+
// Software distributed under the License is distributed on an "AS IS"
7+
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
8+
// License for the specific language governing rights and limitations
9+
// under the License.
10+
//
11+
// The Original Code is RabbitMQ.
12+
//
13+
// The Initial Developers of the Original Code are LShift Ltd,
14+
// Cohesive Financial Technologies LLC, and Rabbit Technologies Ltd.
15+
//
16+
// Portions created before 22-Nov-2008 00:00:00 GMT by LShift Ltd,
17+
// Cohesive Financial Technologies LLC, or Rabbit Technologies Ltd
18+
// are Copyright (C) 2007-2008 LShift Ltd, Cohesive Financial
19+
// Technologies LLC, and Rabbit Technologies Ltd.
20+
//
21+
// Portions created by LShift Ltd are Copyright (C) 2007-2009 LShift
22+
// Ltd. Portions created by Cohesive Financial Technologies LLC are
23+
// Copyright (C) 2007-2009 Cohesive Financial Technologies
24+
// LLC. Portions created by Rabbit Technologies Ltd are Copyright
25+
// (C) 2007-2009 Rabbit Technologies Ltd.
26+
//
27+
// All Rights Reserved.
28+
//
29+
// Contributor(s): ______________________________________.
30+
//
31+
package com.rabbitmq.utility;
32+
33+
/**
34+
* This interface exists as a workaround for the annoyingness of java.lang.Cloneable.
35+
* It is used for generic methods which need to accept something they can actually clone
36+
* (Object.clone is protected and java.lang.Cloneable does not define a public clone method)
37+
* and want to provide some guarantees of the type of the cloned object.
38+
*/
39+
public interface SensibleClone<T extends SensibleClone<T>> extends Cloneable {
40+
41+
/**
42+
* Like Object.clone but sensible; in particular, public and declared to return
43+
* the right type.
44+
*/
45+
public T sensibleClone();
46+
}

src/com/rabbitmq/utility/Utility.java

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,50 @@
3939
*/
4040

4141
public class Utility {
42+
static class ThrowableCreatedElsewhere extends Throwable {
43+
public ThrowableCreatedElsewhere(Throwable throwable) {
44+
super(throwable.getClass() + " created elsewhere");
45+
this.setStackTrace(throwable.getStackTrace());
46+
}
47+
48+
@Override public Throwable fillInStackTrace(){
49+
return this;
50+
}
51+
}
52+
53+
public static <T extends Throwable & SensibleClone<T>> T fixStackTrace(T throwable) {
54+
throwable = throwable.sensibleClone();
55+
56+
if(throwable.getCause() == null) {
57+
// We'd like to preserve the original stack trace in the cause.
58+
// Unfortunately Java doesn't let you set the cause once it's been
59+
// set once. This means we have to choose between either
60+
// - not preserving the type
61+
// - sometimes losing the original stack trace
62+
// - performing nasty reflective voodoo which may or may not work
63+
// We only lose the original stack trace when there's a root cause
64+
// which will hopefully be enlightening enough on its own that it
65+
// doesn't matter too much.
66+
try {
67+
throwable.initCause(new ThrowableCreatedElsewhere(throwable));
68+
} catch(IllegalStateException e) {
69+
// This exception was explicitly initialised with a null cause.
70+
// Alas this means we can't set the cause even though it has none.
71+
// Thanks.
72+
}
73+
}
74+
75+
76+
throwable.fillInStackTrace();
77+
// We want to remove fixStackTrace from the trace.
78+
StackTraceElement[] existing = throwable.getStackTrace();
79+
StackTraceElement[] newTrace = new StackTraceElement[existing.length - 1];
80+
System.arraycopy(existing, 1, newTrace, 0, newTrace.length);
81+
throwable.setStackTrace(newTrace);
82+
return throwable;
83+
}
4284

85+
4386
public static String makeStackTrace(Throwable throwable) {
4487
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
4588
PrintStream printStream = new PrintStream(outputStream);

src/com/rabbitmq/utility/ValueOrException.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
//
3131
package com.rabbitmq.utility;
3232

33-
public class ValueOrException<V, E extends Throwable> {
33+
public class ValueOrException<V, E extends Throwable & SensibleClone<E>> {
3434
private final boolean _useValue;
3535
private final V _value;
3636
private final E _exception;
@@ -57,7 +57,7 @@ private ValueOrException(V value, E exception, boolean useValue) {
5757
* @param value the value to wrap as a ValueOrException
5858
* @return the wrapped value
5959
*/
60-
public static <V, E extends Throwable> ValueOrException<V, E> makeValue(V value) {
60+
public static <V, E extends Throwable & SensibleClone<E>> ValueOrException<V, E> makeValue(V value) {
6161
return new ValueOrException<V, E>(value, null, true);
6262
}
6363

@@ -66,7 +66,7 @@ public static <V, E extends Throwable> ValueOrException<V, E> makeValue(V value)
6666
* @param exception the exception to wrap as a ValueOrException
6767
* @return the wrapped exception
6868
*/
69-
public static <V, E extends Throwable> ValueOrException<V, E> makeException(E exception) {
69+
public static <V, E extends Throwable & SensibleClone<E>> ValueOrException<V, E> makeException(E exception) {
7070
return new ValueOrException<V, E>(null, exception, false);
7171
}
7272

@@ -78,7 +78,7 @@ public V getValue() throws E {
7878
if (_useValue) {
7979
return _value;
8080
} else {
81-
throw _exception;
81+
throw Utility.fixStackTrace(_exception);
8282
}
8383
}
8484
}

test/src/com/rabbitmq/client/test/ValueOrExceptionTest.java

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,39 +30,59 @@
3030
//
3131
package com.rabbitmq.client.test;
3232

33-
import java.io.IOException;
34-
3533
import junit.framework.TestCase;
3634
import junit.framework.TestSuite;
3735

3836
import com.rabbitmq.utility.ValueOrException;
37+
import com.rabbitmq.utility.SensibleClone;
3938

4039

4140
public class ValueOrExceptionTest extends TestCase {
41+
public static class InsufficientMagicException extends Exception
42+
implements SensibleClone<InsufficientMagicException> {
43+
public InsufficientMagicException(String message) {
44+
super(message);
45+
}
46+
47+
public InsufficientMagicException sensibleClone() {
48+
return new InsufficientMagicException(getMessage());
49+
}
50+
}
51+
52+
4253
public static TestSuite suite()
4354
{
4455
TestSuite suite = new TestSuite("valueOrEx");
4556
suite.addTestSuite(ValueOrExceptionTest.class);
4657
return suite;
4758
}
4859

49-
public void testStoresValue() throws IOException {
60+
public void testStoresValue() throws InsufficientMagicException {
5061
Integer value = new Integer(3);
51-
ValueOrException<Integer, IOException> valueOrEx = ValueOrException.<Integer, IOException>makeValue(value);
5262

63+
ValueOrException<Integer, InsufficientMagicException> valueOrEx =
64+
ValueOrException.<Integer, InsufficientMagicException>makeValue(value);
65+
5366
Integer returnedValue = valueOrEx.getValue();
5467
assertTrue(returnedValue == value);
5568
}
5669

57-
public void testStoresException() {
58-
IOException exception = new IOException("dummy message");
59-
ValueOrException<Integer, IOException> valueOrEx = ValueOrException.<Integer, IOException>makeException(exception);
70+
public void testClonesException() {
71+
InsufficientMagicException exception =
72+
new InsufficientMagicException("dummy message");
73+
ValueOrException<Integer, InsufficientMagicException> valueOrEx
74+
= ValueOrException.makeException(exception);
6075

6176
try {
6277
valueOrEx.getValue();
6378
fail("Expected exception");
64-
} catch(IOException returnedException) {
65-
assertTrue(returnedException == exception);
79+
} catch(InsufficientMagicException returnedException) {
80+
assertTrue(returnedException != exception);
81+
assertEquals(returnedException.getMessage(), exception.getMessage());
82+
boolean inGetValue = false;
83+
for(StackTraceElement elt : returnedException.getStackTrace())
84+
inGetValue |= "getValue".equals(elt.getMethodName());
85+
assertTrue(inGetValue);
6686
}
6787
}
6888
}

test/src/com/rabbitmq/client/test/performance/ScalabilityTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ public static void main(String[] args) throws Exception {
213213
}
214214

215215

216-
public Results run() throws Exception{
216+
public Results run() throws Exception {
217217
Connection con = new ConnectionFactory().newConnection(params.host, params.port);
218218
Channel channel = con.createChannel();
219219

test/src/com/rabbitmq/client/test/server/DurableBindingLifecycle.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public void testDurableBindingRecovery() throws IOException {
7676

7777
restart();
7878

79-
for (int i = 0; i < N; i++){
79+
for (int i = 0; i < N; i++) {
8080
basicPublishVolatile(X, K);
8181
}
8282

@@ -113,7 +113,7 @@ public void testDurableBindingsDeletion() throws IOException {
113113

114114
declareDurableTopicExchange(X);
115115

116-
for (int i = 0; i < N; i++){
116+
for (int i = 0; i < N; i++) {
117117
basicPublishVolatile(X, K);
118118
}
119119

test/src/com/rabbitmq/examples/ManyConnections.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ public void run() {
9090

9191
public static void runChannel(int threadNumber,
9292
Connection conn,
93-
Channel ch){
93+
Channel ch) {
9494
try {
9595
int delayLen = (int) (1000 / rate);
9696
long startTime = System.currentTimeMillis();

0 commit comments

Comments
 (0)