You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2008/01/17 16:19:09 UTC

svn commit: r612842 - in /incubator/sling/trunk/usling: usling-servlets/src/main/java/org/apache/sling/ujax/ usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/ usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrat...

Author: bdelacretaz
Date: Thu Jan 17 07:18:10 2008
New Revision: 612842

URL: http://svn.apache.org/viewvc?rev=612842&view=rev
Log:
SLING-168, file upload support for UjaxPostServlet, contributed by Tobias Bocanegra, thanks!

Added:
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxFileUploadHandler.java   (with props)
    incubator/sling/trunk/usling/usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/UploadFileTest.java   (with props)
    incubator/sling/trunk/usling/usling-webapp/src/test/resources/integration-test/file-to-upload.txt   (with props)
Modified:
    incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java
    incubator/sling/trunk/usling/usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/helpers/UslingIntegrationTestClient.java

Added: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxFileUploadHandler.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxFileUploadHandler.java?rev=612842&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxFileUploadHandler.java (added)
+++ incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxFileUploadHandler.java Thu Jan 17 07:18:10 2008
@@ -0,0 +1,188 @@
+/*
+ * 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 org.apache.sling.ujax;
+
+import org.apache.sling.api.request.RequestParameter;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.commons.mime.MimeTypeService;
+import org.apache.jackrabbit.util.Text;
+
+import java.util.Calendar;
+import java.io.IOException;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeTypeManager;
+import javax.jcr.nodetype.NodeType;
+
+/**
+ * Handles file uploads.
+ * <p/>
+ *
+ * Simple example:
+ * <xmp>
+ *   <form action="/home/admin" method="POST" enctype="multipart/form-data">
+ *     <input type="file" name="./portrait" />
+ *   </form>
+ * </xmp>
+ *
+ * this will create a nt:file node below "/home/admin" if the node type of
+ * "admin" is (derived from) nt:folder, a nt:resource node otherwise.
+ * <p/>
+ *
+ * Filename example:
+ * <xmp>
+ *   <form action="/home/admin" method="POST" enctype="multipart/form-data">
+ *     <input type="file" name="./*" />
+ *   </form>
+ * </xmp>
+ *
+ * same as above, but uses the filename of the uploaded file as name for the
+ * new node.
+ * <p/>
+ *
+ * Type hint example:
+ * <xmp>
+ *   <form action="/home/admin" method="POST" enctype="multipart/form-data">
+ *     <input type="file" name="./portrait" />
+ *     <input type="hidden" name="./portrait@TypeHint" value="my:file" />
+ *   </form>
+ * </xmp>
+ *
+ * this will create a new node with the type my:file below admin. if the hinted
+ * type extends from nt:file an intermediate file node is created otherwise
+ * directly a resource node.
+ * 
+ * @version $Rev$, $Date$
+ */
+public class UjaxFileUploadHandler {
+
+    /**
+     * The CVS/SVN id
+     */
+    static final String CVS_ID = "$URL$ $Rev$ $Date$";
+
+    // nodetype name string constants
+    public static final String NT_FOLDER = "nt:folder";
+    public static final String NT_FILE = "nt:file";
+    public static final String NT_RESOURCE = "nt:resource";
+
+    // item name string constants
+    public static final String JCR_CONTENT = "jcr:content";
+    public static final String JCR_LASTMODIFIED = "jcr:lastModified";
+    public static final String JCR_MIMETYPE = "jcr:mimeType";
+    public static final String JCR_ENCODING = "jcr:encoding";
+    public static final String JCR_DATA = "jcr:data";
+
+    /**
+     * Uses the file(s) in the request parameter for creation of new nodes.
+     * if the parent node is a nt:folder a new nt:file is created. otherwise
+     * just a nt:resource. if the <code>name</code> is '*', the filename of
+     * the uploaded file is used.
+     *
+     * @param request the servlet request
+     * @param parent the parent node
+     * @param name the name of the file/resource node or '*'
+     * @param values the request values
+     * @param typeHint a hint for the node type
+     * @throws RepositoryException if an error occurs
+     */
+    void setFile(SlingHttpServletRequest request, Node parent, String name,
+                 RequestParameter[] values, String typeHint)
+            throws RepositoryException {
+        RequestParameter value = values[0];
+        assert !value.isFormField();
+
+        // ignore if empty
+        if (value.getSize() <= 0) {
+            return;
+        }
+
+        // get node name
+        if (name.equals("*")) {
+            name = value.getFileName();
+            // strip of possible path (some browsers include the entire path)
+            name = name.substring(name.lastIndexOf('/') + 1);
+            name = name.substring(name.lastIndexOf('\\') + 1);
+        }
+        name = Text.escapeIllegalJcrChars(name);
+
+        // check type hint. if the type is ok and extends from nt:file,
+        // create an nt:file with that type. if it's invalid, drop it and let
+        // the parent node type decide.
+        boolean createNtFile = parent.isNodeType(NT_FOLDER);
+        if (typeHint != null) {
+            try {
+                NodeTypeManager ntMgr = parent.getSession().getWorkspace().getNodeTypeManager();
+                NodeType nt = ntMgr.getNodeType(typeHint);
+                createNtFile = nt.isNodeType(NT_FILE);
+            } catch (RepositoryException e) {
+                // assuming type not valid.
+                typeHint = null;
+            }
+        }
+
+        // set empty type
+        if (typeHint == null) {
+            typeHint = createNtFile ? NT_FILE : NT_RESOURCE;
+        }
+
+        // remove node
+        if (parent.hasNode(name)) {
+            parent.getNode(name).remove();
+        }
+
+        // create nt:file node if needed
+        if (createNtFile) {
+            // create nt:file
+            parent = parent.addNode(name, typeHint);
+            name = JCR_CONTENT;
+            typeHint = NT_RESOURCE;
+        }
+        
+        // create resource node
+        Node res = parent.addNode(name, typeHint);
+
+        // get content type
+        String contentType = value.getContentType();
+        if (contentType != null) {
+            int idx = contentType.indexOf(';');
+            if (idx > 0) {
+                contentType = contentType.substring(0, idx);
+            }
+        }
+        if (contentType == null || contentType.equals("application/octet-stream")) {
+            // try to find a better content type
+            MimeTypeService svc = request.getServiceLocator().getService(MimeTypeService.class);
+            if (svc != null) {
+                contentType = svc.getMimeType(value.getFileName());
+            }
+            if (contentType == null || contentType.equals("application/octet-stream")) {
+                contentType = "application/octet-stream";
+            }
+        }
+
+        // set properties
+        res.setProperty(JCR_LASTMODIFIED, Calendar.getInstance());
+        res.setProperty(JCR_MIMETYPE, contentType);
+        try {
+            res.setProperty(JCR_DATA, value.getInputStream());
+        } catch (IOException e) {
+            throw new RepositoryException("Error while retrieving inputstream from parameter value.", e);
+        }
+    }
+}
\ No newline at end of file

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxFileUploadHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxFileUploadHandler.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java?rev=612842&r1=612841&r2=612842&view=diff
==============================================================================
--- incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java (original)
+++ incubator/sling/trunk/usling/usling-servlets/src/main/java/org/apache/sling/ujax/UjaxPostServlet.java Thu Jan 17 07:18:10 2008
@@ -47,6 +47,7 @@
 
     private static final Logger log = LoggerFactory.getLogger(UjaxPostServlet.class);
     private final UjaxPropertyValueSetter propertyValueSetter = new UjaxPropertyValueSetter();
