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