    001    // Copyright 2007, 2008, 2009, 2011 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.services;
    016
    017    import org.apache.commons.fileupload.FileItemFactory;
    018    import org.apache.commons.fileupload.disk.DiskFileItemFactory;
    019    import org.apache.commons.io.FileCleaner;
    020    import org.apache.tapestry5.internal.InternalConstants;
    021    import org.apache.tapestry5.ioc.Configuration;
    022    import org.apache.tapestry5.ioc.MappedConfiguration;
    023    import org.apache.tapestry5.ioc.OrderedConfiguration;
    024    import org.apache.tapestry5.ioc.ScopeConstants;
    025    import org.apache.tapestry5.ioc.annotations.Autobuild;
    026    import org.apache.tapestry5.ioc.annotations.Scope;
    027    import org.apache.tapestry5.ioc.annotations.Symbol;
    028    import org.apache.tapestry5.ioc.services.PerthreadManager;
    029    import org.apache.tapestry5.ioc.services.RegistryShutdownHub;
    030    import org.apache.tapestry5.ioc.services.RegistryShutdownListener;
    031    import org.apache.tapestry5.services.ComponentEventRequestFilter;
    032    import org.apache.tapestry5.services.HttpServletRequestFilter;
    033    import org.apache.tapestry5.services.LibraryMapping;
    034    import org.apache.tapestry5.upload.internal.services.MultipartDecoderImpl;
    035    import org.apache.tapestry5.upload.internal.services.MultipartServletRequestFilter;
    036    import org.apache.tapestry5.upload.internal.services.UploadExceptionFilter;
    037
    038    import java.io.File;
    039    import java.util.concurrent.atomic.AtomicBoolean;
    040
    041    public class UploadModule
    042    {
    043        private static final String NO_LIMIT = "-1";
    044
    045        private static final AtomicBoolean needToAddShutdownListener = new AtomicBoolean(true);
    046
    047        public static void contributeComponentClassResolver(Configuration<LibraryMapping> configuration)
    048        {
    049            // Add the component to the "core" library.
    050
    051            configuration.add(new LibraryMapping(InternalConstants.CORE_LIBRARY, "org.apache.tapestry5.upload"));
    052        }
    053
    054        @Scope(ScopeConstants.PERTHREAD)
    055        public static MultipartDecoder buildMultipartDecoder(PerthreadManager perthreadManager,
    056
    057                                                             RegistryShutdownHub shutdownHub,
    058
    059                                                             @Autobuild
    060                                                             MultipartDecoderImpl multipartDecoder)
    061        {
    062            // This is proabably overkill since the FileCleaner should catch temporary files, but lets
    063            // be safe.
    064            perthreadManager.addThreadCleanupListener(multipartDecoder);
    065
    066            if (needToAddShutdownListener.getAndSet(false))
    067            {
    068                shutdownHub.addRegistryShutdownListener(new Runnable()
    069                {
    070                    public void run()
    071                    {
    072                        FileCleaner.exitWhenFinished();
    073                    }
    074                });
    075            }
    076
    077            return multipartDecoder;
    078        }
    079
    080        /**
    081         * Contributes a filter, "MultipartFilter" after "IgnoredPaths".
    082         */
    083        public static void contributeHttpServletRequestHandler(
    084                OrderedConfiguration<HttpServletRequestFilter> configuration, MultipartDecoder multipartDecoder)
    085        {
    086            configuration.add("MultipartFilter", new MultipartServletRequestFilter(multipartDecoder), "after:IgnoredPaths");
    087        }
    088
    089        /**
    090         * Adds UploadException to the pipeline, between Secure and Ajax (both provided by TapestryModule). UploadException
    091         * is responsible for triggering the {@linkplain org.apache.tapestry5.upload.services.UploadEvents#UPLOAD_EXCEPTION
    092         * upload exception event}.
    093         */
    094        public static void contributeComponentEventRequestHandler(
    095                OrderedConfiguration<ComponentEventRequestFilter> configuration)
    096        {
    097            configuration.addInstance("UploadException", UploadExceptionFilter.class, "after:Secure", "before:Ajax");
    098        }
    099
    100        /**
    101         * The default FileItemFactory used by the MultipartDecoder is
    102         * {@link org.apache.commons.fileupload.disk.DiskFileItemFactory}.
    103         */
    104        public static FileItemFactory buildDefaultFileItemFactory(@Symbol(UploadSymbols.REPOSITORY_THRESHOLD)
    105                                                                  int repositoryThreshold,
    106
    107                                                                  @Symbol(UploadSymbols.REPOSITORY_LOCATION)
    108                                                                  String repositoryLocation)
    109        {
    110            return new DiskFileItemFactory(repositoryThreshold, new File(repositoryLocation));
    111        }
    112
    113        public static void contributeFactoryDefaults(MappedConfiguration<String, String> configuration)
    114        {
    115            configuration.add(UploadSymbols.REPOSITORY_THRESHOLD, Integer
    116                    .toString(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD));
    117            configuration.add(UploadSymbols.REPOSITORY_LOCATION, System.getProperty("java.io.tmpdir"));
    118            configuration.add(UploadSymbols.REQUESTSIZE_MAX, NO_LIMIT);
    119            configuration.add(UploadSymbols.FILESIZE_MAX, NO_LIMIT);
    120        }
    121    }