001: package com.ibm.webdav;
002:
003: /*
004: * (C) Copyright IBM Corp. 2000 All rights reserved.
005: *
006: * The program is provided "AS IS" without any warranty express or
007: * implied, including the warranty of non-infringement and the implied
008: * warranties of merchantibility and fitness for a particular purpose.
009: * IBM will not be liable for any damages suffered by you as a result
010: * of using the Program. In no event will IBM be liable for any
011: * special, indirect or consequential damages or lost profits even if
012: * IBM has been advised of the possibility of their occurrence. IBM
013: * will not be liable for any third party claims against you.
014: *
015: * Portions Copyright (C) Simulacra Media Ltd, 2004.
016: */
017: import java.util.Vector;
018: import java.util.Enumeration;
019: import java.io.StringWriter;
020: import java.io.StringReader;
021: import java.io.IOException;
022: import java.io.StreamTokenizer;
023:
024: /** A Precondition represents some condition or collection of conditions
025: * representing states of a resource. If the state of the resource does not
026: * match any of the specified states in any of the conditions, then the
027: * method must fail. Conditions in a Precondition are OR'd together while
028: * ConditionFactors in a ConditionTerm are AND'ed.
029: * @author Jim Amsden <jamsden@us.ibm.com>
030: * @see com.ibm.webdav.Precondition
031: * @see com.ibm.webdav.ConditionTerm
032: * @see com.ibm.webdav.ConditionFactor
033: * @see com.ibm.webdav.EntityTag
034: * @see com.ibm.webdav.StateToken
035: */
036: public class Precondition {
037: private Vector conditions = new Vector();
038:
039: /** Construct an empty Precondition. The client must add Conditions.
040: */
041: public Precondition() {
042: }
043:
044: /** Construct a Precondition by parsing the given If header as defined by
045: * section 8.4 in the WebDAV spec.
046: * @param ifHeader the contents of a WebDAV If header
047: */
048: public Precondition(String ifHeader) throws WebDAVException {
049: StreamTokenizer tokenizer = new StreamTokenizer(
050: new StringReader(ifHeader));
051: // URI characters
052: tokenizer.wordChars('!', '/');
053: tokenizer.wordChars(':', '@');
054: tokenizer.wordChars('[', '_');
055: tokenizer.ordinaryChar('(');
056: tokenizer.ordinaryChar(')');
057: tokenizer.ordinaryChar('<');
058: tokenizer.ordinaryChar('>');
059: tokenizer.ordinaryChar('[');
060: tokenizer.ordinaryChar(']');
061:
062: tokenizer.quoteChar('"');
063:
064: int token = 0;
065: try {
066: token = tokenizer.nextToken();
067: switch (token) {
068: case '<': {
069: while (token == '<') {
070: addCondition(Condition.create(tokenizer));
071: token = tokenizer.ttype;
072: }
073: break;
074: }
075: case '(': {
076: while (token == '(') {
077: addCondition(Condition.create(tokenizer));
078: token = tokenizer.ttype;
079: }
080: break;
081: }
082: }
083: if (token != StreamTokenizer.TT_EOF) {
084: throw new WebDAVException(WebDAVStatus.SC_BAD_REQUEST,
085: "Error parsing If header: saw: " + (char) token
086: + " expected: EOF");
087: }
088: if (!getConditions().hasMoreElements()) {
089: throw new WebDAVException(WebDAVStatus.SC_BAD_REQUEST,
090: "Syntax error in If header: list is empty: "
091: + ifHeader);
092: }
093: } catch (IOException exc) {
094: }
095: }
096:
097: /** Add a Condition to this Precondition. Conditions are OR'd together to
098: * check for a matching resource.
099: * @param condition the Condition to add
100: * @exception com.ibm.webdav.WebDAVException thrown if the precondition already contains this condition
101: */
102: public void addCondition(Condition condition)
103: throws WebDAVException {
104: // a Resource URI can only be specified once in a Precondition
105: Enumeration conditions = getConditions();
106: if (condition.getResourceURI() != null) {
107: while (conditions.hasMoreElements()) {
108: Condition existingCondition = (Condition) conditions
109: .nextElement();
110: if (existingCondition.getResourceURI() != null
111: && existingCondition.getResourceURI().equals(
112: condition.getResourceURI())) {
113: throw new WebDAVException(
114: WebDAVStatus.SC_BAD_REQUEST,
115: condition.getResourceURI()
116: + " cannot be specified more than once in an If header");
117: }
118: }
119: }
120: this .conditions.addElement(condition);
121: }
122:
123: /** Add a condition created from the given URI and state token. This is a
124: * convenience method used primarily to create preconditions for lock tokens
125: * that must be provided in the resource context for methods that update
126: * the resource.
127: *
128: * @param resourceURI the URI of the resource the state token applies to. Null
129: * implicitly specifies the resource processing the request
130: * @param stateToken the state token to match
131: */
132: public void addStateTokenCondition(String resourceURI,
133: String stateToken) throws WebDAVException {
134: Condition condition = new Condition(resourceURI);
135: ConditionTerm term = new ConditionTerm();
136: term.addConditionFactor(new StateToken(stateToken));
137: condition.addConditionTerm(term);
138: addCondition(condition);
139: }
140:
141: /** Construct a Precondition by parsing the given If header as defined by
142: * section 9.4 in the WebDAV spec.
143: * @param ifHeader the contents of a WebDAV If header
144: * @return the parser If header
145: * @exception com.ibm.webdav.WebDAVException thrown if there is a syntax error in the If header
146: */
147: public static Precondition create(String ifHeader)
148: throws WebDAVException {
149: return new Precondition(ifHeader);
150: }
151:
152: /** Get the Conditions contained in this Precondition. At least one must match
153: * in order for a valid match to occur.
154: * @return an Enumeration of Conditions
155: */
156: public Enumeration getConditions() {
157: return conditions.elements();
158: }
159:
160: /** See if this Precondition contains a matching Condition.
161: * @param condition the condition to match
162: * @return true if this precondition contains atleast one condition matching the given condition
163: */
164: public boolean matches(Condition condition) {
165: boolean match = false;
166: Enumeration conditions = getConditions();
167: while (!match && conditions.hasMoreElements()) {
168: Condition existingCondition = (Condition) conditions
169: .nextElement();
170: match = existingCondition.matches(condition);
171: }
172: return match;
173: }
174:
175: /** Return a String representation of this Precondition as defined by section 9.4
176: * of the WebDAV Spec. The string is the value of an If header.
177: * @return a string representation of this precondition
178: */
179: public String toString() {
180: StringWriter os = new StringWriter();
181: Enumeration conditions = getConditions();
182: while (conditions.hasMoreElements()) {
183: Condition condition = (Condition) conditions.nextElement();
184: os.write(condition.toString());
185: if (conditions.hasMoreElements()) {
186: os.write(' ');
187: }
188: }
189: try {
190: os.close();
191: } catch (Exception exc) {
192: }
193: return os.toString();
194: }
195: }
|