Added: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java?rev=740749&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java Wed Feb 4 14:13:24 2009
@@ -0,0 +1,298 @@
+/*
+ * 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.jackrabbit.server.util;
+
+import org.apache.commons.fileupload.FileItem;
+import org.apache.commons.fileupload.FileItemFactory;
+import org.apache.commons.fileupload.FileUploadException;
+import org.apache.commons.fileupload.disk.DiskFileItemFactory;
+import org.apache.commons.fileupload.servlet.ServletFileUpload;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * HttpMultipartPost...
+ */
+class HttpMultipartPost {
+
+ /**
+ * logger instance
+ */
+ private static final Logger log = LoggerFactory.getLogger(HttpMultipartPost.class);
+
+ private final Map nameToItems = new LinkedHashMap();
+ private final Set fileParamNames = new HashSet();
+
+ private boolean initialized;
+
+ HttpMultipartPost(HttpServletRequest request, File tmpDir) throws IOException {
+ extractMultipart(request, tmpDir);
+ initialized = true;
+ }
+
+ /**
+ *
+ * @param tmpDir
+ * @return
+ */
+ private static FileItemFactory getFileItemFactory(File tmpDir) {
+ DiskFileItemFactory fiFactory = new DiskFileItemFactory(DiskFileItemFactory.DEFAULT_SIZE_THRESHOLD, tmpDir);
+ return fiFactory;
+ }
+
+ /**
+ *
+ * @param request
+ * @param tmpDir
+ * @throws IOException
+ */
+ private void extractMultipart(HttpServletRequest request, File tmpDir)
+ throws IOException {
+ if (!ServletFileUpload.isMultipartContent(request)) {
+ log.warn("Request does not contain multipart content -> ignoring.");
+ return;
+ }
+
+ ServletFileUpload upload = new ServletFileUpload(getFileItemFactory(tmpDir));
+ try {
+ List fileItems = upload.parseRequest(request);
+ for (Iterator it = fileItems.iterator(); it.hasNext();) {
+ FileItem item = (FileItem) it.next();
+ addItem(item);
+ }
+ } catch (FileUploadException e) {
+ log.error("Error while processing multipart.", e);
+ throw new IOException(e.toString());
+ }
+ }
+
+ /**
+ * Add the given file item to the list defined for its name and make the
+ * list is present in the map. If the item does not represent a simple
+ * form field its name is also added to the fileParamNames set.
+ *
+ * @param item The {@link FileItem} to add.
+ */
+ private void addItem(FileItem item) {
+ String name = item.getFieldName();
+ ArrayList l = (ArrayList) nameToItems.get(item.getFieldName());
+ if (l == null) {
+ l = new ArrayList();
+ nameToItems.put(name, l);
+ }
+ l.add(item);
+
+ // if file parameter, add name to the set of file params in order to
+ // be able to extract the file param values later on without iterating
+ // over all keys.
+ if (!item.isFormField()) {
+ fileParamNames.add(name);
+ }
+ }
+
+ private void checkInitialized() {
+ if (!initialized) {
+ throw new IllegalStateException("HttpMultipartPost not initialized (or already disposed).");
+ }
+ }
+
+ /**
+ * Release all file items hold with the name-to-items map. specially those
+ * having a tmp-file associated with.
+ *
+ * @see FileItem#delete()
+ */
+ synchronized void dispose() {
+ checkInitialized();
+
+ for (Iterator it = nameToItems.values().iterator(); it.hasNext();) {
+ List fileItems = (List) it.next();
+ for (int i = 0; i < fileItems.size(); i++) {
+ FileItem item = (FileItem) fileItems.get(i);
+ item.delete();
+ }
+ }
+
+ nameToItems.clear();
+ fileParamNames.clear();
+ initialized = false;
+ }
+
+ /**
+ * Returns an iterator over all file item names.
+ *
+ * @return a set of strings.
+ */
+ Set getParameterNames() {
+ checkInitialized();
+ return nameToItems.keySet();
+ }
+
+
+ /**
+ * Returns the content types of the paramaters with the given name. If
+ * the parameter does not exist null is returned. If the content
+ * type of any of the parameter values is not known, the corresponding entry
+ * in the array returned is null.
+ *
+ * The content type of a paramater is only known here if the information + * has been sent by the client browser. This is generally only the case + * for file upload fields of HTML forms which have been posted using the + * HTTP POST with multipart/form-data encoding. + *
+ * Example : For the form + *
++ * + * this method will return an array of two entries when called for the + * Upload parameter. The first entry will contain the content + * type (if transmitted by the client) of the file uploaded. The second + * entry will be
null because the content type of the text
+ * input field will generally not be sent by the client.
+ *
+ * @param name The name of the paramater whose content type is to be
+ * returned.
+ * @return The content types of the file items with the specified name.
+ */
+ String[] getParameterTypes(String name) {
+ checkInitialized();
+ String[] cts = null;
+ List l = (List) nameToItems.get(name);
+ if (l != null && !l.isEmpty()) {
+ cts = new String[l.size()];
+ for (int i = 0; i < cts.length; i++) {
+ cts[i] = ((FileItem) l.get(i)).getContentType();
+ }
+ }
+ return cts;
+ }
+
+ /**
+ * Returns the first value of the file items with the given name.
+ * The byte to string converstion is done using either the contenttype of
+ * the file items or the formEncoding.
+ *
+ * Please note that if the addressed parameter is an uploaded file rather
+ * than a simple form entry, the name of the original file is returned
+ * instead of the content.
+ *
+ * @param name the name of the parameter
+ * @return the string of the first value or null if the
+ * parameter does not exist
+ */
+ String getParameter(String name) {
+ checkInitialized();
+ List l = (List) nameToItems.get(name);
+ if (l == null || l.isEmpty()) {
+ return null;
+ } else {
+ FileItem item = ((FileItem) l.get(0));
+ if (item.isFormField()) {
+ return item.getString();
+ } else {
+ return item.getName();
+ }
+ }
+ }
+
+ /**
+ * Returns an array of Strings with all values of the parameter addressed
+ * by name. the byte to string conversion is done using either
+ * the content type of the multipart body or the formEncoding.
+ *
+ * Please note that if the addressed parameter is an uploaded file rather
+ * than a simple form entry, the name of the original file is returned
+ * instead of the content.
+ *
+ * @param name the name of the parameter
+ * @return a string array of values or null if no entry with the
+ * given name exists.
+ */
+ String[] getParameterValues(String name) {
+ checkInitialized();
+ List l = (List) nameToItems.get(name);
+ if (l == null || l.isEmpty()) {
+ return null;
+ } else {
+ String[] values = new String[l.size()];
+ for (int i = 0; i < values.length; i++) {
+ FileItem item = ((FileItem) l.get(i));
+ if (item.isFormField()) {
+ values[i] = item.getString();
+ } else {
+ values[i] = item.getName();
+ }
+ }
+ return values;
+ }
+ }
+
+ /**
+ * Returns a set of the file parameter names. An empty set if
+ * no file parameters were present in the request.
+ *
+ * @return an set of file item names representing the file
+ * parameters available with the request.
+ */
+ Set getFileParameterNames() {
+ checkInitialized();
+ return fileParamNames;
+ }
+
+ /**
+ * Returns an array of input streams for uploaded file parameters.
+ *
+ * @param name the name of the file parameter(s)
+ * @return an array of input streams or null if no file params
+ * with the given name exist.
+ * @throws IOException if an I/O error occurs
+ */
+ InputStream[] getFileParameterValues(String name) throws IOException {
+ checkInitialized();
+ InputStream[] values = null;
+ if (fileParamNames.contains(name)) {
+ List l = (List) nameToItems.get(name);
+ if (l != null && !l.isEmpty()) {
+ List ins = new ArrayList(l.size());
+ for (Iterator it = l.iterator(); it.hasNext();) {
+ FileItem item = (FileItem) it.next();
+ if (!item.isFormField()) {
+ ins.add(item.getInputStream());
+ }
+ }
+ values = (InputStream[]) ins.toArray(new InputStream[ins.size()]);
+ }
+ }
+ return values;
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java?rev=740749&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java Wed Feb 4 14:13:24 2009
@@ -0,0 +1,126 @@
+/*
+ * 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.jackrabbit.server.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.File;
+import java.util.HashSet;
+import java.util.Iterator;
+
+/**
+ * RequestData...
+ */
+public class RequestData {
+
+ /**
+ * logger instance
+ */
+ private static final Logger log = LoggerFactory.getLogger(RequestData.class);
+
+ private final HttpServletRequest request;
+ private final HttpMultipartPost mpReq;
+
+ public RequestData(HttpServletRequest request, File tmpDir) throws IOException {
+ this.request = request;
+ this.mpReq = new HttpMultipartPost(request, tmpDir);
+ }
+
+ /**
+ * Dispose resources used.
+ */
+ public void dispose() {
+ mpReq.dispose();
+ }
+
+ /**
+ * Returns an iterator over all parameter names.
+ *
+ * @return an iterator over strings.
+ */
+ public Iterator getParameterNames() {
+
+ HashSet names = new HashSet(request.getParameterMap().keySet());
+ names.addAll(mpReq.getParameterNames());
+
+ return names.iterator();
+ }
+
+ /**
+ * Returns the first value of the parameter with the given name.
+ * The byte to string converstion is done using either the contenttype of
+ * the parameter or the formEncoding.
+ *
+ * Please note that if the addressed parameter is a file parameter, the
+ * name of the original file is returned, and not its content.
+ *
+ * @param name the name of the parameter
+ * @return the string of the first value or null if the
+ * parameter does not exist
+ */
+ public String getParameter(String name) {
+ String ret = mpReq.getParameter(name);
+ return (ret == null) ? request.getParameter(name) : ret;
+ }
+
+ /**
+ * Returns the content types retrieved for parameters with the specified
+ * name from the multipart or null if the multipart does not
+ * contain parameter(s) with the given name.
+ *
+ * @param name parameter name
+ * @return the parameter types retrieved for the specified parameter
+ * name from the multipart or null.
+ */
+ public String[] getParameterTypes(String name) {
+ String[] types = mpReq.getParameterTypes(name);
+ return types == null ? null : types;
+ }
+
+ /**
+ * Returns an array of Strings with all values of the parameter addressed
+ * by name. the byte to string conversion is done using either
+ * the content type of the multipart body or the formEncoding.
+ *
+ * Please note that if the addressed parameter is a file parameter, the
+ * name of the original file is returned, and not its content.
+ *
+ * @param name the name of the parameter
+ * @return a string array of values or null if the parameter
+ * does not exist.
+ */
+ public String[] getParameterValues(String name) {
+ String[] ret = mpReq.getParameterValues(name);
+ return ret == null ? request.getParameterValues(name) : ret;
+ }
+
+ /**
+ * Returns an array of input streams for uploaded file parameters.
+ *
+ * @param name the name of the file parameter(s)
+ * @return an array of input streams or an empty array if no file params
+ * with the given name exist.
+ * @throws IOException if an I/O error occurs
+ */
+ public InputStream[] getFileParameters(String name) throws IOException {
+ return mpReq.getFileParameterValues(name);
+ }
+}
\ No newline at end of file
Propchange: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java?rev=740749&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java Wed Feb 4 14:13:24 2009
@@ -0,0 +1,378 @@
+/*
+ * 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.jackrabbit.server.remoting.davex;
+
+import junit.framework.TestCase;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/** DiffParserTest... */
+public class DiffParserTest extends TestCase {
+
+ public void testSetProperty() throws IOException, DiffException {
+ ArrayList l = new ArrayList();
+ l.add("\"simple string\"");
+ l.add("2345");
+ l.add("true");
+ l.add("false");
+ l.add("234.3455");
+ l.add("null");
+
+ for (int i = 0; i < l.size(); i++) {
+ final String value = l.get(i).toString();
+ String diff = "^/a/prop : " + value;
+
+ DummyDiffHandler handler = new DummyDiffHandler() {
+ public void setProperty(String targetPath, String diffValue) {
+ assertEquals(targetPath, "/a/prop");
+ assertEquals(value, diffValue);
+ }
+ };
+ DiffParser parser = new DiffParser(handler);
+ parser.parse(diff);
+ }
+ }
+
+ public void testSetPropertyMissing() throws IOException,
+ DiffException {
+ ArrayList l = new ArrayList();
+ l.add("");
+ l.add(null);
+
+ for (int i = 0; i < l.size(); i++) {
+ Object obj = l.get(i);
+ String value = (obj == null) ? "" : obj.toString();
+ String diff = "^/a/prop : " + value;
+
+ DummyDiffHandler handler = new DummyDiffHandler() {
+ public void setProperty(String targetPath, String diffValue) {
+ assertEquals(targetPath, "/a/prop");
+ assertTrue(diffValue == null || "".equals(diffValue));
+ }
+ };
+ DiffParser parser = new DiffParser(handler);
+ parser.parse(diff);
+ }
+ }
+
+ public void testSetPropertyWithUnicodeChars() throws IOException,
+ DiffException {
+ final String value = "\"String value containing \u2355\u8723 unicode chars.\"";
+ String diff = "^/a/prop : " + value;
+
+ DiffHandler handler = new DummyDiffHandler() {
+ public void setProperty(String targetPath, String diffValue) {
+ assertEquals(targetPath, "/a/prop");
+ assertEquals(value, diffValue);
+ }
+ };
+
+ DiffParser parser = new DiffParser(handler);
+ parser.parse(diff);
+ }
+
+ public void testSetPropertyWithTrailingLineSep() throws IOException,
+ DiffException {
+ final String value = "\"String value ending with \r\r\n\n\r\n.\"";
+ String diff = "^/a/prop : " + value;
+
+ DiffHandler handler = new DummyDiffHandler() {
+ public void setProperty(String targetPath, String diffValue) {
+ assertEquals(targetPath, "/a/prop");
+ assertEquals(value, diffValue);
+ }
+ };
+
+ DiffParser parser = new DiffParser(handler);
+ parser.parse(diff);
+ }
+
+ public void testSetPropertyWithSpecialChar() throws IOException, DiffException {
+ final String value = "+abc \\r+ \\n-ab >c \r\\r\\n+";
+ String diff = "^/a/prop : " + value;
+
+ DiffHandler handler = new DummyDiffHandler() {
+ public void setProperty(String targetPath, String diffValue) {
+ assertEquals(targetPath, "/a/prop");
+ assertEquals(value, diffValue);
+ }
+ };
+
+ DiffParser parser = new DiffParser(handler);
+ parser.parse(diff);
+ }
+
+ public void testSetPropertyUnterminatedString() throws IOException,
+ DiffException {
+ final String value = "\"String value ending with \r\r\n\n\r\n.";
+ String diff = "^/a/prop : " + value;
+
+ DiffHandler handler = new DummyDiffHandler() {
+ public void setProperty(String targetPath, String diffValue) {
+ assertEquals(targetPath, "/a/prop");
+ assertEquals(value, diffValue);
+ }
+ };
+ DiffParser parser = new DiffParser(handler);
+ parser.parse(diff);
+ }
+
+ public void testSetPropertyWithUnescapedAction() throws IOException,
+ DiffException {
+ String diff = "^abc : \r+def : \n-ghi : \r\n^jkl : \n\r>mno : \n";
+
+ DiffHandler handler = new DummyDiffHandler() {
+ public void addNode(String targetPath, String diffValue)
+ throws DiffException {
+ assertEquals("def", targetPath);
+ assertEquals("", diffValue);
+ }
+ public void setProperty(String targetPath, String diffValue) {
+ assertTrue("abc".equals(targetPath) || "jkl".equals(targetPath));
+ assertEquals("", diffValue);
+ }
+ public void remove(String targetPath, String diffValue)
+ throws DiffException {
+ assertEquals("ghi", targetPath);
+ assertEquals("", diffValue);
+ }
+
+ public void move(String targetPath, String diffValue) throws DiffException {
+ assertEquals("mno", targetPath);
+ assertEquals("\n", diffValue);
+ }
+ };
+
+ DiffParser parser = new DiffParser(handler);
+ parser.parse(diff);
+ }
+
+ public void testValidDiffs() throws IOException, DiffException {
+ List l = new ArrayList();
+ // unquoted string value
+ l.add(new String[] {"+/a/b : 134", "/a/b","134"});
+ l.add(new String[] {"+/a/b : 2.3", "/a/b","2.3"});
+ l.add(new String[] {"+/a/b : true", "/a/b","true"});
+ // quoted string value
+ l.add(new String[] {"+/a/b : \"true\"", "/a/b","\"true\""});
+ l.add(new String[] {"+/a/b : \"string value containing \u3456 unicode char.\"", "/a/b","\"string value containing \u3456unicode char.\""});
+ // value consisting of quotes
+ l.add(new String[] {"+/a/b : \"", "/a/b","\""});
+ l.add(new String[] {"+/a/b : \"\"", "/a/b","\"\""});
+ // value consisting of single
+ l.add(new String[] {"+/a/b : '", "/a/b","'"});
+ l.add(new String[] {"+/a/b : ''''", "/a/b","''''"});
+ // value consisting of space(s) only
+ l.add(new String[] {"+/a/b : ", "/a/b"," "});
+ l.add(new String[] {"+/a/b : ", "/a/b"," "});
+ // value consisting of line separators only
+ l.add(new String[] {"+/a/b : \n", "/a/b","\n"});
+ l.add(new String[] {"+/a/b : \r", "/a/b","\r"});
+ l.add(new String[] {"+/a/b : \r\n", "/a/b","\r\n"});
+ l.add(new String[] {"+/a/b : \r\n\n\r", "/a/b","\r\n\n\r"});
+ // path containing whilespace
+ l.add(new String[] {"+/a /b : 123", "/a /b","123"});
+ l.add(new String[] {"+/a\r\t/b : 123", "/a\r\t/b","123"});
+ // path having trailing whitespace
+ l.add(new String[] {"+/a/b : 123", "/a/b","123"});
+ l.add(new String[] {"+/a/b\r : 123", "/a/b\r","123"});
+ l.add(new String[] {"+/a/b\r\n\n\r\n: 123", "/a/b\r\n\n\r\n","123"});
+ // path containing reserved characters
+ l.add(new String[] {"++abc+ : val", "+abc+","val"});
+ l.add(new String[] {"++++++ : val", "+++++","val"});
+ // value containing reserver characters
+ l.add(new String[] {"+/a/b : +", "/a/b","+"});
+ l.add(new String[] {"+/a/b : +->+-", "/a/b","+->+-"});
+ l.add(new String[] {"+/a/b : \"+->+-\"", "/a/b","\"+->+-\""});
+ // other whitespace than ' ' used as key-value separator
+ l.add(new String[] {"+/a/b :\r123", "/a/b","123"});
+ l.add(new String[] {"+/a/b\r: 123", "/a/b","123"});
+ l.add(new String[] {"+/a/b\r:\r123", "/a/b","123"});
+ l.add(new String[] {"+/a/b\r:\n123", "/a/b","123"});
+ l.add(new String[] {"+/a/b\t:\r123", "/a/b","123"});
+ l.add(new String[] {"+/a/b\t:\t123", "/a/b","123"});
+ // path containing colon
+ l.add(new String[] {"+/a:b/c:d : 123", "/a:b/c:d","123"});
+ // value starting with colon -> ok
+ l.add(new String[] {"+/a/b : : val", "/a/b",": val"});
+ // missing value
+ l.add(new String[] {"+/a/b : ", "/a/b", ""});
+ l.add(new String[] {"+/a/b :\n", "/a/b", ""});
+
+ for (Iterator it = l.iterator(); it.hasNext();) {
+ final String[] strs = (String[]) it.next();
+ DiffHandler hndl = new DummyDiffHandler() {
+ public void setProperty(String targetPath, String diffValue)
+ throws DiffException {
+ assertEquals(strs[1], targetPath);
+ assertEquals(strs[2], diffValue);
+ }
+ };
+ DiffParser parser = new DiffParser(hndl);
+ parser.parse(strs[0]);
+ }
+
+ l = new ArrayList();
+ // multiple commands
+ l.add("+abc :\n\n+def : val");
+ l.add("+abc :\n\n+def : val\n");
+ l.add("+abc : \r+def : val");
+ l.add("+/a/b : val\r+abc : \r ");
+ l.add("+/a/b : val\r+abc :\n\n ");
+ // missing value in the last action.
+ l.add("+/a/b : \r+abc :\n");
+ l.add("+/a/b : \\r+abc : abc\r\r+abc :\r");
+ l.add("+abc :\n\n+def : val\r\r>abc : ");
+
+ for (Iterator it = l.iterator(); it.hasNext();) {
+ final List li = new ArrayList();
+ DiffHandler dh = new DummyDiffHandler() {
+ public void addNode(String targetPath, String diffValue) throws DiffException {
+ li.add(diffValue);
+ }
+ };
+
+ String diff = it.next().toString();
+ DiffParser parser = new DiffParser(dh);
+ parser.parse(diff);
+ assertEquals(2, li.size());
+ }
+ }
+
+ public void testSeparatorLines() throws IOException, DiffException {
+ String diff = "+abc :\n\n+val : val";
+ DiffHandler dh = new DummyDiffHandler() {
+ public void addNode(String targetPath, String diffValue) throws DiffException {
+ if ("abc".equals(targetPath)) {
+ assertEquals("", diffValue);
+ } else {
+ assertEquals("val", diffValue);
+ }
+ }
+ };
+ new DiffParser(dh).parse(diff);
+
+ diff = "+abc :\n+val : val";
+ dh = new DummyDiffHandler() {
+ public void addNode(String targetPath, String diffValue) throws DiffException {
+ assertEquals("+val : val", diffValue);
+ }
+ };
+ new DiffParser(dh).parse(diff);
+
+ // TODO: check again: currently all line-sep. chars before an diff-char are ignored unless they are escaped in way the handler understands (e.g. JSON does: \\r for \r).
+ diff = "+abc :\r\r\r+def : val";
+ dh = new DummyDiffHandler() {
+ public void addNode(String targetPath, String diffValue) throws DiffException {
+ if ("abc".equals(targetPath)) {
+ assertEquals("", diffValue);
+ } else {
+ assertEquals("val", diffValue);
+ }
+ }
+ };
+ new DiffParser(dh).parse(diff);
+
+ diff = "+abc : val\r+def :\n\n ";
+ dh = new DummyDiffHandler() {
+ public void addNode(String targetPath, String diffValue) throws DiffException {
+ if ("abc".equals(targetPath)) {
+ assertEquals("val", diffValue);
+ } else {
+ assertEquals("\n ", diffValue);
+ }
+ }
+ };
+ new DiffParser(dh).parse(diff);
+ }
+
+ public void testUnicodeLineSep() throws IOException, DiffException {
+ String diff = "+abc : val" + new String(new byte[] {Character.LINE_SEPARATOR}, "utf-8") + "+abc : val";
+ DiffHandler dh = new DummyDiffHandler() {
+ public void addNode(String targetPath, String diffValue) throws DiffException {
+ assertEquals("abc", targetPath);
+ assertEquals("val", diffValue);
+ }
+ };
+ new DiffParser(dh).parse(diff);
+ }
+
+ public void testInvalidDiff() throws IOException, DiffException {
+ List l = new ArrayList();
+ l.add("");
+ // path, separator and value missing
+ l.add("+");
+ l.add("+/a/b : val\r+");
+ // path starting with whitespace, separator and value missing
+ l.add("+\n");
+ // separator and value missing
+ l.add("+/a/b");
+ l.add("+/a/b : val\r+abc\n");
+ l.add("+/a/b :");
+ // invalid for separator and value are missing (all : and whitespace
+ // is interpreted as part of the path.
+ l.add("+/a/b:");
+ l.add("+/a/b:val");
+ l.add("+/a/b: val");
+ l.add("+/a/b:\rval");
+ l.add("+/a/b :: val");
+ // diff starting with whitespace
+ l.add(" +/a/b: val");
+ l.add("\r\r\r\r\r\r+/a/b: val");
+ // key starting with whitespace
+ l.add("+\r/a/b : 123");
+ l.add("+ /a/b : 123");
+ // key starting with colon
+ l.add("+:/a/b : 123");
+
+ for (Iterator it = l.iterator(); it.hasNext();) {
+ String diff = it.next().toString();
+ try {
+ DiffParser parser = new DiffParser(new DummyDiffHandler());
+ parser.parse(diff);
+ fail(diff + " is not a valid diff string -> should throw DiffException.");
+ } catch (DiffException e) {
+ // ok
+ }
+ }
+ }
+
+ private class DummyDiffHandler implements DiffHandler {
+
+ public void addNode(String targetPath, String diffValue)
+ throws DiffException {
+ // does nothing
+ }
+
+ public void setProperty(String targetPath, String diffValue)
+ throws DiffException {
+ // does nothing
+ }
+
+ public void remove(String targetPath, String diffValue)
+ throws DiffException {
+ // does nothing
+ }
+
+ public void move(String targetPath, String diffValue) throws DiffException {
+ // does nothing
+ }
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/DiffParserTest.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url
Added: jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java?rev=740749&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java Wed Feb 4 14:13:24 2009
@@ -0,0 +1,39 @@
+/*
+ * 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.jackrabbit.server.remoting.davex;
+
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes all testcases for package org.apache.jackrabbit.server.remoting.davex.
+ */
+public class TestAll extends TestCase {
+
+ /**
+ * Returns a Test suite that executes all tests inside this
+ * package.
+ */
+ public static Test suite() {
+ TestSuite suite = new TestSuite("org.apache.jackrabbit.server.remoting.davex tests");
+
+ suite.addTestSuite(DiffParserTest.class);
+
+ return suite;
+ }
+}
Propchange: jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/server/remoting/davex/TestAll.java
------------------------------------------------------------------------------
svn:keywords = author date id revision url