jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From tri...@apache.org
Subject svn commit: r156314 [9/15] - in incubator/jackrabbit/trunk/contrib/jcr-server: ./ client/ client/src/ client/src/java/ client/src/java/org/ client/src/java/org/apache/ client/src/java/org/apache/jackrabbit/ client/src/java/org/apache/jackrabbit/client/ server/ server/src/ server/src/java/ server/src/java/org/ server/src/java/org/apache/ server/src/java/org/apache/jackrabbit/ server/src/java/org/apache/jackrabbit/server/ server/src/java/org/apache/jackrabbit/server/simple/ server/src/java/org/apache/jackrabbit/server/simple/dav/ server/src/java/org/apache/jackrabbit/server/simple/dav/lock/ server/src/java/org/apache/jackrabbit/webdav/ server/src/java/org/apache/jackrabbit/webdav/spi/ server/src/java/org/apache/jackrabbit/webdav/spi/lock/ server/src/java/org/apache/jackrabbit/webdav/spi/nodetype/ server/src/java/org/apache/jackrabbit/webdav/spi/observation/ server/src/java/org/apache/jackrabbit/webdav/spi/search/ server/src/java/org/apache/jackrabbit/webdav/spi/transaction/ server/src/java/org/apache/jackrabbit/webdav/spi/version/ server/src/java/org/apache/jackrabbit/webdav/spi/version/report/ webapp/ webapp/src/ webapp/src/webapp/ webapp/src/webapp/WEB-INF/ webapp/src/webapp/WEB-INF/repository/ webdav/ webdav/src/ webdav/src/java/ webdav/src/java/org/ webdav/src/java/org/apache/ webdav/src/java/org/apache/jackrabbit/ webdav/src/java/org/apache/jackrabbit/webdav/ webdav/src/java/org/apache/jackrabbit/webdav/lock/ webdav/src/java/org/apache/jackrabbit/webdav/observation/ webdav/src/java/org/apache/jackrabbit/webdav/ordering/ webdav/src/java/org/apache/jackrabbit/webdav/property/ webdav/src/java/org/apache/jackrabbit/webdav/search/ webdav/src/java/org/apache/jackrabbit/webdav/transaction/ webdav/src/java/org/apache/jackrabbit/webdav/util/ webdav/src/java/org/apache/jackrabbit/webdav/version/ webdav/src/java/org/apache/jackrabbit/webdav/version/report/
Date Sun, 06 Mar 2005 14:03:11 GMT
Added: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/IfHeader.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/IfHeader.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/IfHeader.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/IfHeader.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,833 @@
+/*
+ * 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.jackrabbit.webdav;
+
+import org.apache.log4j.Logger;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Iterator;
+import java.io.StringReader;
+import java.io.IOException;
+import java.io.Reader;
+
+/**
+ * The <code>IfHeader</code> class represents the state lists defined
+ * through the HTTP <em>If</em> header, which is specified in RFC 2518 as
+ * follows :
+ * <pre>
+     If = "If" ":" ( 1*No-tag-list | 1*Tagged-list)
+     No-tag-list = List
+     Tagged-list = Resource 1*List
+     Resource = Coded-URL
+     List = "(" 1*(["Not"](State-etag | "[" entity-tag "]")) ")"
+     State-etag = Coded-URL
+     Coded-URL = "<" absoluteURI ">"
+ * </pre>
+ * <p>
+ * Reformulating this specification into proper EBNF as specified by N. Wirth
+ * we get the following productions, which map to the parse METHODS of this
+ * class. Any whitespace is ignored except for white space surrounding and
+ * within words which is considered significant.
+ * <pre>
+     If = "If:" ( Tagged | Untagged ).
+     Tagged = { "<" Word ">" Untagged } .
+     Untagged = { "(" IfList ")" } .
+     IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
+     Word = characters .
+ * </pre>
+ * <p>
+ * An <em>If</em> header either contains untagged <em>IfList</em> entries or
+ * tagged <em>IfList</em> entries but not a mixture of both. An <em>If</em>
+ * header containing tagged entries is said to be of <em>tagged</em> type while
+ * an <em>If</em> header containing untagged entries is said to be of
+ * <em>untagged</em> type.
+ * <p>
+ * An <em>IfList</em> is a list of tokens - words enclosed in <em>&lt; &gt;</em>
+ * - and etags - words enclosed in <em>[ ]</em>. An <em>IfList</em> matches a
+ * (token, etag) tuple if all entries in the list match. If an entry in the list
+ * is prefixed with the word <em>Not</em> (parsed case insensitively) the entry
+ * must not match the concrete token or etag.
+ * <p>
+ * Example: The <em>ifList</em> <code>(&lt;token&gt; [etag])</code> only matches
+ * if the concret token has the value <code>token</code> and the conrete etag
+ * has the value <code>etag</code>. On the other hand, the <em>ifList</em>
+ * <code>(Not &lt;notoken&gt;)</code> matches any token which is not
+ * <code>notoken</code> (in this case the concrete value of the etag is
+ * not taken into consideration).
+ *
+ * @author Felix Meschberger
+ */
+public class IfHeader {
+
+    /**
+     * default logger
+     */
+    private static final Logger log = Logger.getLogger(IfHeader.class);
+
+    /**
+     * The list of untagged state entries
+     */
+    private final IfHeaderInterface ifHeader;
+
+    /**
+     * The list of all tokens present in the If header.
+     */
+    private List allTokens = new ArrayList();
+
+    /**
+     * Parses the <em>If</em> header and creates and internal representation
+     * which is easy to query.
+     *
+     * @param req The request object
+     */
+    public IfHeader(HttpServletRequest req) {
+
+	String ifHeaderValue = req.getHeader(DavConstants.HEADER_IF);
+        if (ifHeaderValue != null && ifHeaderValue.length() > 0) {
+
+            StringReader reader = null;
+            int firstChar = 0;
+
+            try {
+                reader = new StringReader(ifHeaderValue);
+
+                // get the first character to decide - expect '(' or '<'
+                try {
+                    reader.mark(1);
+                    firstChar = readWhiteSpace(reader);
+                    reader.reset();
+                } catch (IOException ignore) {
+                    // may be thrown according to API but is only thrown by the
+                    // StringReader class if the reader is already closed.
+                }
+
+                if (firstChar == '(') {
+                    ifHeader = parseUntagged(reader);
+                } else if (firstChar == '<') {
+                    ifHeader = parseTagged(reader);
+                } else {
+                    logIllegalState("If", firstChar, "(<", null);
+                    ifHeader = null;
+                }
+
+            } finally  {
+                if (reader != null) {
+                    reader.close();
+                }
+            }
+
+        } else {
+            log.debug("IfHeader: No If header in request");
+            ifHeader = null;
+        }
+    }
+
+    /**
+     * Tries to match the contents of the <em>If</em> header with the given
+     * token and etag values with the restriction to only check for the tag.
+     * <p>
+     * If the <em>If</em> header is of untagged type, the untagged <em>IfList</em>
+     * is matched against the token and etag given: A match of the token and
+     * etag is found if at least one of the <em>IfList</em> entries match the
+     * token and etag tupel.
+     *
+     * @param tag The tag to identify the <em>IfList</em> to match the token
+     * and etag against.
+     * @param token The token to compare.
+     * @param etag The ETag value to compare.
+     *
+     * @return If the <em>If</em> header is of untagged type the result is
+     *      <code>true</code> if any of the <em>IfList</em> entries matches
+     *      the token and etag values. For tagged type <em>If</em> header the
+     *      result is <code>true</code> if either no entry for the given tag
+     *      exists in the <em>If</em> header or if the <em>IfList</em> for the
+     *      given tag matches the token and etag given.
+     */
+    public boolean matches(String tag, String token, String etag) {
+        if (ifHeader == null) {
+            log.debug("matches: No If header, assume match");
+            return true;
+        } else {
+            return ifHeader.matches(tag, token, etag);
+        }
+    }
+
+    /**
+     * 
+     * @return
+     */
+    public Iterator getAllTokens() {
+        return allTokens.iterator();
+    }
+
+    //---------- internal IF header parser -------------------------------------
+    /**
+     * Parses a tagged type <em>If</em> header. This method implements the
+     * <em>Tagged</em> production given in the class comment :
+     * <pre>
+         Tagged = { "<" Word ">" Untagged } .
+     * </pre>
+     *
+     * @param reader
+     * @return
+     */
+    private IfHeaderMap parseTagged(StringReader reader) {
+        IfHeaderMap map = new IfHeaderMap();
+        try {
+            while (true) {
+                // read next non-whitespace
+                int c = readWhiteSpace(reader);
+                if (c < 0) {
+                    // end of input, no more entries
+                    break;
+                } else if (c == '<') {
+                    // start a tag with an IfList
+                    String resource = readWord(reader, '>');
+                    if (resource != null) {
+                        // go to untagged after reading the resource
+                        map.put(resource, parseUntagged(reader));
+                    } else {
+                        break;
+                    }
+                } else {
+                    // unexpected character
+                    // catchup to end of input or start of a tag
+                    logIllegalState("Tagged", c, "<", reader);
+                }
+            }
+        } catch (IOException ioe) {
+            log.error("parseTagged: Problem parsing If header: "+ioe.toString());
+        }
+
+        return map;
+    }
+
+    /**
+     * Parses an untagged type <em>If</em> header. This method implements the
+     * <em>Untagged</em> production given in the class comment :
+     * <pre>
+         Untagged = { "(" IfList ")" } .
+     * </pre>
+     *
+     * @param reader The <code>StringReader</code> to read from for parsing
+     *
+     * @return An <code>ArrayList</code> of {@link IfList} entries.
+     */
+    private IfHeaderList parseUntagged(StringReader reader) {
+        IfHeaderList list = new IfHeaderList();
+        try {
+            while (true) {
+                // read next non-whitespace
+                reader.mark(1);
+                int c = readWhiteSpace(reader);
+                if (c < 0) {
+                    // end of input, no more IfLists
+                    break;
+
+                } else if (c == '(') {
+                    // start of an IfList, parse
+                    list.add(parseIfList(reader));
+
+                } else if (c == '<') {
+                    // start of a tag, return current list
+                    reader.reset();
+                    break;
+
+                } else {
+                    // unexpected character
+                    // catchup to end of input or start of an IfList
+                    logIllegalState("Untagged", c, "(", reader);
+                }
+            }
+        } catch (IOException ioe) {
+            log.error("parseUntagged: Problem parsing If header: "+ioe.toString());
+        }
+        return list;
+    }
+
+    /**
+     * Parses an <em>IfList</em> in the <em>If</em> header. This method
+     * implements the <em>Tagged</em> production given in the class comment :
+     * <pre>
+         IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
+     * </pre>
+     *
+     * @param reader The <code>StringReader</code> to read from for parsing
+     *
+     * @return The {@link IfList} for the input <em>IfList</em>.
+     *
+     * @throws IOException if a problem occurrs during reading.
+     */
+    private IfList parseIfList(StringReader reader) throws IOException {
+        IfList res = new IfList();
+        boolean positive = true;
+        String word;
+
+        ReadLoop:
+        while (true) {
+            int nextChar = readWhiteSpace(reader);
+            switch (nextChar) {
+                case 'N':
+                case 'n':
+                    // read not
+
+                    // check whether o or O
+                    int not = reader.read();
+                    if (not != 'o' && not != 'O') {
+                        logIllegalState("IfList-Not", not, "o", null);
+                        break;
+                    }
+
+                    // check whether t or T
+                    not = reader.read();
+                    if (not !='t' || not != 'T') {
+                        logIllegalState("IfList-Not", not, "t", null);
+                        break;
+                    }
+
+                    // read Not ok
+                    positive = false;
+                    break;
+
+                case '<':
+                    // state token
+                    word = readWord(reader, '>');
+                    if (word != null) {
+                        res.add(new IfListEntryToken(word, positive));
+                        // also add the token to the list of all tokens
+                        allTokens.add(word);
+                        positive = true;
+                    }
+                    break;
+
+                case '[':
+                    // etag
+                    word = readWord(reader, ']');
+                    if (word != null) {
+                        res.add(new IfListEntryEtag(word, positive));
+                        positive = true;
+                    }
+                    break;
+
+                case ')':
+                    // correct end of list, end the loop
+                    log.debug("parseIfList: End of If list, terminating loop");
+                    break ReadLoop;
+
+                default:
+                    logIllegalState("IfList", nextChar, "nN<[)", reader);
+
+                    // abort loop if EOF
+                    if (nextChar < 0) {
+                        break ReadLoop;
+                    }
+
+                    break;
+            }
+        }
+
+        // return the current list anyway
+        return res;
+    }
+
+    /**
+     * Returns the first non-whitespace character from the reader or -1 if
+     * the end of the reader is encountered.
+     *
+     * @param reader The <code>Reader</code> to read from
+     *
+     * @return The first non-whitespace character or -1 in case of EOF.
+     *
+     * @throws IOException if a problem occurrs during reading.
+     */
+    private int readWhiteSpace(Reader reader) throws IOException {
+        int c = reader.read();
+        while (c >= 0 && Character.isWhitespace((char) c)) {
+             c = reader.read();
+        }
+        return c;
+    }
+
+    /**
+     * Reads from the input until the end character is encountered and returns
+     * the string upto but not including this end character. If the end of input
+     * is reached before reading the end character <code>null</code> is
+     * returned.
+     * <p>
+     * Note that this method does not support any escaping.
+     *
+     * @param reader The <code>Reader</code> to read from
+     * @param end The ending character limitting the word.
+     *
+     * @return The string read upto but not including the ending character or
+     *      <code>null</code> if the end of input is reached before the ending
+     *      character has been read.
+     *
+     * @throws IOException if a problem occurrs during reading.
+     */
+    private String readWord(Reader reader, char end) throws IOException {
+        StringBuffer buf = new StringBuffer();
+
+        // read the word value
+        int c = reader.read();
+        for (; c >= 0 && c != end; c=reader.read()) {
+            buf.append((char) c);
+        }
+
+        // check whether we succeeded
+        if (c < 0) {
+            log.error("readWord: Unexpected end of input reading word");
+            return null;
+        }
+
+        // build the string and return it
+        return buf.toString();
+    }
+
+    /**
+     * Logs an unexpected character with the corresponding state and list of
+     * expected characters. If the reader parameter is not null, characters
+     * are read until either the end of the input is reached or any of the
+     * characters in the expChar string is read.
+     *
+     * @param state The name of the current parse state. This method logs this
+     *      name in the message. The intended value would probably be the
+     *      name of the EBNF production during which the error occurrs.
+     * @param effChar The effective character read.
+     * @param expChar The list of characters acceptable in the current state.
+     * @param reader The reader to be caught up to any of the expected
+     *      characters. If <code>null</code> the input is not caught up to
+     *      any of the expected characters (of course ;-).
+     */
+    private void logIllegalState(String state, int effChar, String expChar,
+                                 StringReader reader) {
+
+        // format the effective character to be logged
+        String effString = (effChar < 0) ? "<EOF>" : String.valueOf((char) effChar);
+
+        // log the error
+        log.error("logIllegalState: Unexpected character '"+effString+" in state "+state+", expected any of "+expChar);
+
+        // catch up if a reader is given
+        if (reader != null && effChar >= 0) {
+            try {
+                log.debug("logIllegalState: Catch up to any of "+expChar);
+                do {
+                    reader.mark(1);
+                    effChar = reader.read();
+                } while (effChar >= 0 && expChar.indexOf(effChar) < 0);
+                if (effChar >= 0) {
+                    reader.reset();
+                }
+            } catch (IOException ioe) {
+                log.error("logIllegalState: IO Problem catching up to any of "+expChar);
+            }
+        }
+    }
+
+    //---------- internal If header structure ----------------------------------
+
+    /**
+     * The <code>IfListEntry</code> abstract class is the base class for
+     * entries in an <em>IfList</em> production. This abstract base class
+     * provides common functionality to both types of entries, namely tokens
+     * enclosed in angle brackets (<code>&lt; &gt;</code>) and etags enclosed
+     * in square brackets (<code>[ ]</code>).
+     */
+    private static abstract class IfListEntry {
+
+        /**
+         * The entry string value - the semantics of this value depends on the
+         * implementing class.
+         */
+        protected final String value;
+
+        /** Flag to indicate, whether this is a positive match or not */
+        protected final boolean positive;
+
+        /** The cached result of the {@link #toString} method. */
+        protected String stringValue;
+
+        /**
+         * Sets up the final fields of this abstract class. The meaning of
+         * value parameter depends solely on the implementing class. From the
+         * point of view of this abstract class, it is simply a string value.
+         *
+         * @param value The string value of this instance
+         * @param positive <code>true</code> if matches are positive
+         */
+        protected IfListEntry(String value, boolean positive) {
+            this.value = value;
+            this.positive = positive;
+        }
+
+        /**
+         * Matches the value from the parameter to the internal string value.
+         * If the parameter and the {@link #value} field match, the method
+         * returns <code>true</code> for positive matches and <code>false</code>
+         * for negative matches.
+         * <p>
+         * This helper method can be called by implementations to evaluate the
+         * concrete match on the correct value parameter. See
+         * {@link #match(String, String)} for the external API method.
+         *
+         * @param value The string value to compare to the {@link #value}
+         *      field.
+         *
+         * @return <code>true</code> if the value parameter and the
+         *      {@link #value} field match and the {@link #positive} field is
+         *      <code>true</code> or if the values do not match and the
+         *      {@link #positive} field is <code>false</code>.
+         */
+        protected boolean match(String value) {
+            return positive == this.value.equals(value);
+        }
+
+        /**
+         * Matches the entry's value to the the token or etag. Depending on the
+         * concrete implementation, only one of the parameters may be evaluated
+         * while the other may be ignored.
+         * <p>
+         * Implementing METHODS may call the helper method {@link #match(String)}
+         * for the actual matching.
+         *
+         * @param token The token value to compare
+         * @param etag The etag value to compare
+         *
+         * @return <code>true</code> if the token/etag matches the <em>IfList</em>
+         *      entry.
+         */
+        public abstract boolean match(String token, String etag);
+
+        /**
+         * Returns a short type name for the implementation. This method is
+         * used by the {@link #toString} method to build the string representation
+         * if the instance.
+         *
+         * @return The type name of the implementation.
+         */
+        protected abstract String getType();
+
+	/**
+	 * Returns the value of this entry.
+	 *
+	 * @return the value
+	 */
+	protected String getValue() {
+	    return value;
+	}
+
+        /**
+         * Returns the String represenation of this entry. This method uses the
+         * {@link #getType} to build the string representation.
+         *
+         * @return the String represenation of this entry.
+         */
+        public String toString() {
+            if (stringValue == null) {
+                stringValue = getType() + ": " + (positive?"":"!") + value;
+            }
+            return stringValue;
+        }
+    }
+
+    /**
+     * The <code>IfListEntryToken</code> extends the {@link IfListEntry}
+     * abstract class to represent an entry for token matching.
+     */
+    private static class IfListEntryToken extends IfListEntry {
+
+        /**
+         * Creates a token matching entry.
+         *
+         * @param token The token value pertinent to this instance.
+         * @param positive <code>true</code> if this is a positive match entry.
+         */
+        IfListEntryToken(String token, boolean positive) {
+            super(token, positive);
+        }
+
+        /**
+         * Matches the token parameter to the stored token value and returns
+         * <code>true</code> if the values match and if the match is positive.
+         * <code>true</code> is also returned for negative matches if the values
+         * do not match.
+         *
+         * @param token The token value to compare
+         * @param etag The etag value to compare, which is ignored in this
+         *      implementation.
+         *
+         * @return <code>true</code> if the token matches the <em>IfList</em>
+         *      entry's token value.
+         */
+        public boolean match(String token, String etag) {
+            return super.match(token);
+        }
+
+        /**
+         * Returns the type name of this implementation, which is fixed to
+         * be <em>Token</em>.
+         *
+         * @return The fixed string <em>Token</em> as the type name.
+         */
+        protected String getType() {
+            return "Token";
+        }
+    }
+
+    /**
+     * The <code>IfListEntryToken</code> extends the {@link IfListEntry}
+     * abstract class to represent an entry for etag matching.
+     */
+    private static class IfListEntryEtag extends IfListEntry {
+
+        /**
+         * Creates an etag matching entry.
+         *
+         * @param etag The etag value pertinent to this instance.
+         * @param positive <code>true</code> if this is a positive match entry.
+         */
+        IfListEntryEtag(String etag, boolean positive) {
+            super(etag, positive);
+        }
+
+        /**
+         * Matches the etag parameter to the stored etag value and returns
+         * <code>true</code> if the values match and if the match is positive.
+         * <code>true</code> is also returned for negative matches if the values
+         * do not match.
+         *
+         * @param token The token value to compare, which is ignored in this
+         *      implementation.
+         * @param etag The etag value to compare
+         *
+         * @return <code>true</code> if the etag matches the <em>IfList</em>
+         *      entry's etag value.
+         */
+        public boolean match(String token, String etag) {
+            return super.match(etag);
+        }
+
+        /**
+         * Returns the type name of this implementation, which is fixed to
+         * be <em>ETag</em>.
+         *
+         * @return The fixed string <em>ETag</em> as the type name.
+         */
+        protected String getType() {
+            return "ETag";
+        }
+    }
+
+    /**
+     * The <code>IfList</code> class extends the <code>ArrayList</code> class
+     * with the limitation to only support adding {@link IfListEntry} objects
+     * and adding a {@link #match} method.
+     * <p>
+     * This class is a container for data contained in the <em>If</em>
+     * production <em>IfList</em>
+     * <pre>
+         IfList = { [ "Not" ] ( ("<" Word ">" ) | ( "[" Word "]" ) ) } .
+     * </pre>
+     * <p>
+     */
+    private static class IfList extends ArrayList {
+
+        /**
+         * Throws an <code>IllegalStateException</code> because only
+         * {@link IfListEntry} objects are supported in this list.
+         *
+         * @param o The <code>Object</code> to add.
+         * @return <code>true</code> if successfull
+         *
+         * @throws IllegalStateException because only {@link IfListEntry}
+         *      objects are supported in this list.
+         */
+        public boolean add(Object o) {
+            throw new IllegalArgumentException("Only IfListEntry instances allowed");
+        }
+
+        /**
+         * Throws an <code>IllegalStateException</code> because only
+         * {@link IfListEntry} objects are supported in this list.
+         *
+         * @param index The position at which to add the object.
+         * @param element The <code>Object</code> to add.
+         *
+         * @throws IllegalStateException because only {@link IfListEntry}
+         *      objects are supported in this list.
+         */
+        public void add(int index, Object element) {
+            throw new IllegalArgumentException("Only IfListEntry instances allowed");
+        }
+
+        /**
+         * Adds the {@link IfListEntry} at the end of the list.
+         *
+         * @param entry The {@link IfListEntry} to add to the list
+         *
+         * @return <code>true</code> (as per the general contract of
+         *      Collection.add).
+         */
+        public boolean add(IfListEntry entry) {
+            return super.add(entry);
+        }
+
+        /**
+         * Adds the {@link IfListEntry} at the indicated position of the list.
+         *
+         * @param index
+         * @param entry
+         *
+         * @throws IndexOutOfBoundsException if index is out of range
+         *      <code>(index &lt; 0 || index &gt; size())</code>.
+         */
+        public void add(int index, IfListEntry entry) {
+            super.add(index, entry);
+        }
+
+        /**
+         * Returns <code>true</code> if all {@link IfListEntry} objects in the
+         * list match the given token and etag. If the list is entry, it is
+         * considered to match the token and etag.
+         *
+         * @param token The token to compare.
+         * @param etag The etag to compare.
+         *
+         * @return <code>true</code> if all entries in the list matche the
+         *      given tag and token.
+         */
+        public boolean match(String token, String etag) {
+            log.debug("match: Trying to match token="+token+", etag="+etag);
+            for (int i=0; i < size(); i++) {
+                IfListEntry ile = (IfListEntry) get(i);
+                if (!ile.match(token, etag)) {
+                    log.debug("match: Entry "+String.valueOf(i)+"-"+ile+" does not match");
+                    return false;
+                }
+            }
+            // invariant: all entries matched
+
+            return true;
+        }
+    }
+
+    /**
+     * The <code>IfHeaderInterface</code> interface abstracts away the difference of
+     * tagged and untagged <em>If</em> header lists. The single method provided
+     * by this interface is to check whether a request may be applied to a
+     * resource with given token and etag.
+     */
+    private static interface IfHeaderInterface {
+
+        /**
+         * Matches the resource, token, and etag against this
+         * <code>IfHeaderInterface</code> instance.
+         *
+         * @param resource The resource to match this instance against. This
+         *      must be absolute URI of the resource as defined in Section 3
+         *      (URI Syntactic Components) of RFC 2396 Uniform Resource
+         *      Identifiers (URI): Generic Syntax.
+         * @param token The resource's lock token to match
+         * @param etag The resource's etag to match
+         *
+         * @return <code>true</code> if the header matches the resource with
+         *      token and etag, which means that the request is applicable
+         *      to the resource according to the <em>If</em> header.
+         */
+        public boolean matches(String resource, String token, String etag);
+    }
+
+    /**
+     * The <code>IfHeaderList</code> clss implements the {@link IfHeaderInterface}
+     * interface to support untagged lists of {@link IfList}s. This class
+     * implements the data container for the production :
+     * <pre>
+         Untagged = { "(" IfList ")" } .
+     * </pre>
+     */
+    private static class IfHeaderList extends ArrayList implements IfHeaderInterface {
+
+        /**
+         * Matches a list of {@link IfList}s against the token and etag. If any of
+         * the {@link IfList}s matches, the method returns <code>true</code>.
+         * On the other hand <code>false</code> is only returned if non of the
+         * {@link IfList}s match.
+         *
+         * @param resource The resource to match, which is ignored by this
+         *      implementation. A value of <code>null</code> is therefor
+         *      acceptable.
+         * @param token The token to compare.
+         * @param etag The ETag value to compare.
+         *
+         * @return <code>True</code> if any of the {@link IfList}s matches the token
+         *      and etag, else <code>false</code> is returned.
+         */
+        public boolean matches(String resource, String token, String etag) {
+            log.debug("matches: Trying to match token="+token+", etag="+etag);
+
+            for (int i=0; i < size(); i++) {
+                IfList il = (IfList) get(i);
+                if (il.match(token, etag)) {
+                    log.debug("matches: Found match with "+il);
+                    return true;
+                }
+            }
+            // invariant: no match found
+
+            return false;
+        }
+    }
+
+    /**
+     * The <code>IfHeaderMap</code> clss implements the {@link IfHeaderInterface}
+     * interface to support tagged lists of {@link IfList}s. This class
+     * implements the data container for the production :
+     * <pre>
+         Tagged = { "<" Word ">" "(" IfList ")" } .
+     * </pre>
+     */
+    private static class IfHeaderMap extends HashMap implements IfHeaderInterface {
+
+        /**
+         * Matches the token and etag for the given resource. If the resource is
+         * not mentioned in the header, a match is assumed and <code>true</code>
+         * is returned in this case.
+         *
+         * @param resource The absolute URI of the resource for which to find
+         *      a match.
+         * @param token The token to compare.
+         * @param etag The etag to compare.
+         *
+         * @return <code>true</code> if either no entry exists for the resource
+         *      or if the entry for the resource matches the token and etag.
+         */
+        public boolean matches(String resource, String token, String etag) {
+            log.debug("matches: Trying to match resource="+resource+", token="+token+","+etag);
+
+            IfHeaderList list = (IfHeaderList) get(resource);
+            if (list == null) {
+                log.debug("matches: No entry for tag "+resource+", assuming match");
+                return true;
+            } else {
+                return list.matches(resource, token, etag);
+            }
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/IfHeader.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/IfHeader.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatus.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatus.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatus.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatus.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,110 @@
+/*
+ * 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.jackrabbit.webdav;
+
+import org.jdom.Document;
+import org.jdom.Element;
+import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * MultiStatus representing the content of a multistatus response body and
+ * allows to retrieve the Xml representation.
+ */
+public class MultiStatus {
+
+    private ArrayList responses = new ArrayList();
+
+    /**
+     * Add response(s) to this multistatus, in order to build a multistatus for
+     * responding to a PROPFIND request.
+     *
+     * @param resource The resource to add property from
+     * @param propNameSet The requested property names of the PROPFIND request
+     * @param propFindType
+     * @param depth
+     */
+    public void addResourceProperties(DavResource resource, DavPropertyNameSet propNameSet,
+				      int propFindType, int depth) {
+	addResponse(new MultiStatusResponse(resource, propNameSet, propFindType));
+	if (depth > 0) {
+	    DavResourceIterator iter = resource.getMembers();
+	    while (iter.hasNext()) {
+		addResourceProperties(iter.nextResource(), propNameSet, propFindType, depth-1);
+	    }
+	}
+    }
+
+    /**
+     * Add response(s) to this multistatus, in order to build a multistatus e.g.
+     * in order to respond to a PROPFIND request. Please note, that in terms
+     * of PROPFIND, this method would correspond to a
+     * {@link DavConstants#PROPFIND_BY_PROPERTY} propfind type.
+     *
+     * @param resource The resource to add property from
+     * @param propNameSet The requested property names of the PROPFIND request
+     * @param depth
+     * @see #addResourceProperties(DavResource, DavPropertyNameSet, int, int) for
+     * the corresponding method that allows to specify the type explicitely.
+     */
+    public void addResourceProperties(DavResource resource, DavPropertyNameSet propNameSet,
+				      int depth) {
+	addResourceProperties(resource, propNameSet, DavConstants.PROPFIND_BY_PROPERTY, depth);
+    }
+
+    /**
+     * Add response(s) to this multistatus, in order to build a multistatus
+     * as returned for failed COPY, MOVE, LOCK or DELETE requests
+     *
+     * @param resource
+     * @param status
+     * @param depth
+     */
+    public void addResourceStatus(DavResource resource, int status, int depth) {
+	addResponse(new MultiStatusResponse(resource.getHref(), status));
+	if (depth > 0) {
+	    DavResourceIterator iter = resource.getMembers();
+	    while (iter.hasNext()) {
+		addResourceStatus(iter.nextResource(), status, depth-1);
+	    }
+	}
+    }
+
+    /**
+     * Add a <code>MultiStatusResponse</code> element to this <code>MultiStatus</code>
+     *
+     * @param response
+     */
+    public void addResponse(MultiStatusResponse response) {
+	responses.add(response);
+    }
+
+    /**
+     * Return the Xml representation of this <code>MultiStatus</code>.
+     *
+     * @return Xml document
+     */
+    public Document toXml() {
+	Element multistatus = new Element(DavConstants.XML_MULTISTATUS, DavConstants.NAMESPACE);
+        Iterator it = responses.iterator();
+	while(it.hasNext()) {
+	    multistatus.addContent(((MultiStatusResponse)it.next()).toXml());
+	}
+	return new Document(multistatus);
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatus.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatus.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,246 @@
+/*
+ * 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.jackrabbit.webdav;
+
+import org.jdom.Element;
+import org.apache.jackrabbit.webdav.property.*;
+import org.apache.jackrabbit.webdav.util.XmlUtil;
+
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * The <code>WebdavMultistatusResponse</code> class implements a structure that
+ * hold a WebDAV multistatus response. Properties can be added to this response
+ * with the respective error/status code.
+ */
+public class MultiStatusResponse implements DavConstants {
+
+    /**
+     * The content the 'href' element for this resposne
+     */
+    private final String href;
+
+    /**
+     * The '200' set (since this is used very often)
+     */
+    private final Element status200;
+
+    /**
+     * The '404' set (since this is used very often)
+     */
+    private final Element status404;
+
+    /**
+     * Hashmap with all stati
+     */
+    private final HashMap stati = new HashMap();
+
+    /**
+     * An optional response description.
+     */
+    private String responseDescription;
+
+    /**
+     * Constructs an empty WebDAV multistatus response
+     */
+    public MultiStatusResponse(String href) {
+        this.href = href;
+        status200 = new Element(XML_PROP, NAMESPACE);
+        status404 = new Element(XML_PROP, NAMESPACE);
+        stati.put(new Integer(DavServletResponse.SC_OK), status200);
+        stati.put(new Integer(DavServletResponse.SC_NOT_FOUND), status404);
+    }
+
+    /**
+     * Constucts a WebDAV multistatus response and retrieves the resource properties
+     * according to the given <code>DavPropertyNameSet</code>.
+     *
+     * @param resource
+     * @param propNameSet
+     */
+    public MultiStatusResponse(DavResource resource, DavPropertyNameSet propNameSet) {
+        this(resource, propNameSet, PROPFIND_BY_PROPERTY);
+    }
+
+    /**
+     * Constucts a WebDAV multistatus response and retrieves the resource properties
+     * according to the given <code>DavPropertyNameSet</code>. It adds all known
+     * property to the '200' set, while unknown properties are added to the '404' set.
+     * <p/>
+     * Note, that the set of property names is ignored in case of a {@link #PROPFIND_ALL_PROP}
+     * and {@link #PROPFIND_PROPERTY_NAMES} propFindType.
+     *
+     * @param resource The resource to retrieve the property from
+     * @param propNameSet The property name set as obtained from the request body.
+     * @param propFindType any of the following values: {@link #PROPFIND_ALL_PROP},
+     * {@link #PROPFIND_BY_PROPERTY}, {@link #PROPFIND_PROPERTY_NAMES}
+     */
+    public MultiStatusResponse(DavResource resource, DavPropertyNameSet propNameSet,
+			       int propFindType) {
+        this(resource.getHref());
+
+	// only property names requested
+	if (propFindType == PROPFIND_PROPERTY_NAMES) {
+	    DavPropertyName[] propNames = resource.getPropertyNames();
+	    for (int i = 0; i < propNames.length; i++) {
+		status200.addContent(propNames[i].toXml());
+	    }
+	// all or a specified set of property and their values requested.
+	} else {
+	    // clone set of property, since several resources could use this again
+	    propNameSet = new DavPropertyNameSet(propNameSet);
+	    // Add requested properties or all non-protected properties
+	    DavPropertyIterator iter = resource.getProperties().iterator();
+	    while (iter.hasNext()) {
+		DavProperty wdp = iter.nextProperty();
+		if ((propFindType == PROPFIND_ALL_PROP && !wdp.isProtected()) || propNameSet.remove(wdp.getName())) {
+		    status200.addContent(wdp.toXml());
+		}
+	    }
+
+	    if (propFindType != PROPFIND_ALL_PROP) {
+		Iterator iter1 = propNameSet.iterator();
+		while (iter1.hasNext()) {
+		    DavPropertyName propName = (DavPropertyName) iter1.next();
+		    status404.addContent(propName.toXml());
+		}
+	    }
+	}
+    }
+
+   /**
+    * Constructs an WebDAV multistatus response for a given resource. This
+    * would be used by COPY, MOVE, DELETE, LOCK, UNLOCK that require a multistatus
+    * in case of failure.
+    */
+    public MultiStatusResponse(String href, int status) {
+        this(href);
+        stati.put(new Integer(status), new Element(null));
+    }
+
+    /**
+     * Adds a JDOM element to this response
+     *
+     * @param prop the property to add
+     * @param status the status of the response set to select
+     */
+    private void add(Element prop, int status) {
+        Integer statusKey = new Integer(status);
+        Element propsContainer = (Element) stati.get(statusKey);
+        if (propsContainer == null) {
+            propsContainer = new Element(XML_PROP, NAMESPACE);
+            stati.put(statusKey, propsContainer);
+        }
+        propsContainer.addContent(prop);
+    }
+
+    /**
+     * Adds a property to this response '200' propstat set.
+     *
+     * @param prop the property to add
+     */
+    public void add(DavProperty prop) {
+        status200.addContent(prop.toXml());
+    }
+
+    /**
+     * Adds a property name to this response '200' propstat set.
+     *
+     * @param name the property name to add
+     */
+    public void add(DavPropertyName name) {
+        status200.addContent(name.toXml());
+    }
+
+    /**
+     * Adds a property to this response
+     *
+     * @param prop the property to add
+     * @param status the status of the response set to select
+     */
+    public void add(DavProperty prop, int status) {
+        add(prop.toXml(), status);
+    }
+
+    /**
+     * Adds a property name to this response
+     *
+     * @param name the property name to add
+     * @param status the status of the response set to select
+     */
+    public void add(DavPropertyName name, int status) {
+        add(name.toXml(), status);
+    }
+
+    /**
+     * Set the content of the optional response description element, which is
+     * intended to contain a message that can be displayed to the user
+     * explaining the nature of this response.
+     *
+     * @param responseDescription
+     */
+    public void setResponseDescription(String responseDescription) {
+        this.responseDescription = responseDescription;
+    }
+
+    /**
+     * Creates the JDOM element for this reponse.
+     *
+     * @return A JDOM element of this response
+     */
+    public Element toXml() {
+        // don't create empty 'href' responses
+        if ("".equals(href)) {
+            return null;
+        }
+
+        Element response= new Element(XML_RESPONSE, NAMESPACE);
+
+        // add '<href>'
+        response.addContent(XmlUtil.hrefToXml(href));
+
+        // add '<propstat>' elements or a single '<status>' element
+        Iterator iter = stati.keySet().iterator();
+        while (iter.hasNext()) {
+            Integer statusKey = (Integer) iter.next();
+	    Element prop = (Element) stati.get(statusKey);
+            if (prop != null) {
+                Element status = new Element(XML_STATUS, NAMESPACE);
+                status.setText("HTTP/1.1 " + statusKey + " " + DavException.getStatusPhrase(statusKey.intValue()));
+
+                if (XML_PROP.equals(prop.getName())) {
+                    // do not add empty propstat elements
+                    if (prop.getContentSize() > 0) {
+                        Element propstat = new Element(XML_PROPSTAT, NAMESPACE);
+                        propstat.addContent(prop);
+                        propstat.addContent(status);
+                        response.addContent(propstat);
+                    }
+                } else {
+                    response.addContent(status);
+                }
+	    }
+        }
+        // add the optional '<responsedescription>' element
+        if (responseDescription != null) {
+            Element desc = new Element(XML_RESPONSEDESCRIPTION, NAMESPACE);
+            desc.setText(responseDescription);
+            response.addContent(desc);
+        }
+        return response;
+    }
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/MultiStatusResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequest.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequest.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequest.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,33 @@
+/*
+ * 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.jackrabbit.webdav;
+
+import org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest;
+import org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest;
+import org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest;
+import org.apache.jackrabbit.webdav.version.DeltaVServletRequest;
+
+/**
+ * The empty <code>WebdavRequest</code> interface collects the functionality
+ * defined by {@link org.apache.jackrabbit.webdav.DavServletRequest} encapsulting
+ * the core Webdav specification (RFC 2518) as well as the various extensions
+ * used for observation and transaction support, ordering of collections, search
+ * and versioning.
+ */
+public interface WebdavRequest extends DavServletRequest,
+        ObservationDavServletRequest, OrderingDavServletRequest,
+        TransactionDavServletRequest, DeltaVServletRequest {
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequest.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,932 @@
+/*
+ * 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.jackrabbit.webdav;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.webdav.util.Text;
+import org.apache.jackrabbit.webdav.lock.LockInfo;
+import org.apache.jackrabbit.webdav.lock.Type;
+import org.apache.jackrabbit.webdav.lock.Scope;
+import org.apache.jackrabbit.webdav.property.*;
+import org.apache.jackrabbit.webdav.transaction.*;
+import org.apache.jackrabbit.webdav.observation.*;
+import org.apache.jackrabbit.webdav.version.*;
+import org.apache.jackrabbit.webdav.version.report.ReportInfo;
+import org.apache.jackrabbit.webdav.ordering.*;
+import org.jdom.input.SAXBuilder;
+import org.jdom.JDOMException;
+import org.jdom.Document;
+import org.jdom.Element;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpSession;
+import javax.servlet.ServletInputStream;
+import javax.servlet.RequestDispatcher;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.io.BufferedReader;
+import java.util.*;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.Principal;
+
+/**
+ * <code>WebdavRequestImpl</code>...
+ */
+public class WebdavRequestImpl implements WebdavRequest {
+
+    private static Logger log = Logger.getLogger(WebdavRequestImpl.class);
+
+    private final HttpServletRequest httpRequest;
+    private final DavLocatorFactory factory;
+    private final IfHeader ifHeader;
+    private final String hrefPrefix;
+
+    private DavSession session;
+
+    private int propfindType = DavConstants.PROPFIND_ALL_PROP;
+    private DavPropertyNameSet propfindProps;
+    private DavPropertySet proppatchSet;
+    private DavPropertyNameSet proppatchRemove;
+
+    /**
+     * Creates a new <code>DavServletRequest</code> with the given parameters.
+     *
+     * @param httpRequest
+     * @param factory
+     */
+    public WebdavRequestImpl(HttpServletRequest httpRequest, DavLocatorFactory factory) {
+        this.httpRequest = httpRequest;
+        this.factory = factory;
+        this.ifHeader = new IfHeader(httpRequest);
+
+        String host = getHeader("Host");
+	String scheme = getScheme();
+	hrefPrefix = scheme + "://" + host + getContextPath();
+    }
+
+    /**
+     * Sets the session field and adds all lock tokens present with either the
+     * Lock-Token header or the If header to the given session object.
+     *
+     * @param session
+     * @see DavServletRequest#setDavSession(DavSession)
+     */
+    public void setDavSession(DavSession session) {
+        this.session = session;
+        // set lock-tokens from header to the current session
+        if (session != null && session.getRepositorySession() != null) {
+            String lt = getLockToken();
+            if (lt != null) {
+                session.addLockToken(lt);
+            }
+            // add all token present in the the If header to the session as well.
+            Iterator it = ifHeader.getAllTokens();
+            while (it.hasNext()) {
+                String ifHeaderToken = (String)it.next();
+                session.addLockToken(ifHeaderToken);
+            }
+        }
+    }
+
+    /**
+     * @see DavServletRequest#getDavSession()
+     */
+    public DavSession getDavSession() {
+        return session;
+    }
+
+    /**
+     * Return a <code>DavResourceLocator</code> representing the request handle.
+     *
+     * @return locator of the requested resource
+     * @see DavServletRequest#getRequestLocator()
+     */
+    public DavResourceLocator getRequestLocator() {
+        String path = getPathInfo();
+        if (path == null) {
+            path = getServletPath();
+        }
+        return factory.createResourceLocator(hrefPrefix, path);
+    }
+
+    /**
+     * Parse the destination header field and return the path of the destination
+     * resource.
+     *
+     * @return path of the destination resource.
+     * @see DavConstants#HEADER_DESTINATION
+     * @see DavServletRequest#getDestinationLocator
+     */
+    public DavResourceLocator getDestinationLocator() {
+        String destination = httpRequest.getHeader(DavConstants.HEADER_DESTINATION);
+        if (destination != null) {
+	    try {
+		URI uri = new URI(destination);
+		if (uri.getAuthority().equals(httpRequest.getHeader("Host"))) {
+		    destination = Text.unescape(uri.getPath());
+		}
+	    } catch (URISyntaxException e) {
+		log.debug("Destination is path is not a valid URI ("+e.getMessage()+".");
+		int pos = destination.lastIndexOf(":");
+		if (pos > 0) {
+		    destination = destination.substring(destination.indexOf("/",pos));
+		    log.debug("Tried to retrieve resource destination path from invalid URI: "+destination);
+		}
+	    }
+
+	    // cut off the context path
+	    String contextPath = httpRequest.getContextPath();
+	    if (destination.startsWith(contextPath)) {
+		destination = destination.substring(contextPath.length());
+	    }
+	}
+	return factory.createResourceLocator(hrefPrefix, destination);
+    }
+
+    /**
+     * Return true if the overwrite header does not inhibit overwriting.
+     *
+     * @return true if the overwrite header requests 'overwriting'
+     * @see DavConstants#HEADER_OVERWRITE
+     * @see DavServletRequest#isOverwrite()
+     */
+    public boolean isOverwrite() {
+	boolean doOverwrite = true;
+	String overwriteHeader = httpRequest.getHeader(DavConstants.HEADER_OVERWRITE);
+	if (overwriteHeader != null && !overwriteHeader.equalsIgnoreCase(DavConstants.NO_OVERWRITE)){
+	    doOverwrite = false;
+	}
+	return doOverwrite;
+    }
+
+    /**
+     * @see DavServletRequest#getDepth(int)
+     */
+    public int getDepth(int defaultValue) {
+	String dHeader = httpRequest.getHeader(DavConstants.HEADER_DEPTH);
+	int depth = depthToInt(dHeader, defaultValue);
+	return depth;
+    }
+
+    /**
+     * @see DavServletRequest#getDepth()
+     */
+    public int getDepth() {
+        return getDepth(DavConstants.DEPTH_INFINITY);
+    }
+
+    /**
+     * Parse the request timeout header and convert the timeout value
+     * into a long indicating the number of milliseconds until expiration time
+     * is reached.<br>
+     * NOTE: If the requested timeout is 'infinite' {@link Long.MAX_VALUE}
+     * is returned.
+     *
+     * @return milliseconds the lock is requested to live.
+     * @see DavServletRequest#getTimeout()
+     */
+    public long getTimeout() {
+	String timeoutStr = httpRequest.getHeader(DavConstants.HEADER_TIMEOUT);
+	long timeout = DavConstants.UNDEFINED_TIMEOUT;
+	if (timeoutStr != null && timeoutStr.length() > 0) {
+	    int secondsInd = timeoutStr.indexOf("Second-");
+	    if (secondsInd >= 0) {
+		secondsInd += 7; // read over "Second-"
+		int i = secondsInd;
+                while (i < timeoutStr.length() && Character.isDigit(timeoutStr.charAt(i))) {
+                    i++;
+                }
+		try {
+		    timeout = 1000L * Long.parseLong(timeoutStr.substring(secondsInd, i));
+		} catch (NumberFormatException ignore) {
+		    // ignore an let the lock define the default timeout
+                    log.error("Invalid timeout format: "+timeoutStr);
+		}
+	    } else if (timeoutStr.equalsIgnoreCase(DavConstants.TIMEOUT_INFINITE)) {
+		timeout = DavConstants.INFINITE_TIMEOUT;
+	    }
+	}
+	return timeout;
+    }
+
+    /**
+     * Retrive the lock token from the 'Lock-Token' header.
+     *
+     * @return String representing the lock token sent in the Lock-Token header.
+     * @throws IllegalArgumentException If the value has not the correct format.
+     * @see DavConstants#HEADER_LOCK_TOKEN
+     * @see DavServletRequest#getLockToken()
+     */
+    public String getLockToken() {
+	return getCodedURLHeader(DavConstants.HEADER_LOCK_TOKEN);
+    }
+
+    /**
+     * @return Xml document
+     * @see DavServletRequest#getRequestDocument()
+     */
+    public Document getRequestDocument() {
+        Document requestDocument = null;
+        // try to parse the request body
+        try {
+            SAXBuilder builder = new SAXBuilder(false);
+            InputStream in = httpRequest.getInputStream();
+            if (in != null) {
+                requestDocument = builder.build(in);
+            }
+        } catch (IOException e) {
+            log.warn("Error while reading the request body: " + e.getMessage());
+        } catch (JDOMException e) {
+            log.warn("Error while building xml document from request body: " + e.getMessage());
+        }
+        return requestDocument;
+    }
+
+    /**
+     * Returns the type of PROPFIND as indicated by the request body.
+     *
+     * @return type of the PROPFIND request. Default value is
+     * {@link DavConstants#PROPFIND_ALL_PROP allprops}
+     * @see DavServletRequest#getPropFindType()
+     */
+    public int getPropFindType() {
+        if (propfindProps == null) {
+            parsePropFindRequest();
+        }
+        return propfindType;
+    }
+
+    /**
+     * Returns the set of properties requested by the PROPFIND body or an
+     * empty set if the {@link #getPropFindType type} is either 'allprop' or
+     * 'propname'.
+     *
+     * @return set of properties requested by the PROPFIND body or an empty set.
+     * @see DavServletRequest#getPropFindProperties()
+     */
+    public DavPropertyNameSet getPropFindProperties() {
+        if (propfindProps == null) {
+            parsePropFindRequest();
+        }
+        return propfindProps;
+    }
+
+    /**
+     * Parse the propfind request body in order to determine the type of the propfind
+     * and the set of requested property.
+     * NOTE: An empty 'propfind' request body will be treated as request for all
+     * property according to the specification.
+     */
+    private void parsePropFindRequest() {
+
+        propfindProps = new DavPropertyNameSet();
+        Document requestDocument = getRequestDocument();
+
+	// propfind httpRequest with empty body or invalid Xml >> retrieve all property
+	// TODO: spec requires a 'BAD REQUEST' error code
+	if (requestDocument == null) {
+	    return;
+	}
+
+	// propfind httpRequest with invalid body >> treat as if empty body
+	Element root = requestDocument.getRootElement();
+	if (!root.getName().equals(DavConstants.XML_PROPFIND)) {
+	    log.info("PropFind-Request has no <profind> tag.");
+	    return;
+	}
+
+	List childList = root.getChildren();
+	for (int i = 0; i < childList.size(); i++) {
+	    Element child = (Element) childList.get(i);
+	    String nodeName = child.getName();
+	    if (DavConstants.XML_PROP.equals(nodeName)) {
+		propfindType = DavConstants.PROPFIND_BY_PROPERTY;
+		propfindProps = new DavPropertyNameSet(child);
+                break;
+	    } else if (DavConstants.XML_PROPNAME.equals(nodeName)) {
+		propfindType = DavConstants.PROPFIND_PROPERTY_NAMES;
+                break;
+	    } else if (DavConstants.XML_ALLPROP.equals(nodeName)) {
+		propfindType = DavConstants.PROPFIND_ALL_PROP;
+                break;
+	    }
+	}
+    }
+
+    /**
+     * Return the list of 'set' entries in the PROPPATCH request body. The list
+     * is empty if the request body could not be parsed or if the request body did
+     * not contain any 'set' elements.
+     *
+     * @return the list of 'set' entries in the PROPPATCH request body
+     * @see DavServletRequest#getPropPatchSetProperties()
+     */
+    public DavPropertySet getPropPatchSetProperties() {
+        if (proppatchSet == null) {
+            parsePropPatchRequest();
+        }
+        return proppatchSet;
+    }
+
+    /**
+     * Return the list of 'remove' entries in the PROPPATCH request body. The list
+     * is empty if the request body could not be parsed or if the request body did
+     * not contain any 'remove' elements.
+     *
+     * @return the list of 'remove' entries in the PROPPATCH request body
+     * @see DavServletRequest#getPropPatchRemoveProperties()
+     */
+    public DavPropertyNameSet getPropPatchRemoveProperties() {
+        if (proppatchRemove == null) {
+            parsePropPatchRequest();
+        }
+        return proppatchRemove;
+    }
+
+    /**
+     * Parse the PROPPATCH request body.
+     */
+    private void parsePropPatchRequest() {
+
+        proppatchSet = new DavPropertySet();
+        proppatchRemove = new DavPropertyNameSet();
+        Document requestDocument = getRequestDocument();
+
+        if (requestDocument == null) {
+            return;
+        }
+
+        Element root = requestDocument.getRootElement();
+        if (!root.getName().equals(DavConstants.XML_PROPERTYUPDATE)) {
+            // we should also check for correct namespace
+            log.warn("PropPatch-Request has no <propertyupdate> tag.");
+            return;
+        }
+
+        List setList = root.getChildren(DavConstants.XML_SET, DavConstants.NAMESPACE);
+        if (!setList.isEmpty()) {
+            Iterator setIter = setList.iterator();
+            while (setIter.hasNext()) {
+                Element propElem = ((Element) setIter.next()).getChild(DavConstants.XML_PROP, DavConstants.NAMESPACE);
+                List properties = propElem.getChildren();
+                for (int i = 0; i < properties.size(); i++) {
+                    Element property = (Element) properties.get(i);
+                    proppatchSet.add(new DefaultDavProperty(property.getName(), property.getContent(), property.getNamespace()));
+                }
+            }
+        }
+
+        // get <remove> properties
+        List removeList = root.getChildren(DavConstants.XML_REMOVE, DavConstants.NAMESPACE);
+        if (!removeList.isEmpty()) {
+            Iterator removeIter = removeList.iterator();
+            while (removeIter.hasNext()) {
+                Element propElem = ((Element) removeIter.next()).getChild(DavConstants.XML_PROP, DavConstants.NAMESPACE);
+                Iterator propIter = propElem.getChildren().iterator();
+                while (propIter.hasNext()) {
+                    Element property = (Element) propIter.next();
+                    proppatchRemove.add(DavPropertyName.create(property.getName(), property.getNamespace()));
+                }
+            }
+        }
+    }
+
+    /**
+     * {@link LockInfo} object encapsulating the information passed with a LOCK
+     * request if the LOCK request body was valid. If the request body is
+     * missing a 'refresh lock' request is assumed. The {@link LockInfo}
+     * then only provides timeout and isDeep property and returns true on
+     * {@link org.apache.jackrabbit.webdav.lock.LockInfo#isRefreshLock()}
+     *
+     * @return lock info object or <code>null</code> if an error occured while
+     * parsing the request body.
+     * @see DavServletRequest#getLockInfo()
+     */
+    public LockInfo getLockInfo() {
+        LockInfo lockInfo = null;
+        boolean isDeep = getDepth(DavConstants.DEPTH_INFINITY) == DavConstants.DEPTH_INFINITY;
+	Document requestDocument = getRequestDocument();
+        // check if XML request body is present. It SHOULD have one for
+	// 'create Lock' request and missing for a 'refresh Lock' request
+	if (requestDocument != null) {
+	    Element root = requestDocument.getRootElement();
+	    if (root.getName().equals(DavConstants.XML_LOCKINFO)) {
+                lockInfo = new LockInfo(root, getTimeout(), isDeep);
+	    } else {
+		log.debug("Lock-Request has no <lockinfo> tag.");
+	    }
+	} else {
+            lockInfo = new LockInfo(null, getTimeout(), isDeep);
+        }
+        return lockInfo;
+    }
+
+    /**
+     * MTest if the if header matches the given resource. The comparison is
+     * made with the {@link DavResource#getHref()
+     * resource href} and the token returned from an exclusive write lock present on
+     * the resource. An empty strong ETag is currently assumed.<br>
+     * NOTE: If either the If header or the resource is <code>null</code> or if
+     * the resource has not applied an exclusive write lock the preconditions are met.
+     * If in contrast the lock applied to the given resource returns a
+     * <code>null</code> lock token (e.g. for security reasons) or a lock token
+     * that does not match, the method will return false.
+     *
+     * @param resource Webdav resources being operated on
+     * @return true if the test is successful and the preconditions for the
+     * request processing are fulfilled.
+     * @param resource
+     * @return
+     * @see DavServletRequest#matchesIfHeader(DavResource)
+     * @see IfHeader#matches(String, String, String)
+     * @see DavResource#hasLock(org.apache.jackrabbit.webdav.lock.Type, org.apache.jackrabbit.webdav.lock.Scope)
+     * @see org.apache.jackrabbit.webdav.lock.ActiveLock#getToken()
+     */
+    public boolean matchesIfHeader(DavResource resource) {
+        // no ifheader, no resource or no write lock on resource
+        // >> preconditions ok so far
+        if (ifHeader == null || resource == null || !resource.hasLock(Type.WRITE, Scope.EXCLUSIVE)) {
+            return true;
+        }
+
+        boolean isMatching = false;
+        String lockToken = resource.getLock(Type.WRITE, Scope.EXCLUSIVE).getToken();
+        if (lockToken != null) {
+            // TODO: strongETag is missing
+            isMatching = matchesIfHeader(resource.getHref(), lockToken, "");
+        } // else: lockToken is null >> the if-header will not match.
+
+        return isMatching;
+    }
+
+    /**
+     * @see DavServletRequest#matchesIfHeader(String, String, String)
+     * @see IfHeader#matches(String, String, String)
+     */
+    public boolean matchesIfHeader(String href, String token, String eTag) {
+        return ifHeader.matches(href, token, eTag);
+    }
+
+    /**
+     * Retrieve the header with the given header name and parse the CodedURL
+     * value included.
+     *
+     * @param headerName
+     * @return token present in the CodedURL header or <code>null</code> if
+     * the header is not present.
+     */
+    private String getCodedURLHeader(String headerName) {
+        String headerValue = null;
+	String header = httpRequest.getHeader(headerName);
+	if (header != null) {
+	    int p1 = header.indexOf('<');
+	    if (p1<0) {
+		throw new IllegalArgumentException("Invalid CodedURL header value:"+header);
+	    }
+	    int p2 = header.indexOf('>', p1);
+	    if (p2<0) {
+		throw new IllegalArgumentException("Invalid CodedURL header value:"+header);
+	    }
+	    headerValue = header.substring(p1+1, p2);
+	}
+	return headerValue;
+    }
+
+    /**
+     * Convert the String depth value to an integer.
+     *
+     * @param depth
+     * @param defaultValue
+     * @return integer representation of the given depth String or the given
+     * defaultValue if depth is <code>null</code> or invalid.
+     */
+    private static int depthToInt(String depth, int defaultValue) {
+        int d = defaultValue;
+        if (depth != null) {
+            if (depth.equalsIgnoreCase("infinity")) {
+                d = DavConstants.DEPTH_INFINITY;
+            } else if (depth.equals("0")) {
+                d = DavConstants.DEPTH_0;
+            } else if (depth.equals("1")) {
+                d = DavConstants.DEPTH_1;
+            }
+        }
+        return d;
+    }
+
+        //-----------------------------< TransactionDavServletRequest Interface >---
+    /**
+     *
+     * @return
+     * @see org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest#getTransactionId()
+     */
+    public String getTransactionId() {
+        return getCodedURLHeader(TransactionConstants.HEADER_TRANSACTIONID);
+    }
+
+    /**
+     *
+     * @return
+     * @see org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest#getTransactionInfo()
+     */
+    public TransactionInfo getTransactionInfo() {
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            try {
+                return new TransactionInfo(requestDocument.getRootElement());
+            } catch (IllegalArgumentException e) {
+                log.error(e.getMessage());
+            }
+        }
+        return null;
+    }
+
+    //-----------------------------< ObservationDavServletRequest Interface >---
+    /**
+     *
+     * @return
+     * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getSubscriptionId()
+     */
+    public String getSubscriptionId() {
+        return getCodedURLHeader(ObservationConstants.HEADER_SUBSCRIPTIONID);
+    }
+
+    /**
+     *
+     * @return
+     * @see org.apache.jackrabbit.webdav.observation.ObservationDavServletRequest#getSubscriptionInfo()
+     */
+    public SubscriptionInfo getSubscriptionInfo() {
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            Element root = requestDocument.getRootElement();
+            if (ObservationConstants.XML_SUBSCRIPTIONINFO.equals(root.getName())) {
+                int depth = getDepth(DavConstants.DEPTH_0);
+                return new SubscriptionInfo(root, getTimeout(), depth == DavConstants.DEPTH_INFINITY);
+            }
+        }
+        return null;
+    }
+
+    //--------------------------------< OrderingDavServletRequest Interface >---
+    /**
+     *
+     * @return
+     * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getOrderingType()
+     */
+    public String getOrderingType() {
+        return getHeader(OrderingConstants.HEADER_ORDERING_TYPE);
+    }
+
+    /**
+     *
+     * @return
+     * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getPosition()
+     */
+    public Position getPosition() {
+        String h = getHeader(OrderingConstants.HEADER_POSITION);
+        Position pos = null;
+        if (h != null) {
+            String[] typeNSegment = h.split("\\s");
+            if (typeNSegment.length == 2) {
+                try {
+                    pos = new Position(typeNSegment[0], typeNSegment[1]);
+                } catch (IllegalArgumentException e) {
+                    log.error("Cannot parse Position header: "+e.getMessage());
+                }
+            }
+        }
+        return pos;
+    }
+
+    /**
+     *
+     * @return <code>OrderPatch</code> object representing the orderpatch request
+     * body or <code>null</code> if the
+     * @see org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest#getOrderPatch()
+     */
+    public OrderPatch getOrderPatch() {
+        OrderPatch op = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            Element root = requestDocument.getRootElement();
+            if (!OrderingConstants.XML_ORDERPATCH.equals(root.getName()) ||
+                    root.getChild(OrderingConstants.XML_ORDERING_TYPE) == null) {
+                log.error("ORDERPATH request body must start with an 'orderpatch' element, which must contain an 'ordering-type' child element.");
+                return op;
+            }
+
+            try {
+                op = new OrderPatch(root);
+            } catch (IllegalArgumentException e) {
+                log.error(e.getMessage());
+            }
+        } else {
+            log.error("Error while building xml document from ORDERPATH request body.");
+        }
+        return op;
+    }
+
+    //-------------------------------------< DeltaVServletRequest interface >---
+    /**
+     * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabel()
+     */
+    public String getLabel() {
+        String label = getHeader(DeltaVConstants.HEADER_LABEL);
+        if (label != null) {
+            label = Text.unescape(label);
+        }
+        return label;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getLabelInfo()
+     */
+    public LabelInfo getLabelInfo() {
+        LabelInfo lInfo = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            Element root = requestDocument.getRootElement();
+            int depth = getDepth(DavConstants.DEPTH_0);
+            try {
+               lInfo = new LabelInfo(root, depth);
+            } catch (IllegalArgumentException e) {
+                log.error(e.getMessage());
+            }
+        }
+        return lInfo;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getMergeInfo()
+     */
+    public MergeInfo getMergeInfo() {
+        MergeInfo mInfo = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            try {
+               mInfo = new MergeInfo(requestDocument.getRootElement());
+            } catch (IllegalArgumentException e) {
+                log.error(e.getMessage());
+            }
+        }
+        return mInfo;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getUpdateInfo()
+     */
+    public UpdateInfo getUpdateInfo() {
+        UpdateInfo uInfo = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            try {
+               uInfo = new UpdateInfo(requestDocument.getRootElement());
+            } catch (IllegalArgumentException e) {
+                log.error(e.getMessage());
+            }
+        }
+        return uInfo;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getReportInfo()
+     */
+    public ReportInfo getReportInfo() {
+        ReportInfo rInfo = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            rInfo = new ReportInfo(requestDocument.getRootElement(), getDepth(DavConstants.DEPTH_0));
+        }
+        return rInfo;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.version.DeltaVServletRequest#getOptionsInfo()
+     */
+    public OptionsInfo getOptionsInfo() {
+        OptionsInfo info = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            info = new OptionsInfo(requestDocument.getRootElement());
+        }
+        return info;
+    }
+
+    //---------------------------------------< HttpServletRequest interface >---
+    public String getAuthType() {
+        return httpRequest.getAuthType();
+    }
+
+    public Cookie[] getCookies() {
+        return httpRequest.getCookies();
+    }
+
+    public long getDateHeader(String s) {
+        return httpRequest.getDateHeader(s);
+    }
+
+    public String getHeader(String s) {
+        return httpRequest.getHeader(s);
+    }
+
+    public Enumeration getHeaders(String s) {
+        return httpRequest.getHeaders(s);
+    }
+
+    public Enumeration getHeaderNames() {
+        return httpRequest.getHeaderNames();
+    }
+
+    public int getIntHeader(String s) {
+        return httpRequest.getIntHeader(s);
+    }
+
+    public String getMethod() {
+        return httpRequest.getMethod();
+    }
+
+    public String getPathInfo() {
+        return httpRequest.getPathInfo();
+    }
+
+    public String getPathTranslated() {
+        return httpRequest.getPathTranslated();
+    }
+
+    public String getContextPath() {
+        return httpRequest.getContextPath();
+    }
+
+    public String getQueryString() {
+        return httpRequest.getQueryString();
+    }
+
+    public String getRemoteUser() {
+        return httpRequest.getRemoteUser();
+    }
+
+    public boolean isUserInRole(String s) {
+        return httpRequest.isUserInRole(s);
+    }
+
+    public Principal getUserPrincipal() {
+        return httpRequest.getUserPrincipal();
+    }
+
+    public String getRequestedSessionId() {
+        return httpRequest.getRequestedSessionId();
+    }
+
+    public String getRequestURI() {
+        return httpRequest.getRequestURI();
+    }
+
+    public StringBuffer getRequestURL() {
+        return httpRequest.getRequestURL();
+    }
+
+    public String getServletPath() {
+        return httpRequest.getServletPath();
+    }
+
+    public HttpSession getSession(boolean b) {
+        return httpRequest.getSession(b);
+    }
+
+    public HttpSession getSession() {
+        return httpRequest.getSession();
+    }
+
+    public boolean isRequestedSessionIdValid() {
+        return httpRequest.isRequestedSessionIdValid();
+    }
+
+    public boolean isRequestedSessionIdFromCookie() {
+        return httpRequest.isRequestedSessionIdFromCookie();
+    }
+
+    public boolean isRequestedSessionIdFromURL() {
+        return httpRequest.isRequestedSessionIdFromURL();
+    }
+
+    public boolean isRequestedSessionIdFromUrl() {
+        return httpRequest.isRequestedSessionIdFromUrl();
+    }
+
+    public Object getAttribute(String s) {
+        return httpRequest.getAttribute(s);
+    }
+
+    public Enumeration getAttributeNames() {
+        return httpRequest.getAttributeNames();
+    }
+
+    public String getCharacterEncoding() {
+        return httpRequest.getCharacterEncoding();
+    }
+
+    public void setCharacterEncoding(String s) throws UnsupportedEncodingException {
+        httpRequest.setCharacterEncoding(s);
+    }
+
+    public int getContentLength() {
+        return httpRequest.getContentLength();
+    }
+
+    public String getContentType() {
+        return httpRequest.getContentType();
+    }
+
+    public ServletInputStream getInputStream() throws IOException {
+        return httpRequest.getInputStream();
+    }
+
+    public String getParameter(String s) {
+        return httpRequest.getParameter(s);
+    }
+
+    public Enumeration getParameterNames() {
+        return httpRequest.getParameterNames();
+    }
+
+    public String[] getParameterValues(String s) {
+        return httpRequest.getParameterValues(s);
+    }
+
+    public Map getParameterMap() {
+        return httpRequest.getParameterMap();
+    }
+
+    public String getProtocol() {
+        return httpRequest.getProtocol();
+    }
+
+    public String getScheme() {
+        return httpRequest.getScheme();
+    }
+
+    public String getServerName() {
+        return httpRequest.getServerName();
+    }
+
+    public int getServerPort() {
+        return httpRequest.getServerPort();
+    }
+
+    public BufferedReader getReader() throws IOException {
+        return httpRequest.getReader();
+    }
+
+    public String getRemoteAddr() {
+        return httpRequest.getRemoteAddr();
+    }
+
+    public String getRemoteHost() {
+        return httpRequest.getRemoteHost();
+    }
+
+    public void setAttribute(String s, Object o) {
+        httpRequest.setAttribute(s, o);
+    }
+
+    public void removeAttribute(String s) {
+       httpRequest.removeAttribute(s);
+    }
+
+    public Locale getLocale() {
+        return httpRequest.getLocale();
+    }
+
+    public Enumeration getLocales() {
+        return httpRequest.getLocales();
+    }
+
+    public boolean isSecure() {
+        return httpRequest.isSecure();
+    }
+
+    public RequestDispatcher getRequestDispatcher(String s) {
+        return httpRequest.getRequestDispatcher(s);
+    }
+
+    public String getRealPath(String s) {
+        return httpRequest.getRealPath(s);
+    }
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavResponse.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavResponse.java?view=auto&rev=156314
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavResponse.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavResponse.java Sun Mar  6 06:02:39 2005
@@ -0,0 +1,29 @@
+/*
+ * 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.jackrabbit.webdav;
+
+import org.apache.jackrabbit.webdav.observation.ObservationDavServletResponse;
+
+/**
+ * The empty <code>WebdavResponse</code> interface collects the functionality
+ * defined by {@link org.apache.jackrabbit.webdav.DavServletResponse} encapsulting
+ * for the core WebDAV specification (RFC 2518) as well as the various extensions
+ * used for observation and transaction support, ordering of collections, search
+ * and versioning.
+ */
+public interface WebdavResponse extends DavServletResponse,
+        ObservationDavServletResponse {
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavResponse.java
------------------------------------------------------------------------------
    svn = 

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/WebdavResponse.java
------------------------------------------------------------------------------
    svn:eol-style = native



Mime
View raw message