001/*
002 * (C) Copyright 2006-2012 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     Bogdan Stefanescu
018 *     Florent Guillaume
019 */
020package org.nuxeo.ecm.webengine;
021
022import org.nuxeo.common.xmap.annotation.XNode;
023import org.nuxeo.common.xmap.annotation.XObject;
024import org.nuxeo.ecm.webengine.util.PathMatcher;
025
026/**
027 * Configure how a given path is handled by the WebEngine filter.
028 * <p>
029 * If <b>autoTx</b> is true (which is the default) then a transaction will be started each time a path matching the
030 * given path specification is requested. (the transaction is started in a filter before the JAX-RS resource is called
031 * and closed after the response is sent to the output stream). If false then no transaction handling is done. The
032 * default is to start a transaction for any path but: [^/]+/skin/.*
033 * <p>
034 * The <b>value</b> attribute is required and must be used to specify the path pattern. The path pattern is either a
035 * prefix or a regular expression. If the <b>regex</b> parameter is true (the default is false) then the value will be
036 * expected to be a regular expression. A prefix denotes a path starting with 'prefix'. Paths are relative to the
037 * webengine servlet (i.e. they correspond to the servlet path info in the JAX-RS servlet) - and always begin with a
038 * '/'.
039 */
040@XObject("path")
041public class PathDescriptor implements Comparable<PathDescriptor> {
042
043    @XNode("@value")
044    protected String value;
045
046    @XNode("@regex")
047    protected boolean regex = false;
048
049    @XNode("@autoTx")
050    protected Boolean autoTx;
051
052    protected PathMatcher matcher;
053
054    public PathDescriptor() {
055    }
056
057    public PathMatcher getMatcher() {
058        return matcher;
059    }
060
061    public String getValue() {
062        return value;
063    }
064
065    public Boolean getAutoTx() {
066        return autoTx;
067    }
068
069    public boolean isAutoTx(boolean defaultValue) {
070        return autoTx == null ? defaultValue : autoTx.booleanValue();
071    }
072
073    public PathMatcher createMatcher() {
074        if (value != null) {
075            if (!value.startsWith("/")) {
076                value = "/" + value;
077            }
078            matcher = regex ? PathMatcher.getRegexMatcher(value) : PathMatcher.getPrefixMatcher(value);
079        } else {
080            throw new IllegalArgumentException("Path value is required");
081        }
082        return matcher;
083    }
084
085    public boolean match(String path) {
086        return matcher.match(path);
087    }
088
089    @Override
090    public boolean equals(Object obj) {
091        if (obj == this) {
092            return true;
093        }
094        if (obj instanceof PathDescriptor) {
095            PathDescriptor pd = ((PathDescriptor) obj);
096            return value != null && value.equals(pd.value) || value == pd.value;
097        }
098        return false;
099    }
100
101    @Override
102    public int hashCode() {
103        return value.hashCode();
104    }
105
106    @Override
107    public String toString() {
108        return value + "; autoTx: " + autoTx;
109    }
110
111    @Override
112    public int compareTo(PathDescriptor o) {
113        if (regex != o.regex) {
114            return regex ? 1 : -1;
115        }
116        int len1 = value.length();
117        int len2 = o.value.length();
118        if (len1 == len2) {
119            return value.compareTo(o.value);
120        }
121        return len2 - len1;
122    }
123
124}