+    private final UjaxFileUploadHandler uploadHandler = new UjaxFileUploadHandler();
     private final NodeNameGenerator nodeNameGenerator = new NodeNameGenerator();
 
     /** Prefix for parameter names which control this POST
@@ -85,6 +86,8 @@
     /** SLING-130, suffix that maps form field names to different JCR property names */
     public static final String VALUE_FROM_SUFFIX = "@ValueFrom";
 
+    public static final String TYPE_HINT_SUFFIX = "@TypeHint";
+
     @Override
     protected void doPost(SlingHttpServletRequest request, SlingHttpServletResponse response)
             throws ServletException, IOException {
@@ -263,7 +266,6 @@
     }
 
     /** Set Node properties from current request
-     *  TODO should handle file uploads as well
      */
     private void setPropertiesFromRequest(Node n, SlingHttpServletRequest request,
             String savePrefix, Set<Node> createdNodes)
@@ -284,7 +286,12 @@
                 }
                 propertyName = paramName.substring(savePrefix.length());
             }
-            
+
+            // ignore field with a '@TypeHint' suffix. this is dealt in setProperty()
+            if (propertyName.endsWith(TYPE_HINT_SUFFIX)) {
+                continue;
+            }
+
             // SLING-130: VALUE_FROM_SUFFIX means take the value of this
             // property from a different field
             RequestParameter[] values = e.getValue();
