001/*
002 * The contents of this file are subject to the terms of the Common Development and
003 * Distribution License (the License). You may not use this file except in compliance with the
004 * License.
005 *
006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
007 * specific language governing permission and limitations under the License.
008 *
009 * When distributing Covered Software, include this CDDL Header Notice in each file and include
010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
011 * Header, with the fields enclosed by brackets [] replaced by your own identifying
012 * information: "Portions Copyright [year] [name of copyright owner]".
013 *
014 * Copyright 2010–2011 ApexIdentity Inc.
015 * Portions Copyright 2011-2014 ForgeRock AS.
016 */
017
018package org.forgerock.openig.filter;
019
020import static org.forgerock.util.Utils.*;
021
022import java.io.IOException;
023
024import org.forgerock.openig.handler.Handler;
025import org.forgerock.openig.handler.HandlerException;
026import org.forgerock.openig.heap.GenericHeaplet;
027import org.forgerock.openig.heap.HeapException;
028import org.forgerock.openig.http.Exchange;
029
030/**
031 * Catches any exceptions thrown during handing of a request. This allows friendlier error
032 * pages to be displayed than would otherwise be displayed by the container. Caught exceptions
033 * are logged with a log level of {@link org.forgerock.openig.log.LogLevel#WARNING} and the exchange is diverted to
034 * the specified exception handler.
035 * <p>
036 * Note: While the response object will be retained in the exchange object, this class will
037 * close any open entity within the response object prior to dispatching the exchange to the
038 * exception handler.
039 */
040public class ExceptionFilter extends GenericFilter {
041
042    /** Handler to dispatch to in the event of caught exceptions. */
043    private final Handler handler;
044
045    /**
046     * Build a new exception filter that will divert the flow to the given handler in case of exception.
047     * @param handler exception handler
048     */
049    public ExceptionFilter(final Handler handler) {
050        this.handler = handler;
051    }
052
053    @Override
054    public void filter(Exchange exchange, Handler next) throws HandlerException, IOException {
055        try {
056            next.handle(exchange);
057        } catch (Throwable t) {
058            // user-impacting
059            logger.warning(t);
060            closeSilently(exchange.response);
061            handler.handle(exchange);
062        }
063    }
064
065    /**
066     * Creates and initializes an exception filter in a heap environment.
067     */
068    public static class Heaplet extends GenericHeaplet {
069        @Override
070        public Object create() throws HeapException {
071            return new ExceptionFilter(heap.resolve(config.get("handler"), Handler.class));
072        }
073    }
074}