/**
* 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 Condition represents some state configuration of a particular resource that must be
* satisfied in order for the associated request to be valid. At least one of
* the ConditionTerms in a Condition must match with states of the resource, i.e.,
* they are OR'd together. Conditions are contained in a Precondition which is used in a
* WebDAV If header.
*/
public class Condition {
private String uri = null;
private Vector conditionTerms = new Vector();
/**
* Construct a Condition on the default resource.
*/
public Condition() {
super();
}
/**
* Construct a Condition with the given URI.
*
* @param uri the URI of the resource associated with this condition
*/
public Condition(String uri) {
this.uri = uri;
}
/**
* Add a ConditionTerm to a Condition.
*
* @param term the term to add
*/
public void addConditionTerm(ConditionTerm term) throws WebDAVException {
conditionTerms.addElement(term);
}
/**
* Does this Condition contain the given ConditionTerm?
*
* @param term the term to check for
* @return true if the condition contains the given term, false otherwise
*/
public boolean contains(ConditionTerm term) {
// iterate through the factors looking for a match
boolean match = false;
Enumeration terms = getConditionTerms();
while (!match && terms.hasMoreElements()) {
ConditionTerm t = (ConditionTerm) terms.nextElement();
match = term.matches(t);
}
return match;
}
/**
* Create a Condition by parsing the given If header as defined by
* section 9.4 in the WebDAV spec.
*
* @param tokenizer a StreamTokenizer on the contents of a WebDAV If header
* @return the parsed condition
*/
public static Condition create(StreamTokenizer tokenizer) throws WebDAVException {
Condition condition = new Condition();
try {
int token = tokenizer.ttype;
if (token == '<') {
token = tokenizer.nextToken();
if (token == StreamTokenizer.TT_WORD) {
condition.setResourceURI(tokenizer.sval);
} else {
throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMissingResource")); //$NON-NLS-1$
}
token = tokenizer.nextToken();
if (token == '>') {
token = tokenizer.nextToken();
} else {
throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMissing", String.valueOf(token), ">")); //$NON-NLS-1$ //$NON-NLS-2$
}
}
if (token == '(') {
while (token == '(') {
condition.addConditionTerm(ConditionTerm.create(tokenizer));
token = tokenizer.ttype;
}
} else {
throw new WebDAVException(IResponse.SC_BAD_REQUEST, Policy.bind("error.parseMissingStart", String.valueOf(token))); //$NON-NLS-1$
}
} catch (IOException exc) {
// ignore or log?
}
return condition;
}
/**
* Create a Condition 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 parsed condition
* @exception WebDAVException thrown if there is a syntax error in the header
*/
public static Condition create(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('"');
Condition condition = null;
try {
int token = tokenizer.nextToken();
condition = Condition.create(tokenizer);
token = tokenizer.ttype;
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$
}
} catch (IOException exc) {
// ignore or log?
}
return condition;
}
/**
* Get all the ConditionTerms for this Condition. At least one of the ConditionTerms in
* a Condition must match with states of the resource, i.e., they are OR'd
* together. Conditions are contained in a Precondition which is used in a
* WebDAV If header.
*/
public Enumeration getConditionTerms() {
return conditionTerms.elements();
}
/**
* Get the URI of the associated Resource. The condition must match on this
* resource. This is useful for Preconditions that span multiple resources.
*
* @return the resource URI whose state is described by this Condition, may be null
* indicating the condition applies to the resource receiving the request
*/
public String getResourceURI() {
return uri;
}
/**
* See if this Condition matches the given Condition. This is an
* OR operation.
*
* @param condition the condition to match against
* @return true if the conditions match, false otherwise.
*/
public boolean matches(Condition condition) {
//// check the Resource if one was given
//boolean match = true;
//if (uri != null) {
////try {
////URL url1 = new URL(uri);
////URL url2 = new URL(condition.getResourceURI());
////match = match && url1.getProtocol().equals(url2.getProtocol());
////match = match && url1.getHost().equals(url2.getHost());
////int port1 = url1.getPort();
////if (port1 == -1) { // use the default port
////port1 = 80;
////}
////int port2 = url2.getPort();
////if (port2 == -1) {
////port2 = 80;
////}
////match = match && (port1 == port2);
////match = match && url1.getFile().equals(url2.getFile());
////} catch (Exception exc) {
////match = false;
////}
//// added to fix bug. should not compare full uris, only the path
//// match = uri.equals(condition.getResourceURI());
//match = (new URI(uri)).getPath().removeTrailingSeparator().equals(
//(new URI(condition.getResourceURI())).getPath().removeTrailingSeparator());
//}
//if (!match) {
//return false;
//}
//// is each term in the condition in the given condition
//match = false;
//Enumeration terms = getConditionTerms();
//while (!match && terms.hasMoreElements()) {
//ConditionTerm term = (ConditionTerm) terms.nextElement();
//match = condition.contains(term);
//}
//return match;
return false;
}
/**
* Set the URI of the associated Resource. The condition must match on this
* resource. This is useful for Preconditions that span multiple resources.
*
* @param value the resource URI whose state is described by this Condition.
* value can be null if the condition applies to the resource executing
* the method.
*/
public void setResourceURI(String value) {
uri = value;
}
/**
* Return a String representation of this Condition as defined by section 9.4
* of the WebDAV Spec.
*
* @return a String representation of this condition
*/
public String toString() {
StringBuffer buffer = new StringBuffer();
if (getResourceURI() != null) {
buffer.append('<');
buffer.append(getResourceURI());
buffer.append("> "); //$NON-NLS-1$
}
Enumeration terms = getConditionTerms();
while (terms.hasMoreElements()) {
ConditionTerm term = (ConditionTerm) terms.nextElement();
buffer.append(term.toString());
if (terms.hasMoreElements())
buffer.append(' ');
}
return buffer.toString();
}
}