@@ -306,15 +313,24 @@
                     continue;
                 }
             }
-            
-            setProperty(n,request,propertyName,values,createdNodes);
+
+            // @TypeHint example
+            // <input type="text" name="./age" />
+            // <input type="hidden" name="./age@TypeHint" value="long" />
+            // causes the setProperty using the 'long' property type
+            final String thName = e.getKey() + TYPE_HINT_SUFFIX;
+            final RequestParameter rp = request.getRequestParameter(thName);
+            final String typeHint = rp == null ? null : rp.getString();
+            setProperty(n, request, propertyName, values, createdNodes, typeHint);
         }
     }
 
     /** Set a single Property on node N
      * @throws RepositoryException */
-    private void setProperty(Node n, SlingHttpServletRequest request, String name,
-            RequestParameter[] values, Set<Node> createdNodes) throws RepositoryException {
+    private void setProperty(Node n, SlingHttpServletRequest request,
+                             String name, RequestParameter[] values,
+                             Set<Node> createdNodes, String typeHint)
+            throws RepositoryException {
 
         // split the relative path identifying the property to be saved
         String proppath = name;
@@ -356,10 +372,12 @@
             parent = (Node) s.getItem(path);
         }
 
-        // TODO String typehint = request.getParameter(proppath + "@TypeHint");
-        final String typeHint = null;
-        final boolean nodeIsNew = createdNodes.contains(parent);
-        propertyValueSetter.setProperty(parent, propname, values, typeHint, nodeIsNew);
+        if (values[0].isFormField()) {
+            final boolean nodeIsNew = createdNodes.contains(parent);
+            propertyValueSetter.setProperty(parent, propname, values, typeHint, nodeIsNew);
+        } else {
+            uploadHandler.setFile(request, parent, propname, values, typeHint);
+        }
 }
 
     /**

Added: incubator/sling/trunk/usling/usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/UploadFileTest.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/UploadFileTest.java?rev=612842&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/UploadFileTest.java (added)
+++ incubator/sling/trunk/usling/usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/UploadFileTest.java Thu Jan 17 07:18:10 2008
@@ -0,0 +1,148 @@
+/*
+ * 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 org.apache.sling.usling.webapp.integrationtest;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.apache.commons.httpclient.methods.GetMethod;
+
+/**
+ * Test uploading files using the ujax post servlet (SLING-168)
+ */
+public class UploadFileTest extends UslingHttpTestBase {
+
+    private static final String TEST_FILE = "src/test/resources/integration-test/file-to-upload.txt";
+    
+    public void testDistinctResource() throws IOException {
+        String folderPath = "/UploadFileTest_1_" + System.currentTimeMillis();
+        final String url = HTTP_BASE_URL + folderPath;
+
+        // create new node
+        String urlOfNewNode = null;
+        try {
+            urlOfNewNode = testClient.createNode(url, null);
+        } catch(IOException ioe) {
+            fail("createNode failed: " + ioe);
+        }
+
+        // upload local file
+        File localFile = new File(TEST_FILE);
+        testClient.uploadToFileNode(urlOfNewNode, localFile, "./file", null);
+
+        // get and check URL of created file
+        String urlOfFileNode = urlOfNewNode + "/file";
+        final GetMethod get = new GetMethod(urlOfFileNode);
+        final int status = httpClient.executeMethod(get);
+        assertEquals(urlOfFileNode + " must be accessible after createNode",200,status);
+
+        /*
+        We should check the data, but nt:resources are not handled yet
+        // compare data with local file (just length)
+        final byte[] data = get.getResponseBody();
+        assertEquals("size of file must be same", localFile.length(), data.length);
+        */
+        String data = get.getResponseBodyAsString();
+        assertTrue("checking for content", data.contains("http://www.apache.org/licenses/LICENSE-2.0"));
+
+        // download structure
+        String json = getContent(urlOfFileNode + ".json", CONTENT_TYPE_JSON);
+        // just check for some strings
+        assertTrue("checking primary type", json.contains("\"jcr:primaryType\":\"nt:resource\""));
+        assertTrue("checking mime type", json.contains("\"jcr:mimeType\":\"text/plain\""));
+
+    }
+
+    public void testDistinctResourceWithType() throws IOException {
+        String folderPath = "/UploadFileTest_1_" + System.currentTimeMillis();
+        final String url = HTTP_BASE_URL + folderPath;
+
+        // create new node
+        String urlOfNewNode = null;
+        try {
+            urlOfNewNode = testClient.createNode(url, null);
+        } catch(IOException ioe) {
+            fail("createNode failed: " + ioe);
+        }
+
+        // upload local file
+        File localFile = new File(TEST_FILE);
+        testClient.uploadToFileNode(urlOfNewNode, localFile, "./file", "nt:unstructured");
+
+        // get and check URL of created file
+        String urlOfFileNode = urlOfNewNode + "/file";
+        final GetMethod get = new GetMethod(urlOfFileNode);
+        final int status = httpClient.executeMethod(get);
+        assertEquals(urlOfFileNode + " must be accessible after createNode",200,status);
+
+        /*
+        We should check the data, but nt:resources are not handled yet
+        // compare data with local file (just length)
+        final byte[] data = get.getResponseBody();
+        assertEquals("size of file must be same", localFile.length(), data.length);
+        */
+        String data = get.getResponseBodyAsString();
+        assertTrue("checking for content", data.contains("http://www.apache.org/licenses/LICENSE-2.0"));
+
+        // download structure
+        String json = getContent(urlOfFileNode + ".json", CONTENT_TYPE_JSON);
+        // just check for some strings
+        assertTrue("checking primary type", json.contains("\"jcr:primaryType\":\"nt:unstructured\""));
+        assertTrue("checking mime type", json.contains("\"jcr:mimeType\":\"text/plain\""));
+    }
+
+    public void testDistinctFile() throws IOException {
+        String folderPath = "/UploadFileTest_1_" + System.currentTimeMillis();
+        testClient.mkdirs(WEBDAV_BASE_URL, folderPath);
+        final String url = HTTP_BASE_URL + folderPath;
+
+
+        // upload local file
+        File localFile = new File(TEST_FILE);
+        testClient.uploadToFileNode(url, localFile, "./file", null);
+
+        // get and check URL of created file
+        String urlOfFileNode = url + "/file";
+        
+        /*
+        TODO: does not work, since no nt:file resource type handler present ???
+
+        final GetMethod get = new GetMethod(urlOfFileNode);
+        final int status = httpClient.executeMethod(get);
+        assertEquals(urlOfFileNode + " must be accessible after createNode",200,status);
+
+        // compare data with local file (just length)
+        final byte[] data = get.getResponseBody();
+        assertEquals("size of file must be same", localFile.length(), data.length);
+        */
+        
+        String webdavUrl = WEBDAV_BASE_URL + folderPath + "/file";
+        final GetMethod get = new GetMethod(webdavUrl);
+        final int status = httpClient.executeMethod(get);
+        assertEquals(urlOfFileNode + " must be accessible after createNode",200,status);
+
+        // compare data with local file (just length)
+        final byte[] data = get.getResponseBody();
+        assertEquals("size of file must be same", localFile.length(), data.length);
+
+        // download structure
+        String json = getContent(urlOfFileNode + ".json", CONTENT_TYPE_JSON);
+        // just check for some strings
+        assertTrue("checking primary type", json.contains("\"jcr:primaryType\":\"nt:file\""));
+    }
+
+}
\ No newline at end of file

