/*
 * 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.security;

import flex.messaging.MessageException;
import flex.messaging.log.LogEvent;
import flex.messaging.messages.ErrorMessage;
import flex.messaging.messages.Message;
import flex.messaging.util.ResourceLoader;

/**
 * SecurityException is a localizable exception type that is used to represent
 * client authentication, client authorization and general server-related security
 * errors. It defines a set of supported error code values as constants suffixed
 * with _CODE.
 */
public class SecurityException extends MessageException {
    static final long serialVersionUID = -3168212117963624230L;

    // Error code constants.
    public static final String CLIENT_AUTHENTICATION_CODE = "Client.Authentication";
    public static final String CLIENT_AUTHORIZATION_CODE = "Client.Authorization";
    public static final String SERVER_AUTHENTICATION_CODE = "Server.Authentication";
    public static final String SERVER_AUTHORIZATION_CODE = "Server.Authorization";

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

    /**
     * Create a SecurityException that will use the default ResourceLoader
     * for error codes.
     */
    public SecurityException() {
        super();
    }

    /**
     * Create a SecurityException that will use the specified ResourceLoader
     * for error codes.
     */
    public SecurityException(ResourceLoader resourceLoader) {
        super(resourceLoader);
    }

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

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

    /**
     * Returns the default initial text for the log output generated by <code>logAtHingePoint()</code>.
     */
    public String getDefaultLogMessageIntro() {
        return "Security error for message: ";
    }

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

    /**
     * Override to disable stack trace logging. Security exceptions are generally innocuous (invalid credentials/role membership)
     * and stack traces make these faults scarier than necessary.
     */
    public boolean isLogStackTraceEnabled() {
        return false;
    }

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

    /**
     * Returns the preferred log level for this exception instance.
     */
    public short getPreferredLogLevel() {
        // SecurityExceptions are common, incorrect credentials/invalid role membership, and don't
        // need to be logged at the ERROR level.
        return LogEvent.DEBUG;
    }

    //----------------------------------
    //  failingMessage
    //----------------------------------            

    private Message failingMessage;

    /**
     * Returns the message with information about what caused this security exception to be thrown.
     *
     * @return message with information about what caused this security exception to be thrown
     */
    public Message getFailingMessage() {
        return failingMessage;
    }

    /**
     * Sets the message with information about what caused this security exception to be thrown.
     *
     * @param failingMessage message with information about what caused this security exception to be thrown
     */
    public void setFailingMessage(Message failingMessage) {
        this.failingMessage = failingMessage;
    }

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

    /**
     * Overrides <code>createErrorMessage()</code> to correlate the <code>ErrorMessage</code> to the
     * failing message by id and destination.
     *
     * @return correlated error message
     */
    public ErrorMessage createErrorMessage() {
        ErrorMessage msg = super.createErrorMessage();
        if (failingMessage != null) {
            msg.setCorrelationId(failingMessage.getMessageId());
            msg.setDestination(failingMessage.getDestination());
        }
        return msg;
    }
}