All Downloads are FREE. Search and download functionalities are using the official Maven repository.

flex.messaging.MessageException Maven / Gradle / Ivy

/*
 * 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.
 */
package flex.messaging;

import java.util.Map;

import flex.messaging.log.Log;
import flex.messaging.log.LogCategories;
import flex.messaging.log.LogEvent;
import flex.messaging.messages.ErrorMessage;
import flex.messaging.messages.Message;
import flex.messaging.util.ExceptionUtil;
import flex.messaging.util.PropertyStringResourceLoader;
import flex.messaging.util.ResourceLoader;
import flex.messaging.util.StringUtils;

/**
 * The MessageException class is the basic exception type used throughout
 * the server.  This class is extended to support more specific exception types.
 */
public class MessageException extends LocalizedException
{
    //--------------------------------------------------------------------------
    //
    // Static Constants
    //
    //--------------------------------------------------------------------------

    // Message exception code strings.
    public static final String CODE_SERVER_RESOURCE_UNAVAILABLE = "Server.ResourceUnavailable";


    static final long serialVersionUID = 3310842114461162689L;

    //--------------------------------------------------------------------------
    //
    // Constructors
    //
    //--------------------------------------------------------------------------

    /**
     * Default constructor.
     */
    public MessageException()
    {
    }

    /**
     * Construct a message specifying a ResourceLoader to be used to load localized strings.
     *
     * @param loader
     */
    public MessageException(ResourceLoader loader)
    {
        super(loader);
    }

    /**
     * Constructor with a message.
     *
     * @param message The detailed message for the exception.
     */
    public MessageException(String message)
    {
        setMessage(message);
    }

    /**
     * Constructs a new exception with the specified message and the Throwable as the root cause.
     *
     * @param message The detailed message for the exception.
     * @param t The root cause of the exception.
     */
    public MessageException(String message, Throwable t)
    {
        setMessage(message);
        setRootCause(t);
    }

    /**
     * Constructs a new exception with the specified Throwable as the root cause.
     *
     * @param t The root cause of the exception.
     */
    public MessageException(Throwable t)
    {
        String rootMessage = t.getMessage();
        if (rootMessage == null)
            rootMessage = t.toString();
        setMessage(rootMessage);
        setRootCause(t);
    }

    //--------------------------------------------------------------------------
    //
    // Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  code
    //----------------------------------


    protected String code;

    /**
     * Returns the code of the exception.
     *
     * @return Code of the exception.
     */
    public String getCode()
    {
        return code;
    }

    /**
     * Sets the code of the exception.
     *
     * @param code Code of the exception.
     */
    public void setCode(String code)
    {
        this.code = code;
    }

    //----------------------------------
    //  defaultLogMessageIntro
    //----------------------------------

    /**
     * Returns the default initial text for use in the log output generated by logAtHingePoint().
     *
     * @return the default initial text for use in the log output generated by logAtHingePoint().
     */
    public String getDefaultLogMessageIntro()
    {
        return "Error handling message: ";
    }

    //----------------------------------
    //  extendedData
    //----------------------------------


    protected Map extendedData;

    /**
     * Returns the extended data of the exception.
     *
     * @return The extended data of the exception.
     */
    public Map getExtendedData()
    {
        return extendedData;
    }

    /**
     * Sets the extended data of the exception.
     *
     * @param extendedData The extended data of the exception.
     */
    public void setExtendedData(Map extendedData)
    {
        this.extendedData = extendedData;
    }

    //----------------------------------
    //  errorMessage
    //----------------------------------


    protected ErrorMessage errorMessage;

    /**
     * Returns the error message of the exception.
     *
     * @return The error message of the exception.
     */
    public ErrorMessage getErrorMessage()
    {
        if (errorMessage == null)
        {
            errorMessage = createErrorMessage();
        }
        return errorMessage;
    }

    /**
     * Sets the error message of the exception.
     *
     * @param errorMessage The error message of the exception.
     */
    public void setErrorMessage(ErrorMessage errorMessage)
    {
        this.errorMessage = errorMessage;
    }

    //----------------------------------
    //  logStackTraceEnabled
    //----------------------------------

    /**
     * Indicates whether logging of this exception should include a full stack trace or not.
     * Default is true.
     *
     * @see #logAtHingePoint(Message, ErrorMessage, String)
     * @return true if the logging stack traces is enabled.
     */
    public boolean isLogStackTraceEnabled()
    {
        return true;
    }

    //----------------------------------
    //  logged
    //----------------------------------

    protected boolean logged;

    /**
     * Indicates whether this exception has already been logged
     * by a call to logAtHingPoint().
     * Manual logging for an exception can use setLogged(true)
     * to suppress any further automatic logging of the exception.
     *
     * @return true if the exception has been logged; otherwise false.
     */
    public boolean isLogged()
    {
        return logged;
    }

    /**
     * Records whether this exception has been logged.
     *
     * @param value true if the exception has been logged; otherwise false.
     */
    public void setLogged(boolean value)
    {
        logged = value;
    }

    //----------------------------------
    //  peferredLogLevel
    //----------------------------------