Propchange: incubator/sling/trunk/usling/usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/UploadFileTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/sling/trunk/usling/usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/UploadFileTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: incubator/sling/trunk/usling/usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/helpers/UslingIntegrationTestClient.java
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/helpers/UslingIntegrationTestClient.java?rev=612842&r1=612841&r2=612842&view=diff
==============================================================================
--- incubator/sling/trunk/usling/usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/helpers/UslingIntegrationTestClient.java (original)
+++ incubator/sling/trunk/usling/usling-webapp/src/test/java/org/apache/sling/usling/webapp/integrationtest/helpers/UslingIntegrationTestClient.java Thu Jan 17 07:18:10 2008
@@ -18,6 +18,7 @@
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.File;
 import java.util.Map;
 
 import org.apache.commons.httpclient.HttpClient;
@@ -29,6 +30,8 @@
 import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
 import org.apache.commons.httpclient.methods.multipart.Part;
 import org.apache.commons.httpclient.methods.multipart.StringPart;
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.sling.usling.webapp.integrationtest.UslingHttpTestBase;
 
 /** Client functions to interact with microsling in integration tests */ 
 public class UslingIntegrationTestClient {
@@ -130,7 +133,37 @@
         if(status!=302) {
             throw new IOException("Expected status code 302 for POST, got " + status + ", URL=" + url);
         }
-        final String location = post.getResponseHeader("Location").getValue();
+        String location = post.getResponseHeader("Location").getValue();
+        post.releaseConnection();
+        // simple check if host is missing
+        if (!location.startsWith("http://")) {
+            String host = UslingHttpTestBase.HTTP_BASE_URL;
+            int idx = host.indexOf('/', 8);
+            if (idx > 0) {
+                host = host.substring(0, idx);
+            }
+            location = host + location;
+        }
         return location;
     }
