/**
* Copyright 2010 JBoss Inc
*
* 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.eclipse.webdav.internal.kernel;
import java.io.*;
import java.util.Enumeration;
import java.util.Vector;
import org.eclipse.webdav.IResponse;
/**
* A Precondition represents some condition or collection of conditions
* representing states of a resource. If the state of the resource does not
* match any of the specified states in any of the conditions, then the
* method must fail. Conditions in a Precondition are OR'd together while
* ConditionFactors in a ConditionTerm are AND'ed.
*/
public class Precondition {
private Vector conditions = new Vector();
/**
* Construct an empty Precondition. The client must add Conditions.
*/
public Precondition() {
super();
}
/**
* Construct a Precondition by parsing the given If header as defined by
* section 8.4 in the WebDAV spec.
*
* @param ifHeader the contents of a WebDAV If header
*/
public Precondition(String ifHeader) throws WebDAVException {
StreamTokenizer tokenizer = new StreamTokenizer(new StringReader(ifHeader));
// URI characters
tokenizer.wordChars('!', '/');
tokenizer.wordChars(':', '@');
tokenizer.ordinaryChar('(');
tokenizer.ordinaryChar(')');
tokenizer.ordinaryChar('<');
tokenizer.ordinaryChar('>');
tokenizer.ordinaryChar('[');
tokenizer.ordinaryChar(']');
tokenizer.quoteChar('"');
int token = 0;
try {
token = tokenizer.nextToken();
switch (token) {
case '<' :
while (token == '<') {
addCondition(Condition.create(tokenizer));
token = tokenizer.ttype;
}
break;
case '(' :
while (token == '(') {
addCondition(Condition.create(tokenizer));
token = tokenizer.ttype;
}
break;
}
if (token != StreamTokenizer.TT_EOF)
throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMissing", String.valueOf(token), "EOF")); //$NON-NLS-1$ //$NON-NLS-2$
if (!getConditions().hasMoreElements())
throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseEmptyList", ifHeader)); //$NON-NLS-1$
} catch (IOException exc) {
// ignore or log?
}
}
/**
* Add a Condition to this Precondition. Conditions are OR'd together to
* check for a matching resource.
*
* @param condition the Condition to add
* @exception WebDAVException thrown if the precondition already contains this condition
*/
public void addCondition(Condition condition) throws WebDAVException {
// a Resource URI can only be specified once in a Precondition
Enumeration conditions = getConditions();
if (condition.getResourceURI() != null) {
while (conditions.hasMoreElements()) {
Condition existingCondition = (Condition) conditions.nextElement();
if (existingCondition.getResourceURI() != null && existingCondition.getResourceURI().equals(condition.getResourceURI()))
throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMultipleSpecification", condition.getResourceURI())); //$NON-NLS-1$
}
}
this.conditions.addElement(condition);
}
/**
* Add a condition created from the given URI and state token. This is a
* convenience method used primarily to create preconditions for lock tokens
* that must be provided in the resource context for methods that update
* the resource.
*
* @param resourceURI the URI of the resource the state token applies to. Null
* implicitly specifies the resource processing the request
* @param stateToken the state token to match
*/
public void addStateTokenCondition(String resourceURI, String stateToken) throws WebDAVException {
Condition condition = new Condition(resourceURI);
ConditionTerm term = new ConditionTerm();
term.addConditionFactor(new StateToken(stateToken));
condition.addConditionTerm(term);
addCondition(condition);
}
/**
* Construct a Precondition by parsing the given If header as defined by
* section 9.4 in the WebDAV spec.
*
* @param ifHeader the contents of a WebDAV If header
* @return the parser If header
* @exception WebDAVException thrown if there is a syntax error in the If header
*/
public static Precondition create(String ifHeader) throws WebDAVException {
return new Precondition(ifHeader);
}
/**
* Get the Conditions contained in this Precondition. At least one must match
* in order for a valid match to occur.
*
* @return an Enumeration of Conditions
*/
public Enumeration getConditions() {
return conditions.elements();
}
/**
* See if this Precondition contains a matching Condition.
*
* @param condition the condition to match
* @return true if this precondition contains atleast one condition matching the given condition
*/
public boolean matches(Condition condition) {
boolean match = false;
Enumeration conditions = getConditions();
while (!match && conditions.hasMoreElements()) {
Condition existingCondition = (Condition) conditions.nextElement();
match = existingCondition.matches(condition);
}
return match;
}
/**
* Return a String representation of this Precondition as defined by section 9.4
* of the WebDAV Spec. The string is the value of an If header.
*
* @return a string representation of this precondition
*/
public String toString() {
StringBuffer buffer = new StringBuffer();
Enumeration conditions = getConditions();
while (conditions.hasMoreElements()) {
Condition condition = (Condition) conditions.nextElement();
buffer.append(condition.toString());
if (conditions.hasMoreElements())
buffer.append(' ');
}
return buffer.toString();
}
}