001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one
003     * or more contributor license agreements.  See the NOTICE file
004     * distributed with this work for additional information
005     * regarding copyright ownership.  The ASF licenses this file
006     * to you under the Apache License, Version 2.0 (the
007     * "License"); you may not use this file except in compliance
008     * with the License.  You may obtain a copy of the License at
009     *
010     *  http://www.apache.org/licenses/LICENSE-2.0
011     *
012     * Unless required by applicable law or agreed to in writing,
013     * software distributed under the License is distributed on an
014     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015     * KIND, either express or implied.  See the License for the
016     * specific language governing permissions and limitations
017     * under the License.
018     */
019    
020    
021    package org.apache.geronimo.security.util;
022    
023    import java.util.Set;
024    import java.util.HashSet;
025    import java.util.regex.Pattern;
026    
027    /**
028     * Tracks sets of HTTP actions for use while computing permissions during web deployment.
029     *
030     * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
031     */
032    public class HTTPMethods {
033        private static final Pattern TOKEN_PATTERN = Pattern.compile("[!-~&&[^\\(\\)\\<\\>@,;:\\\\\"/\\[\\]\\?=\\{\\}]]*");
034    
035        private final Set<String> methods = new HashSet<String>();
036        private boolean isExcluded = false;
037    
038    
039        public HTTPMethods() {
040        }
041    
042        public HTTPMethods(HTTPMethods httpMethods, boolean complemented) {
043            isExcluded = httpMethods.isExcluded ^ complemented;
044            methods.addAll(httpMethods.methods);
045        }
046    
047        public void add(String httpMethod) {
048            if (isExcluded) {
049                checkToken(httpMethod);
050                methods.remove(httpMethod);
051            } else if (httpMethod == null || httpMethod.length() == 0) {
052                isExcluded = true;
053                methods.clear();
054            } else {
055                checkToken(httpMethod);
056                methods.add(httpMethod);
057            }
058        }
059    
060        public HTTPMethods add(HTTPMethods httpMethods) {
061            if (isExcluded) {
062                if (httpMethods.isExcluded) {
063                    methods.retainAll(httpMethods.methods);
064                } else {
065                    methods.removeAll(httpMethods.methods);
066                }
067            } else {
068                if (httpMethods.isExcluded) {
069                    isExcluded = true;
070                    Set<String> toRemove = new HashSet<String>(methods);
071                    methods.clear();
072                    methods.addAll(httpMethods.methods);
073                    methods.removeAll(toRemove);
074                } else {
075                    methods.addAll(httpMethods.methods);
076                }
077            }
078            return this;
079        }
080    
081        public String getHttpMethods() {
082            return getHttpMethodsBuffer(isExcluded).toString();
083        }
084    
085        public StringBuffer getHttpMethodsBuffer() {
086            return getHttpMethodsBuffer(isExcluded);
087        }
088    
089        public String getComplementedHttpMethods() {
090            return getHttpMethodsBuffer(!isExcluded).toString();
091        }
092    
093        private StringBuffer getHttpMethodsBuffer( boolean excluded) {
094            StringBuffer buffer = new StringBuffer();
095            if (excluded) {
096                buffer.append("!");
097            }
098            boolean afterFirst = false;
099            for (String method : methods) {
100                if (afterFirst) {
101                    buffer.append(",");
102                } else {
103                    afterFirst = true;
104                }
105                buffer.append(method);
106            }
107            return buffer;
108        }
109    
110        private void checkToken(String method) {
111            if (!TOKEN_PATTERN.matcher(method).matches()) {
112                throw new IllegalArgumentException("Invalid HTTPMethodSpec");
113            }
114        }
115    
116    
117        public boolean isNone() {
118            return !isExcluded && methods.isEmpty();
119        }
120    }