Package org.nimbustools.messaging.gt4_0.common

Source Code of org.nimbustools.messaging.gt4_0.common.CommonUtil

/*
* Copyright 1999-2006 University of Chicago
*
* 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.nimbustools.messaging.gt4_0.common;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.axis.types.Duration;
import org.oasis.wsrf.faults.BaseFaultType;
import org.globus.wsrf.utils.FaultHelper;

import java.util.List;
import java.util.LinkedList;

@SuppressWarnings("unchecked")
public class CommonUtil {

    private static final Log logger =
            LogFactory.getLog(CommonUtil.class.getName());

    public static final String PRETTY_CAUSES_NUM_KEY =
                                    "nimbus.errors.parent.number";

    public static final String PRETTY_CAUSES_STACKTRACES =
                                    "nimbus.errors.stacktraces";

    public static Duration minutesToDuration(int minutes) {
        /*
        * false - non-negative duration
        * 0 years
        * 0 months
        * 0 days
        * 0 hours
        * # minutes
        * 0 seconds
        */
        return new Duration(false, 0, 0, 0, 0, minutes, 0);
    }

    public static Duration secondsToDuration(int seconds) {
        /*
        * false - non-negative duration
        * 0 years
        * 0 months
        * 0 days
        * 0 hours
        * 0 minutes
        * # seconds
        */
        return new Duration(false, 0, 0, 0, 0, 0, seconds);
    }

    /**
     * Converts duration into seconds.  The current Duration class
     * implementation does not support proper <, >, or even equals
     * operations.  Choosing to convert all Durations off to seconds
     * for comparison rather than extend and fix the Duration class
     * implementation.
     *
     * Max duration is max(int) seconds. This is around ~25k days.
     *
     * Assumes years and month are ZERO and negative is FALSE.  Years
     * and months cannot be compared reliably because they can only be
     * partially ordered.
     *
     * TODO: possibly incorporate this restriction into the service schema?
     *
     * TODO: what to do if these ints are made to overflow?
     *
     * Uses the
     * {@link Double#doubleToLongBits(double) doubleToLongBits}
     * method.
     *
     * @param dur Positive duration instance w/o years or months.
     * @return Number of seconds in the Duration instance.
     * @throws InvalidDurationException problem
     */
    public static int durationToSeconds(Duration dur)
            throws InvalidDurationException {

        final int days;
        final int hours;
        final int mins;
        final double secs;
        final Long longsecs;
        final int intsecs;

        if (dur.isNegative()) {
            throw new InvalidDurationException("Duration can not be negative.");
        }

        if (dur.getYears() != 0) {
            throw new InvalidDurationException("Years in duration must be " +
                    "zero.");
        }

        if (dur.getMonths() != 0) {
            throw new InvalidDurationException("Months in duration must be " +
                    "zero.");
        }
        // Convert each to next lowest, until we get to seconds.
        days = dur.getDays();
        hours = dur.getHours() + days * 24;
        mins = dur.getMinutes() + hours * 60;
        secs = dur.getSeconds() + mins * 60;

        // Convert to int

        longsecs = new Long(new Double(secs).longValue());
        intsecs = longsecs.intValue();
        if (intsecs == Integer.MAX_VALUE) {
            throw new InvalidDurationException("Duration can not be " +
                    "longer than ~25k days.");
        }
        return intsecs;
    }


    /**
     * Ceilings to nearest minute.
     * @param dur duration
     * @return nearest minute (cieling)
     * @throws InvalidDurationException problem
     */
    public static int durationToMinutes(Duration dur)
            throws InvalidDurationException {

        final int seconds = durationToSeconds(dur);
        return secondsToMinutes(seconds);
    }

    // Ceilings to nearest minute.
    public static int secondsToMinutes(int seconds) {
        if (seconds == 0) {
            return 0;
        } else {
            int minutes = seconds/60;
            if (seconds % 60 > 0) {
                minutes += 1;
            }
            return minutes;
        }
    }


    /**
     * Buck stops here...  Using this mostly to include a message in a
     * close-to-user exception, where the Throwable gets set to that
     * exception's cause (for debug mode stacktrace).
     *
     * For example:
     *
     * <code>throw new Exception(CommonStrings.genericExceptionMessageWrapper(t), t);</code>
     *
     * @param any some Throwable you have not dealt with
     * @return some kind of message, even a non-informative one.
     * @see #recurseForSomeString(Throwable)
     */
    public static String genericExceptionMessageWrapper(Throwable any) {

        // Bad if a user ever sees this contingency, always needs fix for the
        // next release.
        final String fallback = "[[ Sorry, could not find any problem " +
                "description. See debugging output for stacktrace and please " +
                "inform development list, including debugging output if " +
                "you can.";

        final String fallback_suffix = " ]]";

        if (any == null) {
            return fallback + fallback_suffix;
        }

        String message = any.getMessage();
        if (message == null) {
            message = recurseForSomeString(any);
        }
        if (message == null) {
            message = fallback + "  Problem name: \"" +
                            any.getClass().getName() + "\"" + fallback_suffix;
        }
        return message;
    }

    /**
     * todo: method description
     *
     * Makes use of <code>BaseFaultType</code> awareness, via
     * <code>#faultString(BaseFaultType)</code>
     *
     * @param throwable may be null
     * @return null or first encountered error description string
     * @see #faultString(org.oasis.wsrf.faults.BaseFaultType)
     */
    public static String recurseForSomeString(Throwable throwable) {

        Throwable t = throwable;

        while (true) {

            if (t == null) {
                return null;
            }

            String msg = t.getMessage();

            if (msg != null) {
                return msg; // *** RETURN ***
            }

            if (t instanceof BaseFaultType) {
                msg = faultString((BaseFaultType)t);

                if (msg == null) {
                    t = t.getCause();
                } else {
                    return msg; // *** RETURN ***
                }

            } else {
                t = t.getCause();
            }

        }
    }

    /**
     * finds the root cause and prints its error description or if there is no
     * error description, just its class name
     *
     * Makes use of <code>BaseFaultType</code> awareness, via
     * <code>#faultString(BaseFaultType)</code>
     *
     * @param throwable may be null
     * @param suffixClassChain if true, class names of all errors involved are
     *        tacked on to the string like: [[ classname --> classname --> ...]]
     * @param numIncludedParentMsgs if suffixClassChain is true, this is the
     *        number of parents up from cause to print the exception messages
     *        for in the chain msg (not just the parent types)
     * @param lookForSysProp if true, the "nimbus.errors.parent.number" will
     *        be consulted and could possibly override the choice for
     *        numIncludedParentMsgs
     * @return LAST encountered error description/classname, only null if
     *         input is null (there is neither a type nor message to report)
     */
    public static String recurseForRootString(final Throwable throwable,
                                              final boolean suffixClassChain,
                                              final int numIncludedParentMsgs,
                                              final boolean lookForSysProp) {
       

        int realNumIncludedParentMsgs = numIncludedParentMsgs;
        if (lookForSysProp) {
            final String numParentsString =
                        System.getProperty(PRETTY_CAUSES_NUM_KEY);

            try {
                if (numParentsString != null
                        && numParentsString.trim().length() != 0) {
                   realNumIncludedParentMsgs =
                           Integer.parseInt(numParentsString);
                }
            } catch (Throwable t2) {
                logger.error("Could not parse a number from the '" +
                        PRETTY_CAUSES_NUM_KEY + "' system property.");
            }
        }

        final String alsoStackTracesStr =
                        System.getProperty(PRETTY_CAUSES_STACKTRACES);

        boolean alsoStackTraces = false;
        if (alsoStackTracesStr != null &&
                alsoStackTracesStr.trim().equalsIgnoreCase("true")) {
            alsoStackTraces = true;
        }

        final List parentMsgs = new LinkedList();
        final List parentTypes = new LinkedList();
        final List parentStacktraces = new LinkedList();
        final StringBuffer buf = new StringBuffer();

        int numDeep = 0;

        Throwable t = throwable;
        Throwable lastt = null;

        while (true) {

            if (t == null) {
                return _doneRecursingForRootString(lastt,
                                                   numDeep,
                                                   buf,
                                                   suffixClassChain,
                                                   parentMsgs,
                                                   parentTypes,
                                                   realNumIncludedParentMsgs,
                                                   alsoStackTraces,
                                                   parentStacktraces);
            }

            numDeep += 1;

            String thisMsg = t.getMessage();
            if (thisMsg == null && t instanceof BaseFaultType) {
                thisMsg = faultString((BaseFaultType)t);
            }

            if (thisMsg == null) {

                if (t instanceof RuntimeException) {

                    final StringBuffer lilStack = new StringBuffer();
                    lilStack.append("No message, but RuntimeException so " +
                            "including part of the stack trace: [[ ");
                    lilStack.append("\n").append(t.getClass().getName());
                    final StackTraceElement[] runTimeTraces = t.getStackTrace();
                    for (int i = 0; i < runTimeTraces.length; i++) {
                        final StackTraceElement runTimeTrace = runTimeTraces[i];
                        lilStack.append("\n\t at ").append(runTimeTrace);

                        if (i == 10) {
                            final int remaining = runTimeTraces.length - i;
                            if (remaining > 0) {
                                lilStack.append("\n ...")
                                        .append(remaining)
                                        .append(" more.");
                            }
                            break;
                        }
                    }

                    lilStack.append("\n ]]");
                    thisMsg = lilStack.toString();

                } else {
                    thisMsg = "no message";
                }
            }

            final String thisType = t.getClass().getName();

            final Throwable thisCause = t.getCause();

            if (thisCause == null) {
                lastt = t;
                t = null;
                buf.append(thisMsg).append(" (").append(thisType).append(")");
            } else {
                // keep going deeper
                lastt = t;
                t = thisCause;
                parentMsgs.add(thisMsg);
                parentTypes.add(thisType);
                parentStacktraces.add(t.getStackTrace());
            }
        }
    }

    private static String _doneRecursingForRootString(
                                        final Throwable lastt,
                                        final int numDeep,
                                        final StringBuffer buf,
                                        final boolean suffixClassChain,
                                        final List parentMsgs,
                                        final List parentTypes,
                                        final int includedParentMsgs,
                                        final boolean alsoStackTraces,
                                        final List parentStacktraces) {

        if (numDeep == 0) {
            return null; // *** EARLY RETURN ***
        }
       
        if (numDeep == 1) {
            return buf.toString(); // *** EARLY RETURN ***
        }

        final String main = buf.toString();

        if (!suffixClassChain) {
            return main; // *** EARLY RETURN ***
        }

        final int numMsgs = parentMsgs.size();
        if (numMsgs != parentTypes.size()) {
            return main + "\n[[**** PROBLEM WITH ATTAINING CAUSE CHAIN: " +
                    "parentMsgs and parentTypes sizes do not match ****]]";
        }

        final StringBuffer retbuf = new StringBuffer(main);
        retbuf.append("\n[[**** Cause chain report ****]]");

        for (int i = 0; i < numMsgs; i++) {
            retbuf.append("\n  ");
            for (int j = 0; j < i; j++) {
                retbuf.append(" ");
            }
            final String type = (String) parentTypes.get(i);
            retbuf.append("caused by (#").append(i+1).append("): ").append(type);
        }
        retbuf.append("\n");
       
        int startIncluding = numMsgs - includedParentMsgs;
        if (startIncluding < 0) {
            startIncluding = 0;
        }

        for (int i = 0; i < numMsgs; i++) {
            if (i >= startIncluding) {
                retbuf.append("\n");
                final String msg = (String) parentMsgs.get(i);
                retbuf.append("Message for #")
                      .append(i+1)
                      .append(":\n")
                      .append(msg);
                if (includedParentMsgs > 1) {
                    retbuf.append("\n========================================");
                }

                if (alsoStackTraces) {

                    final String thisTraceName = "Stacktrace for #" + (i+1);
                   
                    retbuf.append("\n\n")
                          .append(thisTraceName)
                          .append(":\n")
                          .append(msg);

                    final StackTraceElement[] traces =
                            (StackTraceElement[]) parentStacktraces.get(i);

                    if (traces == null || traces.length == 0) {
                        retbuf.append("     no stacktrace available (?)");
                    } else {
                        for (int j = 0; j < traces.length; j++) {
                            final StackTraceElement trace = traces[j];
                            retbuf.append("\tat ").append(trace).append("\n");
                        }
                    }

                    retbuf.append("\n(END ").append(thisTraceName).append(")");

                    if (includedParentMsgs > 1) {
                        retbuf.append("\n========================================");
                    }
                    retbuf.append("\n");
                }
            }
        }

        retbuf.append("\n\nOriginal message:\n").append(main);

        if (alsoStackTraces) {
            retbuf.append("\nStacktrace for original problem: ");
            if (lastt == null) {
                retbuf.append("     no throwable available (?)");
            } else {

                final StackTraceElement[] traces = lastt.getStackTrace();
                if (traces == null || traces.length == 0) {
                    retbuf.append("     no stacktrace available (?)");
                } else {
                    for (int j = 0; j < traces.length; j++) {
                        final StackTraceElement trace = traces[j];
                        retbuf.append("\tat ").append(trace).append("\n");
                    }
                }
            }
            retbuf.append("\n(END stacktrace for original problem)");
        }
       
        retbuf.append("\n[[**** end of cause chain report ****]]\n\n");
        return retbuf.toString();
    }


    /**
     * todo: method description
     *
     * @param e may be null
     * @return null if input is null, first encountered error description, or class name
     */
    public static String faultString(BaseFaultType e) {

        if (e == null) {
            return null;
        }

        final FaultHelper helper = new FaultHelper(e);
        final String[] descriptions = helper.getDescription();

        if (descriptions == null || descriptions.length == 0) {

            // Decided that anything recursing into BaseFaultType causes for
            // strings via #getCause(), such as #recurseForSomeString(), is
            // not going to find anything.

            return "Fault without any problem description: " +
                                            e.getClass().getName();
        }

        final StringBuffer buf = new StringBuffer(2048);

        buf.append(descriptions[0]);

        if (descriptions.length > 1) {
            for (int i = 1; i < descriptions.length; i++) {
                buf.append(" || ")
                   .append(descriptions[i]);
            }
        }
        return buf.toString();
    }
}
TOP

Related Classes of org.nimbustools.messaging.gt4_0.common.CommonUtil

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.