    /**
     * Returns the preferred log level for this exception instance.
     * The default value is LogEvent.ERROR.
     *
     * @see #logAtHingePoint(Message, ErrorMessage, String)
     * @return the preffered log level.
     */
    public short getPreferredLogLevel()
    {
        return LogEvent.ERROR;
    }

    //----------------------------------
    //  resourceLoader
    //----------------------------------

    /**
     * Returns the ResourceLoader used to load localized strings.
     *
     * @return The ResourceLoader used to load localized strings.
     */
    @Override protected ResourceLoader getResourceLoader()
    {
        if (resourceLoader == null)
        {
            try
            {
                MessageBroker broker = FlexContext.getMessageBroker();
                resourceLoader = broker != null? broker.getSystemSettings().getResourceLoader()
                        : new PropertyStringResourceLoader();
            }
            catch (NoClassDefFoundError exception) // Could happen in client mode.
            {
                return new PropertyStringResourceLoader();
            }
        }

        return resourceLoader;
    }

    //----------------------------------
    //  rootCauseErrorMessage
    //----------------------------------


    public Object getRootCauseErrorMessage()
    {
        if (rootCause == null)
            return null;

        // FIXME: serialize number field.
        return rootCause instanceof MessageException?
                ((MessageException)rootCause).createErrorMessage() : rootCause;
    }

    //----------------------------------
    //  statusCode
    //----------------------------------

    protected int statusCode;

    /**
     * Returns the HTTP status code of the exception.
     *
     * @return The HTTP status code of the exception.
     */
    public int getStatusCode()
    {
        return statusCode;
    }

    /**
     * Sets the HTTP status code of the exception.
     *
     * @param statusCode The HTTP status code of the exception.
     */
    public void setStatusCode(int statusCode)
    {
        this.statusCode = statusCode;
    }

    //--------------------------------------------------------------------------
    //
    // Public Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Creates an error message from the exception.
     *
     * @return The error message.
     */
    public ErrorMessage createErrorMessage()
    {
        ErrorMessage msg = new ErrorMessage();
        msg.faultCode = code != null? code : "Server.Processing";
        msg.faultString = message;
        msg.faultDetail = details;
        msg.rootCause = getRootCauseErrorMessage();
        if (extendedData != null)
            msg.extendedData = extendedData;
        if (statusCode != 0)
            msg.setHeader(Message.STATUS_CODE_HEADER, statusCode);
        return msg;
    }

    /**
     * Invoked at hinge-points in server processing where catch-all exception logging is performed.
     * This method uses isLogged() and setLogged() to avoid repeat logging
     * of the same exception and uses getPreferredLogLevel() which may be
     * overridden in subclasses to control the log level that the logging is output at.
     * The underlying exception stack traces are also conditionally included in log output
     * if the exception class allows it and this is determined by invoking isLogStackTraceEnabled()
     *
     * @param inboundMessage The inbound message that triggered an exception during processing.
     * @param outboundMessage The outbound ErrorMessage, which may be null depending on whether it has been generated
     *                        or not at the point this method is invoked.
     * @param logMessageIntro The beginning text for the log message, which may be null; default value is returned by getDefaultLogMessageIntro().
     */
    public void logAtHingePoint(Message inboundMessage, ErrorMessage outboundMessage, String logMessageIntro)
    {
        if (!isLogged())
        {
            setLogged(true);

            short preferredLevel = getPreferredLogLevel();
            // If the preferred level is less than the current Log level; return early.
            if (preferredLevel < Log.getTargetLevel())
                return;

            // Construct core log output.
            StringBuffer output = new StringBuffer();
            output.append((logMessageIntro != null) ? logMessageIntro : getDefaultLogMessageIntro());
            output.append(this.toString());
            output.append(StringUtils.NEWLINE);
            output.append("  incomingMessage: ");
            output.append(inboundMessage);
            output.append(StringUtils.NEWLINE);
            if (outboundMessage != null)
            {
                output.append("  errorReply: ");
                output.append(outboundMessage);
                output.append(StringUtils.NEWLINE);
            }
            if (isLogStackTraceEnabled())
            {
                output.append(ExceptionUtil.exceptionFollowedByRootCausesToString(this));
                output.append(StringUtils.NEWLINE);
            }

            switch (preferredLevel)
            {
                case LogEvent.FATAL:
                {
                    Log.getLogger(LogCategories.MESSAGE_GENERAL).fatal(output.toString());
                    break;
                }
                case LogEvent.ERROR:
                {
                    Log.getLogger(LogCategories.MESSAGE_GENERAL).error(output.toString());
                    break;
                }
                case LogEvent.WARN:
                {
                    Log.getLogger(LogCategories.MESSAGE_GENERAL).warn(output.toString());
                    break;
                }
                case LogEvent.INFO:
                {
                    Log.getLogger(LogCategories.MESSAGE_GENERAL).info(output.toString());
                    break;
                }
                case LogEvent.DEBUG:
                {
                    Log.getLogger(LogCategories.MESSAGE_GENERAL).debug(output.toString());
                    break;
                }
                default:
                {
                    Log.getLogger(LogCategories.MESSAGE_GENERAL).fatal("Failed to log exception for handling message due to an invalid preferred log level: " + preferredLevel);
                    break;
                }
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy