/** * 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(); } }