You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2005/02/26 01:50:33 UTC

cvs commit: jakarta-tapestry/framework/src/descriptor/META-INF tapestry.multipart.xml hivemodule.xml

hlship      2005/02/25 16:50:33

  Modified:    framework/src/java/org/apache/tapestry/multipart
                        UploadPart.java ValuePart.java
               framework/src/java/org/apache/tapestry/form Upload.java
                        Upload.jwc
               framework/src/java/org/apache/tapestry/request
                        RequestContext.java
               framework/src/java/org/apache/tapestry/services/impl
                        InvokeEngineTerminator.java
               src/documentation/content/xdocs/UsersGuide configuration.xml
               framework/src/descriptor/META-INF hivemodule.xml
  Added:       framework/src/test/org/apache/tapestry/multipart
                        TestMultipartDecoderFilter.java
                        TestUploadFormParametersWrapper.java
               framework/src/java/org/apache/tapestry/multipart
                        MultipartDecoderFilter.java
                        MultipartDecoderImpl.java
                        MultipartStrings.properties
                        UploadFormParametersWrapper.java
                        MultipartDecoder.java MultipartMessages.java
               framework/src/descriptor/META-INF tapestry.multipart.xml
  Removed:     framework/src/java/org/apache/tapestry/multipart IPart.java
                        DefaultMultipartDecoder.java
  Log:
  Refactor multipart/form-data support.
  
  Revision  Changes    Path
  1.1                  jakarta-tapestry/framework/src/test/org/apache/tapestry/multipart/TestMultipartDecoderFilter.java
  
  Index: TestMultipartDecoderFilter.java
  ===================================================================
  // Copyright 2005 The Apache Software Foundation
  //
  // Licensed 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 org.apache.tapestry.multipart;
  
  import java.io.IOException;
  
  import javax.servlet.ServletException;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  
  import org.apache.hivemind.test.HiveMindTestCase;
  import org.apache.tapestry.services.RequestServicer;
  import org.easymock.MockControl;
  
  /**
   * Tests for {@link org.apache.tapestry.multipart.MultipartDecoderFilter}.
   * 
   * @author Howard M. Lewis Ship
   * @since 3.1
   */
  public class TestMultipartDecoderFilter extends HiveMindTestCase
  {
      private static class MockServicer implements RequestServicer
      {
          HttpServletRequest _request;
  
          public void service(HttpServletRequest request, HttpServletResponse response)
                  throws IOException, ServletException
          {
              _request = request;
          }
      }
  
      private HttpServletRequest newRequest(String contentType)
      {
          MockControl control = newControl(HttpServletRequest.class);
          HttpServletRequest request = (HttpServletRequest) control.getMock();
  
          request.getContentType();
          control.setReturnValue(contentType);
  
          return request;
      }
  
      private HttpServletResponse newResponse()
      {
          return (HttpServletResponse) newMock(HttpServletResponse.class);
      }
  
      public void testNormalRequest() throws Exception
      {
          HttpServletRequest request = newRequest("application/x-www-form-urlencoded");
          HttpServletResponse response = newResponse();
  
          MockServicer servicer = new MockServicer();
  
          replayControls();
  
          MultipartDecoderFilter f = new MultipartDecoderFilter();
  
          f.service(request, response, servicer);
  
          assertSame(request, servicer._request);
  
          verifyControls();
      }
  
      public void testUploadRequest() throws Exception
      {
          HttpServletRequest request = newRequest("multipart/form-data");
          HttpServletResponse response = newResponse();
          HttpServletRequest decoded = (HttpServletRequest) newMock(HttpServletRequest.class);
  
          MockControl control = newControl(MultipartDecoder.class);
          MultipartDecoder decoder = (MultipartDecoder) control.getMock();
  
          decoder.decode(request);
          control.setReturnValue(decoded);
  
          decoder.cleanup();
  
          MockServicer servicer = new MockServicer();
  
          replayControls();
  
          MultipartDecoderFilter f = new MultipartDecoderFilter();
          f.setDecoder(decoder);
  
          f.service(request, response, servicer);
  
          assertSame(decoded, servicer._request);
  
          verifyControls();
      }
  }
  
  
  1.1                  jakarta-tapestry/framework/src/test/org/apache/tapestry/multipart/TestUploadFormParametersWrapper.java
  
  Index: TestUploadFormParametersWrapper.java
  ===================================================================
  // Copyright 2005 The Apache Software Foundation
  //
  // Licensed 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 org.apache.tapestry.multipart;
  
  import java.util.Enumeration;
  import java.util.HashMap;
  import java.util.Map;
  
  import javax.servlet.http.HttpServletRequest;
  
  import org.apache.hivemind.test.HiveMindTestCase;
  
  /**
   * Tests for {@link org.apache.tapestry.multipart.UploadFormParametersWrapper}.
   * 
   * @author Howard M. Lewis Ship
   * @since 3.1
   */
  public class TestUploadFormParametersWrapper extends HiveMindTestCase
  {
      private HttpServletRequest newRequest()
      {
          return (HttpServletRequest) newMock(HttpServletRequest.class);
      }
  
      public void testMapIsNotModifiable()
      {
          HttpServletRequest request = newRequest();
  
          replayControls();
  
          Map map = new HashMap();
  
          map.put("key", new String[]
          { "value" });
  
          HttpServletRequest r = new UploadFormParametersWrapper(request, map);
  
          Map pmap = r.getParameterMap();
  
          assertNotSame(map, pmap);
  
          assertSame(map.get("key"), pmap.get("key"));
  
          try
          {
              pmap.put("foo", "bar");
              unreachable();
          }
          catch (UnsupportedOperationException ex)
          {
              // Expected.
          }
  
          verifyControls();
      }
  
      public void testGetSingleParameterWhenNull()
      {
          HttpServletRequest request = newRequest();
  
          replayControls();
  
          HttpServletRequest r = new UploadFormParametersWrapper(request, new HashMap());
  
          assertNull(r.getParameter("unknown-key"));
  
          verifyControls();
      }
  
      public void testGetSingleParameterWhenEmptyArray()
      {
          HttpServletRequest request = newRequest();
  
          replayControls();
  
          HashMap params = new HashMap();
  
          params.put("empty-key", new String[0]);
  
          HttpServletRequest r = new UploadFormParametersWrapper(request, params);
  
          assertNull(r.getParameter("empty-key"));
  
          verifyControls();
      }
  
      public void testGetParameterValues()
      {
          String[] values =
          { "fred", "barney" };
  
          HttpServletRequest request = newRequest();
  
          replayControls();
  
          HashMap params = new HashMap();
  
          params.put("key", values);
  
          HttpServletRequest r = new UploadFormParametersWrapper(request, params);
  
          assertSame(values, r.getParameterValues("key"));
  
          verifyControls();
      }
  
      public void testGetParameterNames()
      {
          HttpServletRequest request = newRequest();
  
          replayControls();
  
          HashMap params = new HashMap();
  
          params.put("key", new String[0]);
  
          HttpServletRequest r = new UploadFormParametersWrapper(request, params);
  
          Enumeration e = r.getParameterNames();
  
          assertEquals(true, e.hasMoreElements());
          assertEquals("key", e.nextElement());
          assertEquals(false, e.hasMoreElements());
  
          verifyControls();
      }
  }
  
  
  1.5       +4 -4      jakarta-tapestry/framework/src/java/org/apache/tapestry/multipart/UploadPart.java
  
  Index: UploadPart.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/multipart/UploadPart.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- UploadPart.java	6 Jan 2005 02:17:34 -0000	1.4
  +++ UploadPart.java	26 Feb 2005 00:50:32 -0000	1.5
  @@ -30,7 +30,7 @@
    * @author Joe Panico
    * @since 2.0.1
    */
  -public class UploadPart extends Object implements IUploadFile, IPart
  +public class UploadPart extends Object implements IUploadFile
   {
       private FileItem _fileItem;
   
  @@ -73,9 +73,9 @@
           }
           catch (IOException ex)
           {
  -            throw new ApplicationRuntimeException(Tapestry.format(
  -                    "UploadPart.unable-to-open-content-file",
  -                    _fileItem.getName()), ex);
  +            throw new ApplicationRuntimeException(MultipartMessages.unableToOpenContentFile(
  +                    this,
  +                    ex), ex);
           }
       }
   
  
  
  
  1.4       +16 -19    jakarta-tapestry/framework/src/java/org/apache/tapestry/multipart/ValuePart.java
  
  Index: ValuePart.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/multipart/ValuePart.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ValuePart.java	6 Jan 2005 02:17:34 -0000	1.3
  +++ ValuePart.java	26 Feb 2005 00:50:32 -0000	1.4
  @@ -18,17 +18,16 @@
   import java.util.List;
   
   /**
  - *  A portion of a multipart request that stores a value, or values, for
  - *  a parameter.
  - *
  - *  @author Howard Lewis Ship
  - *  @since 2.0.1
  - *
  - **/
  + * A portion of a multipart request that stores a value, or values, for a parameter.
  + * 
  + * @author Howard Lewis Ship
  + * @since 2.0.1
  + */
   
  -public class ValuePart implements IPart
  +public class ValuePart
   {
       private int _count;
  +
       // Stores either String or List of String
       private Object _value;
   
  @@ -44,9 +43,8 @@
       }
   
       /**
  -     *  Returns the value, or the first value (if multi-valued).
  -     * 
  -     **/
  +     * Returns the value, or the first value (if multi-valued).
  +     */
   
       public String getValue()
       {
  @@ -59,15 +57,15 @@
       }
   
       /**
  -     *  Returns the values as an array of strings.  If there is only one value,
  -     *  it is returned wrapped as a single element array.
  -     * 
  -     **/
  +     * Returns the values as an array of strings. If there is only one value, it is returned wrapped
  +     * as a single element array.
  +     */
   
       public String[] getValues()
       {
           if (_count == 1)
  -            return new String[] {(String) _value };
  +            return new String[]
  +            { (String) _value };
   
           List l = (List) _value;
   
  @@ -93,9 +91,8 @@
       }
   
       /**
  -     *  Does nothing.
  -     * 
  -     **/
  +     * Does nothing.
  +     */
   
       public void cleanup()
       {
  
  
  
  1.1                  jakarta-tapestry/framework/src/java/org/apache/tapestry/multipart/MultipartDecoderFilter.java
  
  Index: MultipartDecoderFilter.java
  ===================================================================
  // Copyright 2005 The Apache Software Foundation
  //
  // Licensed 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 org.apache.tapestry.multipart;
  
  import java.io.IOException;
  
  import javax.servlet.ServletException;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletResponse;
  
  import org.apache.tapestry.services.RequestServicer;
  import org.apache.tapestry.services.RequestServicerFilter;
  
  /**
   * Checks to see if the request is a file upload and, if so, uses the
   * {@link org.apache.tapestry.multipart.MultipartDecoder} to obtain form parameters.
   * 
   * @author Howard M. Lewis Ship
   * @since 3.1
   */
  public class MultipartDecoderFilter implements RequestServicerFilter
  {
      private MultipartDecoder _decoder;
  
      public void service(HttpServletRequest request, HttpServletResponse response,
              RequestServicer servicer) throws IOException, ServletException
      {
          String contentType = request.getContentType();
  
          // contentType is occasionally null in testing. The browser tacks on additional
          // information onto the contentType to indicate where the boundaries are in
          // the stream.
  
          boolean encoded = contentType != null && contentType.startsWith("multipart/form-data");
  
          try
          {
              HttpServletRequest newRequest = encoded ? _decoder.decode(request) : request;
  
              servicer.service(newRequest, response);
          }
          finally
          {
              if (encoded)
                  _decoder.cleanup();
          }
      }
  
      public void setDecoder(MultipartDecoder decoder)
      {
          _decoder = decoder;
      }
  }
  
  
  1.1                  jakarta-tapestry/framework/src/java/org/apache/tapestry/multipart/MultipartDecoderImpl.java
  
  Index: MultipartDecoderImpl.java
  ===================================================================
  // Copyright 2005 The Apache Software Foundation
  //
  // Licensed 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 org.apache.tapestry.multipart;
  
  import java.io.UnsupportedEncodingException;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  import javax.servlet.http.HttpServletRequest;
  
  import org.apache.commons.fileupload.DiskFileUpload;
  import org.apache.commons.fileupload.FileItem;
  import org.apache.commons.fileupload.FileUploadException;
  import org.apache.hivemind.ApplicationRuntimeException;
  import org.apache.tapestry.request.IUploadFile;
  
  /**
   * Implementation of {@link org.apache.tapestry.multipart.MultipartDecoder}that is based on <a
   * href="http://jakarta.apache.org/commons/fileupload/">Jakarta FileUpload </a>.
   * 
   * @author Howard M. Lewis Ship
   * @author Joe Panico
   * @since 3.1
   */
  public class MultipartDecoderImpl implements MultipartDecoder
  {
      /**
       * Map of UploadPart (which implements IUploadFile), keyed on parameter name.
       */
  
      private Map _uploadParts = new HashMap();
  
      /**
       * Map of ValuePart, keyed on parameter name.
       */
      private Map _valueParts = new HashMap();
  
      private int _maxSize = 10000000;
  
      private int _thresholdSize = 1024;
  
      private String _repositoryPath = System.getProperty("java.io.tmpdir");
  
      private String _encoding;
  
      public HttpServletRequest decode(HttpServletRequest request)
      {
          _encoding = request.getCharacterEncoding();
  
          DiskFileUpload upload = createUpload(request);
  
          try
          {
              List fileItems = upload
                      .parseRequest(request, _thresholdSize, _maxSize, _repositoryPath);
  
              processFileItems(fileItems);
          }
          catch (FileUploadException ex)
          {
              throw new ApplicationRuntimeException(MultipartMessages.unableToDecode(ex), ex);
          }
  
          Map parameterMap = buildParameterMap();
  
          return new UploadFormParametersWrapper(request, parameterMap);
      }
  
      private Map buildParameterMap()
      {
          Map result = new HashMap();
  
          Iterator i = _valueParts.entrySet().iterator();
          while (i.hasNext())
          {
              Map.Entry e = (Map.Entry) i.next();
  
              String name = (String) e.getKey();
              ValuePart part = (ValuePart) e.getValue();
  
              result.put(name, part.getValues());
          }
  
          return result;
      }
  
      private void processFileItems(List parts)
      {
          if (parts == null)
              return;
  
          Iterator i = parts.iterator();
  
          while (i.hasNext())
          {
              FileItem item = (FileItem) i.next();
  
              processFileItem(item);
          }
      }
  
      private void processFileItem(FileItem item)
      {
          if (item.isFormField())
          {
              processFormFieldItem(item);
              return;
          }
  
          processUploadFileItem(item);
      }
  
      private void processUploadFileItem(FileItem item)
      {
          String name = item.getFieldName();
  
          UploadPart part = new UploadPart(item);
  
          _uploadParts.put(name, part);
      }
  
      void processFormFieldItem(FileItem item)
      {
          String name = item.getFieldName();
  
          String value = extractFileItemValue(item);
  
          ValuePart part = (ValuePart) _valueParts.get(name);
  
          if (part == null)
              _valueParts.put(name, new ValuePart(value));
          else
              part.add(value);
      }
  
      private String extractFileItemValue(FileItem item)
      {
          try
          {
              return (_encoding == null) ? item.getString() : item.getString(_encoding);
          }
          catch (UnsupportedEncodingException ex)
          {
              throw new ApplicationRuntimeException(MultipartMessages.unsupportedEncoding(
                      _encoding,
                      ex), ex);
          }
      }
  
      protected DiskFileUpload createUpload(HttpServletRequest request)
      {
          DiskFileUpload upload = new DiskFileUpload();
  
          if (_encoding != null)
              upload.setHeaderEncoding(_encoding);
  
          return upload;
      }
  
      public IUploadFile getFileUpload(String parameterName)
      {
          return (IUploadFile) _uploadParts.get(parameterName);
      }
  
      public void cleanup()
      {
          Iterator i = _uploadParts.values().iterator();
  
          while (i.hasNext())
          {
              UploadPart part = (UploadPart) i.next();
  
              part.cleanup();
          }
      }
  
  }
  
  
  1.1                  jakarta-tapestry/framework/src/java/org/apache/tapestry/multipart/MultipartStrings.properties
  
  Index: MultipartStrings.properties
  ===================================================================
  # Copyright 2005 The Apache Software Foundation
  #
  # Licensed 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.
  
  unable-to-decode=Unable to decode multipart encoded request: {0}
  unsupported-encoding=Unsupported character encoding ''{0}'' when decoding multipart encoded request: {1}
  write-failure=Unable to write uploaded file content to {0}: {1}
  
  
  1.1                  jakarta-tapestry/framework/src/java/org/apache/tapestry/multipart/UploadFormParametersWrapper.java
  
  Index: UploadFormParametersWrapper.java
  ===================================================================
  // Copyright 2005 The Apache Software Foundation
  //
  // Licensed 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 org.apache.tapestry.multipart;
  
  import java.util.Collections;
  import java.util.Enumeration;
  import java.util.Map;
  
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.http.HttpServletRequestWrapper;
  
  import org.apache.hivemind.util.Defense;
  
  /**
   * {@link javax.servlet.http.HttpServletRequest}&nbsp; wrapper that provides access to the form
   * field values uploaded in a multipart request.
   * 
   * @author Howard M. Lewis Ship
   * @since 3.1
   */
  public class UploadFormParametersWrapper extends HttpServletRequestWrapper
  {
      /**
       * Map of {@link ValuePart}&nbsp;keyed on parameter name.
       */
      private Map _parameterMap;
  
      /**
       * @param parameterMap
       *            a map whose keys are parameter names and whose values are arrays of Strings.
       */
      public UploadFormParametersWrapper(HttpServletRequest request, Map parameterMap)
      {
          super(request);
  
          Defense.notNull(parameterMap, "parameterMap");
  
          _parameterMap = Collections.unmodifiableMap(parameterMap);
      }
  
      public String getParameter(String name)
      {
          String[] values = getParameterValues(name);
  
          return (values == null || values.length == 0) ? null : values[0];
      }
  
      public Map getParameterMap()
      {
          return _parameterMap;
      }
  
      public Enumeration getParameterNames()
      {
          return Collections.enumeration(_parameterMap.keySet());
      }
  
      public String[] getParameterValues(String name)
      {
          return (String[]) _parameterMap.get(name);
      }
  
      public String toString()
      {
          return "<UploadFormPartWrapper for " + getRequest() + ">";
      }
  }
  
  
  1.1                  jakarta-tapestry/framework/src/java/org/apache/tapestry/multipart/MultipartDecoder.java
  
  Index: MultipartDecoder.java
  ===================================================================
  // Copyright 2005 The Apache Software Foundation
  //
  // Licensed 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 org.apache.tapestry.multipart;
  
  import javax.servlet.http.HttpServletRequest;
  
  import org.apache.tapestry.request.IUploadFile;
  
  /**
   * Responsible for detecting and processing file upload requests, using Jakarta Commons FileUpload.
   * Implementations of this service typically use the threaded service lifecycle model.
   * 
   * @author Howard M. Lewis Ship
   * @since 3.1
   */
  public interface MultipartDecoder
  {
      /**
       * Decodes the request, returning a new {@link javax.servlet.http.HttpServletRequest}
       * implementation that will allow access to the form fields submitted in the request (but omits
       * uploaded files.
       */
  
      public HttpServletRequest decode(HttpServletRequest request);
  
      /**
       * Gets a file upload with the given name, or returns null if no such file upload was in the
       * request.
       */
  
      public IUploadFile getFileUpload(String parameterName);
  
      /**
       * Cleans up any temporary resources created during the request processing. This typically
       * includes temporary files used to contain uploaded file content.
       */
  
      public void cleanup();
  }
  
  
  1.1                  jakarta-tapestry/framework/src/java/org/apache/tapestry/multipart/MultipartMessages.java
  
  Index: MultipartMessages.java
  ===================================================================
  // Copyright 2005 The Apache Software Foundation
  //
  // Licensed 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 org.apache.tapestry.multipart;
  
  import java.io.File;
  
  import org.apache.hivemind.impl.MessageFormatter;
  
  /**
   * @author Howard M. Lewis Ship
   * @since 3.1
   */
  class MultipartMessages
  {
      private static final MessageFormatter _formatter = new MessageFormatter(
              MultipartMessages.class, "MultipartStrings");
  
      public static String unableToDecode(Throwable cause)
      {
          return _formatter.format("unable-to-decode", cause);
      }
  
      public static String unsupportedEncoding(String encoding, Throwable cause)
      {
          return _formatter.format("unsupported-encoding", encoding, cause);
      }
  
      public static String unableToOpenContentFile(UploadPart part, Throwable cause)
      {
          return _formatter.format("unable-to-open-content-file", part.getFilePath(), cause);
      }
  
      public static String writeFailure(File file, Throwable cause)
      {
          return _formatter.format("write-failure", file, cause);
      }
  
  }
  
  
  1.4       +20 -15    jakarta-tapestry/framework/src/java/org/apache/tapestry/form/Upload.java
  
  Index: Upload.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/form/Upload.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Upload.java	5 Jan 2005 23:17:13 -0000	1.3
  +++ Upload.java	26 Feb 2005 00:50:32 -0000	1.4
  @@ -17,39 +17,42 @@
   import org.apache.tapestry.IForm;
   import org.apache.tapestry.IMarkupWriter;
   import org.apache.tapestry.IRequestCycle;
  +import org.apache.tapestry.multipart.MultipartDecoder;
   import org.apache.tapestry.request.IUploadFile;
   
   /**
  - *  Form element used to upload files.  For the momement, it is necessary to
  - *  explicitly set the form's enctype to "multipart/form-data".
  + * Form element used to upload files. For the momement, it is necessary to explicitly set the form's
  + * enctype to "multipart/form-data". [ <a
  + * href="../../../../../ComponentReference/Upload.html">Component Reference </a>]
    * 
  - *  [<a href="../../../../../ComponentReference/Upload.html">Component Reference</a>]
  - * 
  - *  @author Howard Lewis Ship
  - *  @since 1.0.8
  - * 
  - **/
  + * @author Howard Lewis Ship
  + * @since 1.0.8
  + */
   
   public abstract class Upload extends AbstractFormComponent
   {
       protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
       {
           IForm form = getForm(cycle);
  -		
  +
           String name = form.getElementId(this);
   
           if (form.isRewinding())
           {
  -        	if (!isDisabled())
  -	            setFile(cycle.getRequestContext().getUploadFile(name));
  +            if (!isDisabled())
  +            {
  +                IUploadFile file = getDecoder().getFileUpload(name);
  +
  +                setFile(file);
  +            }
   
               return;
           }
   
  -		// Force the form to use the correct encoding type for
  -		// file uploads.
  -		
  -		form.setEncodingType("multipart/form-data");
  +        // Force the form to use the correct encoding type for
  +        // file uploads.
  +
  +        form.setEncodingType("multipart/form-data");
   
           writer.beginEmpty("input");
           writer.attribute("type", "file");
  @@ -68,4 +71,6 @@
       public abstract boolean isDisabled();
   
       public abstract void setFile(IUploadFile file);
  +
  +    public abstract MultipartDecoder getDecoder();
   }
  \ No newline at end of file
  
  
  
  1.4       +2 -0      jakarta-tapestry/framework/src/java/org/apache/tapestry/form/Upload.jwc
  
  Index: Upload.jwc
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/form/Upload.jwc,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- Upload.jwc	27 Jan 2005 05:35:51 -0000	1.3
  +++ Upload.jwc	26 Feb 2005 00:50:32 -0000	1.4
  @@ -38,4 +38,6 @@
     <reserved-parameter name="type"/>
     <reserved-parameter name="name"/>
     
  +  <inject property="decoder" object="service:tapestry.multipart.MultipartDecoder"/>
  +  
   </component-specification>
  
  
  
  1.9       +1 -119    jakarta-tapestry/framework/src/java/org/apache/tapestry/request/RequestContext.java
  
  Index: RequestContext.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/request/RequestContext.java,v
  retrieving revision 1.8
  retrieving revision 1.9
  diff -u -r1.8 -r1.9
  --- RequestContext.java	25 Feb 2005 21:26:27 -0000	1.8
  +++ RequestContext.java	26 Feb 2005 00:50:32 -0000	1.9
  @@ -39,9 +39,6 @@
   import org.apache.tapestry.IMarkupWriter;
   import org.apache.tapestry.IRender;
   import org.apache.tapestry.IRequestCycle;
  -import org.apache.tapestry.Tapestry;
  -import org.apache.tapestry.multipart.DefaultMultipartDecoder;
  -import org.apache.tapestry.multipart.IMultipartDecoder;
   import org.apache.tapestry.spec.IApplicationSpecification;
   
   /**
  @@ -93,10 +90,6 @@
   
       private HttpServlet _servlet;
   
  -    private IMultipartDecoder _decoder;
  -    
  -    private boolean _decoded;
  -
       private IApplicationSpecification _specification;
   
       /**
  @@ -123,40 +116,6 @@
           _request = request;
           _response = response;
           _specification = specification;
  -
  -        // All three parameters may be null if created from
  -        // AbstractEngine.cleanupEngine().
  -
  -        if (_request != null && DefaultMultipartDecoder.isMultipartRequest(request))
  -        {
  -            IMultipartDecoder decoder = obtainMultipartDecoder(servlet, request);
  -            setDecoder(decoder);
  -        }
  -    }
  -
  -    /**
  -     * Invoked from the constructor to create a {@link DefaultMultipartDecoder}instance.
  -     * Applications with specific upload needs may need to override this to provide a subclass
  -     * instance instead. The caller will invoke {@link IMultipartDecoder#decode(HttpServletRequest)}
  -     * on the returned object.
  -     * <p>
  -     * This implementation checks for application extension
  -     * {@link Tapestry#MULTIPART_DECODER_EXTENSION_NAME}. If that is not defined, a shared instance
  -     * of {@link DefaultMultipartDecoder}is returned.
  -     * 
  -     * @see ApplicationServlet#createRequestContext(HttpServletRequest, HttpServletResponse)
  -     * @since 3.0
  -     */
  -
  -    protected IMultipartDecoder obtainMultipartDecoder(HttpServlet servlet,
  -            HttpServletRequest request) throws IOException
  -    {
  -        if (_specification.checkExtension(Tapestry.MULTIPART_DECODER_EXTENSION_NAME))
  -            return (IMultipartDecoder) _specification.getExtension(
  -                    Tapestry.MULTIPART_DECODER_EXTENSION_NAME,
  -                    IMultipartDecoder.class);
  -
  -        return DefaultMultipartDecoder.getSharedInstance();
       }
   
       /**
  @@ -195,9 +154,6 @@
           pair(writer, name, new Date(value));
       }
   
  -
  -
  -
       /**
        * Builds an absolute URL from the given URI, using the {@link HttpServletRequest}as the source
        * for scheme, server name and port.
  @@ -255,7 +211,7 @@
           buffer.append(scheme);
           buffer.append("://");
           buffer.append(server);
  -        
  +
           if (port > 0)
           {
               buffer.append(':');
  @@ -315,10 +271,6 @@
   
       public String getParameter(String name)
       {
  -        IMultipartDecoder decoder = getDecoder();
  -        if (decoder != null)
  -            return decoder.getString(_request, name);
  -
           return _request.getParameter(name);
       }
   
  @@ -342,19 +294,11 @@
   
       public String[] getParameters(String name)
       {
  -        IMultipartDecoder decoder = getDecoder();
  -        if (decoder != null)
  -            return decoder.getStrings(_request, name);
  -
           return _request.getParameterValues(name);
       }
   
       public String[] getParameterNames()
       {
  -        IMultipartDecoder decoder = getDecoder();
  -        if (decoder != null)
  -            return decoder.getStringParameterNames(_request);
  -
           Enumeration e = _request.getParameterNames();
           List names = new ArrayList();
   
  @@ -369,35 +313,6 @@
       }
   
       /**
  -     * Returns the named {@link IUploadFile}, if it exists, or null if it doesn't. Uploads require
  -     * an encoding of <code>multipart/form-data</code> (this is specified in the form's enctype
  -     * attribute). If the encoding type is not so, or if no upload matches the name, then this
  -     * method returns null.
  -     */
  -
  -    public IUploadFile getUploadFile(String name)
  -    {
  -        IMultipartDecoder decoder = getDecoder();
  -        if (decoder == null)
  -            return null;
  -
  -        return decoder.getUploadFile(_request, name);
  -    }
  -
  -    /**
  -     * Invoked at the end of the request cycle to cleanup and temporary resources. This is chained
  -     * to the {@link DefaultMultipartDecoder}, if there is one.
  -     * 
  -     * @since 2.0.1
  -     */
  -
  -    public void cleanup()
  -    {
  -        if (_decoder != null)
  -            _decoder.cleanup(_request);
  -    }
  -
  -    /**
        * Returns the request which initiated the current request cycle. Note that the methods
        * {@link #getParameter(String)}and {@link #getParameters(String)}should be used, rather than
        * obtaining parameters directly from the request (since the RequestContext handles the
  @@ -921,39 +836,6 @@
       }
   
       /**
  -     * Returns the multipart decoder and lazily decodes the request parameters. This allows both for
  -     * this operation to be performed only when really needed and for opening the request for
  -     * reading much later, so that the Engine can have a chance to set the encoding that the request
  -     * needs to use.
  -     * 
  -     * @return the multipart decoder or null if not needed for this request
  -     * @since 3.0
  -     */
  -    private IMultipartDecoder getDecoder()
  -    {
  -        if (_decoder != null && !_decoded)
  -        {
  -            _decoder.decode(_request);
  -            _decoded = true;
  -        }
  -
  -        return _decoder;
  -    }
  -
  -    /**
  -     * Sets the multipart decoder to be used for the request.
  -     * 
  -     * @param decoder
  -     *            the multipart decoder
  -     * @since 3.0
  -     */
  -    public void setDecoder(IMultipartDecoder decoder)
  -    {
  -        _decoder = decoder;
  -        _decoded = false;
  -    }
  -
  -    /**
        * @since 3.1 --- but probably pretty temporary!
        */
       public IApplicationSpecification getApplicationSpecification()
  
  
  
  1.4       +9 -8      jakarta-tapestry/framework/src/java/org/apache/tapestry/services/impl/InvokeEngineTerminator.java
  
  Index: InvokeEngineTerminator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/java/org/apache/tapestry/services/impl/InvokeEngineTerminator.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- InvokeEngineTerminator.java	5 Jan 2005 23:16:57 -0000	1.3
  +++ InvokeEngineTerminator.java	26 Feb 2005 00:50:33 -0000	1.4
  @@ -13,6 +13,7 @@
   // limitations under the License.
   
   package org.apache.tapestry.services.impl;
  +
   import java.io.IOException;
   
   import javax.servlet.ServletException;
  @@ -29,22 +30,24 @@
   import org.apache.tapestry.spec.IApplicationSpecification;
   
   /**
  - * The terminatior for the <code>tapestry.RequestProcessor</code> pipeline,
  - * this service is responsible for locating the correct engine instance and
  - * letting it to the rest of the request.
  - *
  + * The terminatior for the <code>tapestry.RequestProcessor</code> pipeline, this service is
  + * responsible for locating the correct engine instance and letting it to the rest of the request.
  + * 
    * @author Howard Lewis Ship
    * @since 3.1
    */
   public class InvokeEngineTerminator implements RequestServicer
   {
       private HttpServlet _servlet;
  +
       private EngineManager _engineManager;
  +
       private IApplicationSpecification _specification;
  +
       private Infrastructure _infrastructure;
   
       public void service(HttpServletRequest request, HttpServletResponse response)
  -        throws IOException, ServletException
  +            throws IOException, ServletException
       {
           IEngine engine = _engineManager.getEngineInstance();
   
  @@ -59,8 +62,6 @@
           finally
           {
               _engineManager.storeEngineInstance(engine);
  -
  -            context.cleanup();
           }
   
       }
  @@ -85,4 +86,4 @@
           _infrastructure = infrastructure;
       }
   
  -}
  +}
  \ No newline at end of file
  
  
  
  1.10      +0 -14     jakarta-tapestry/src/documentation/content/xdocs/UsersGuide/configuration.xml
  
  Index: configuration.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/src/documentation/content/xdocs/UsersGuide/configuration.xml,v
  retrieving revision 1.9
  retrieving revision 1.10
  diff -u -r1.9 -r1.10
  --- configuration.xml	8 Feb 2005 21:09:55 -0000	1.9
  +++ configuration.xml	26 Feb 2005 00:50:33 -0000	1.10
  @@ -694,20 +694,6 @@
   	(perhaps in a database), or constructed on the fly.
     </td></tr>
   
  -
  - 
  -<tr><td>org.apache.tapestry.multipart-decoder </td> <td>&IMultipartDecoder;</td>
  -
  -<td>
  -Allows an alternate object to be responsible for decoding multipart requests (context
  -type multipart/form-data, used for file uploads).  Generally, this is used to
  -configure an instance of &DefaultMultipartDecoder; with non-default values for
  -the maximum upload size, threshold size (number of bytes before a temporary file is created
  -to store the) and repository directory (where temporary files are stored).	
  -</td></tr>
  -
  -
  -
   <tr><td>org.apache.tapestry.ognl-type-converter</td> <td>ognl.TypeConverter</td>
   
   <td>
  
  
  
  1.28      +1 -0      jakarta-tapestry/framework/src/descriptor/META-INF/hivemodule.xml
  
  Index: hivemodule.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-tapestry/framework/src/descriptor/META-INF/hivemodule.xml,v
  retrieving revision 1.27
  retrieving revision 1.28
  diff -u -r1.27 -r1.28
  --- hivemodule.xml	25 Feb 2005 18:01:31 -0000	1.27
  +++ hivemodule.xml	26 Feb 2005 00:50:33 -0000	1.28
  @@ -40,6 +40,7 @@
     <sub-module descriptor="tapestry.asset.xml"/>
     <sub-module descriptor="tapestry.persist.xml"/>
     <sub-module descriptor="tapestry.state.xml"/>
  +  <sub-module descriptor="tapestry.multipart.xml"/>
     
     <service-point id="ClasspathResourceFactory" interface="ClasspathResourceFactory">
     
  
  
  
  1.1                  jakarta-tapestry/framework/src/descriptor/META-INF/tapestry.multipart.xml
  
  Index: tapestry.multipart.xml
  ===================================================================
  <?xml version="1.0"?>
  <!-- 
     Copyright 2005 The Apache Software Foundation
  
     Licensed 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.
  -->
  
  <module id="tapestry.multipart" version="3.1.0" package="org.apache.tapestry.multipart">
    
    Support for multipart/form-data encoded requests used for file uploads.
    
    <service-point id="MultipartDecoder" interface="MultipartDecoder">
      
      Service responsible for parsing and decoding multipart form submissions. 
      
      <create-instance class="MultipartDecoderImpl" model="threaded"/>
      
    </service-point>
    
    <service-point id="MultipartDecoderFilter" interface="org.apache.tapestry.services.RequestServicerFilter">
      
      Identifies upload requests and passes them to the MultipartDecoder service
      for decoding.
      
      <invoke-factory>
        <construct class="MultipartDecoderFilter">
          <set-service property="decoder" service-id="MultipartDecoder"/>
        </construct>
      </invoke-factory>
      
    </service-point>
    
    <contribution configuration-id="tapestry.request.RequestServicerPipeline">
      <filter name="MultipartDecoderFilter" object="service:MultipartDecoderFilter"/>
    </contribution>
    
  </module>
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: tapestry-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: tapestry-dev-help@jakarta.apache.org