📄 ifheader.java
字号:
/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.header;import org.apache.jackrabbit.webdav.DavConstants;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import javax.servlet.http.HttpServletRequest;import java.io.IOException;import java.io.Reader;import java.io.StringReader;import java.util.ArrayList;import java.util.Arrays;import java.util.HashMap;import java.util.Iterator;import java.util.List;/** * 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>< ></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>(<token> [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 <notoken>)</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 implements Header { /** * default logger */ private static final Logger log = LoggerFactory.getLogger(IfHeader.class); /** * The string representation of the header value */ private final String headerValue; /** * The list of untagged state entries */ private final IfHeaderInterface ifHeader; /** * The list of all positive tokens present in the If header. */ private List allTokens = new ArrayList(); /** * The list of all NOT tokens present in the If header. */ private List allNotTokens = new ArrayList(); /** * Create a Untagged <code>IfHeader</code> if the given lock tokens. * * @param tokens */ public IfHeader(String[] tokens) { allTokens.addAll(Arrays.asList(tokens)); StringBuffer b = new StringBuffer(); for (int i = 0; i < tokens.length; i++) { b.append("(").append("<"); b.append(tokens[i]); b.append(">").append(")"); } headerValue = b.toString(); ifHeader = parse(); } /** * 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) { headerValue = req.getHeader(DavConstants.HEADER_IF); ifHeader = parse(); } /** * Return {@link DavConstants#HEADER_IF If} * * @return {@link DavConstants#HEADER_IF If} * @see DavConstants#HEADER_IF */ public String getHeaderName() { return DavConstants.HEADER_IF; } /** * Return the String representation of the If header present on * the given request or <code>null</code>. * * @return If header value as String or <code>null</code>. */ public String getHeaderValue() { return headerValue; } /** * Returns true if an If header was present in the given request. False otherwise. * * @return true if an If header was present. */ public boolean hasValue() { return 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 an interator over all tokens present in the if header, that were * not denied by a leading NOT statement. */ public Iterator getAllTokens() { return allTokens.iterator(); } /** * @return an interator over all NOT tokens present in the if header, that * were explicitely denied. */ public Iterator getAllNotTokens() { return allNotTokens.iterator(); } /** * Parse the original header value and build th internal IfHeaderInterface * object that is easy to query. */ private IfHeaderInterface parse() { IfHeaderInterface ifHeader; if (headerValue != null && headerValue.length() > 0) { StringReader reader = null; int firstChar = 0; try { reader = new StringReader(headerValue); // 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; } return ifHeader; } //---------- 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.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -