public class

Utility

extends Object
//  The contents of this file are subject to the Mozilla Public License
//  Version 1.1 (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.mozilla.org/MPL/
//
//  Software distributed under the License is distributed on an "AS IS"
//  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
//  the License for the specific language governing rights and
//  limitations under the License.
//
//  The Original Code is RabbitMQ.
//
//  The Initial Developer of the Original Code is VMware, Inc.
//  Copyright (c) 2007-2011 VMware, Inc.  All rights reserved.
//

package com.rabbitmq.utility;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;

/**
 * Catch-all holder class for static helper methods.
 */

public class Utility {
    static class ThrowableCreatedElsewhere extends Throwable {
        /** Default for non-checking. */
        private static final long serialVersionUID = 1L;

        public ThrowableCreatedElsewhere(Throwable throwable) {
          super(throwable.getClass() + " created elsewhere");
          this.setStackTrace(throwable.getStackTrace());
        }

        @Override public Throwable fillInStackTrace(){ 
            return this; 
        } 
    }

    public static <T extends Throwable & SensibleClone<T>> T fixStackTrace(T throwable) {
      throwable = throwable.sensibleClone();

      if(throwable.getCause() == null) {
        // We'd like to preserve the original stack trace in the cause.
        // Unfortunately Java doesn't let you set the cause once it's been
        // set once. This means we have to choose between either 
        //  - not preserving the type
        //  - sometimes losing the original stack trace
        //  - performing nasty reflective voodoo which may or may not work
        // We only lose the original stack trace when there's a root cause
        // which will hopefully be enlightening enough on its own that it 
        // doesn't matter too much. 
        try {
          throwable.initCause(new ThrowableCreatedElsewhere(throwable));
        } catch(IllegalStateException e) {
          // This exception was explicitly initialised with a null cause. 
          // Alas this means we can't set the cause even though it has none. 
          // Thanks. 
        }
      }


      throwable.fillInStackTrace();
      // We want to remove fixStackTrace from the trace.
      StackTraceElement[] existing = throwable.getStackTrace();
      StackTraceElement[] newTrace = new StackTraceElement[existing.length - 1];
      System.arraycopy(existing, 1, newTrace, 0, newTrace.length);
      throwable.setStackTrace(newTrace);
      return throwable;
    }

  
    public static String makeStackTrace(Throwable throwable) {
        ByteArrayOutputStream baOutStream = new ByteArrayOutputStream();
        PrintStream printStream = new PrintStream(baOutStream, false);
        throwable.printStackTrace(printStream);
        printStream.flush(); // since we don't automatically do so
        String text = baOutStream.toString();
        printStream.close(); // closes baOutStream
        return text;
    }

    /**
     * Used to indicate that we are not, in fact, using a variable, also to silence compiler warnings.
     *
     * @param value the object we're pretending to use
     */
    public static void use(Object value) {
        if (value != null) {
            return;
        }
    }

    /**
     * Similarly, for situations where an empty statement is required
     */
    public static void emptyStatement() {
        use(null);
    }
}