001    //  Copyright 2008, 2009 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.tapestry5.upload.internal.services;
016    
017    import org.apache.commons.fileupload.FileUploadException;
018    import org.apache.tapestry5.annotations.Events;
019    import org.apache.tapestry5.internal.services.ComponentResultProcessorWrapper;
020    import org.apache.tapestry5.ioc.annotations.Primary;
021    import org.apache.tapestry5.runtime.Component;
022    import org.apache.tapestry5.services.*;
023    import org.apache.tapestry5.upload.services.MultipartDecoder;
024    import org.apache.tapestry5.upload.services.UploadEvents;
025    
026    import java.io.IOException;
027    
028    /**
029     * Determines if there was an {@link org.apache.commons.fileupload.FileUploadException} processing the request and, if
030     * so, triggers an exception event on the page. If the page fails to respond to the event, then
031     */
032    @Events(UploadEvents.UPLOAD_EXCEPTION + " when a exception occur processing the upload")
033    public class UploadExceptionFilter implements ComponentEventRequestFilter
034    {
035        private final MultipartDecoder decoder;
036    
037        private final ComponentEventResultProcessor resultProcessor;
038    
039        private ComponentSource componentSource;
040    
041        public UploadExceptionFilter(MultipartDecoder decoder,
042                                     @Traditional @Primary ComponentEventResultProcessor resultProcessor,
043                                     ComponentSource componentSource)
044        {
045            this.decoder = decoder;
046            this.resultProcessor = resultProcessor;
047            this.componentSource = componentSource;
048        }
049    
050        public void handle(ComponentEventRequestParameters parameters, ComponentEventRequestHandler handler)
051                throws IOException
052        {
053            FileUploadException uploadException = decoder.getUploadException();
054    
055            if (uploadException != null)
056            {
057                Component page = componentSource.getPage(parameters.getActivePageName());
058    
059                ComponentResultProcessorWrapper callback = new ComponentResultProcessorWrapper(resultProcessor);
060    
061                page.getComponentResources().triggerEvent(UploadEvents.UPLOAD_EXCEPTION, new Object[] { uploadException },
062                                                          callback);
063    
064                // If an event handler exists and returns a value, then the callback will be aborted and a response
065                // (typically a redirect) will already have been sent to the client.
066    
067                if (callback.isAborted()) return;
068    
069                // If the page does not properly handle the exception, then we throw it now.
070    
071                throw new RuntimeException(UploadMessages.unableToDecode(), uploadException);
072            }
073    
074    
075            handler.handle(parameters);
076        }
077    }