+
+    /** Upload to an file node structure, see SLING-168 */
+    public void uploadToFileNode(String url, File localFile, String fieldName, String typeHint)
+        throws IOException {
+
+        final Part[] parts = new Part[typeHint == null ? 1 : 2];
+        parts[0] = new FilePart(fieldName, localFile);
+        if (typeHint != null) {
+            parts[1] = new StringPart(fieldName + "@TypeHint", typeHint);
+        }
+        final PostMethod post = new PostMethod(url);
+        post.setFollowRedirects(false);
+        post.setRequestEntity(new MultipartRequestEntity(parts, post.getParams()));
+
+        final int status = httpClient.executeMethod(post);
+        if(status!=302) {
+            throw new IOException("Expected status code 302 for POST, got " + status + ", URL=" + url);
+        }
+    }
+
 }

Added: incubator/sling/trunk/usling/usling-webapp/src/test/resources/integration-test/file-to-upload.txt
URL: http://svn.apache.org/viewvc/incubator/sling/trunk/usling/usling-webapp/src/test/resources/integration-test/file-to-upload.txt?rev=612842&view=auto
==============================================================================
--- incubator/sling/trunk/usling/usling-webapp/src/test/resources/integration-test/file-to-upload.txt (added)
+++ incubator/sling/trunk/usling/usling-webapp/src/test/resources/integration-test/file-to-upload.txt Thu Jan 17 07:18:10 2008
@@ -0,0 +1,12 @@
+This file is used by UploadFileTest.java.
+
+In must contain http://www.apache.org/licenses/LICENSE-2.0 for tests.
+
+Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Fusce semper ipsum et lorem. In hac habitasse 
+platea dictumst. Donec dictum tincidunt purus. Aenean quis nunc. Aliquam rhoncus. Proin sed risus. 
+Maecenas porta arcu in nisi. Pellentesque quis sapien quis lectus vehicula aliquet. Cras ornare elit 
+eget massa. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed 
+ut justo. Integer porttitor quam. Aliquam aliquet. Nulla interdum arcu vitae nibh. Morbi dapibus odio 
+a sem. Integer dictum. Praesent vel eros nec ipsum venenatis malesuada. Vestibulum rutrum mi ac ligula. 
+Ut nisl ligula, vehicula dignissim, accumsan quis, faucibus sed, sapien. Quisque purus tellus, euismod 
+id, auctor quis, rutrum non, augue.
\ No newline at end of file

Propchange: incubator/sling/trunk/usling/usling-webapp/src/test/resources/integration-test/file-to-upload.txt
------------------------------------------------------------------------------
    svn:eol-style = native