001/*
002 * (C) Copyright 2006-2007 Nuxeo SAS (http://nuxeo.com/) and contributors.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Nuxeo - initial API and implementation
016 *
017 * $Id$
018 */
019
020package org.nuxeo.runtime.deployment.preprocessor.install.filters;
021
022import org.nuxeo.common.utils.Path;
023import org.nuxeo.common.utils.PathFilter;
024
025/**
026 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
027 */
028public abstract class AbstractFilter implements PathFilter {
029
030    protected final Path pattern;
031
032    protected AbstractFilter(Path pattern) {
033        this.pattern = pattern;
034    }
035
036    public boolean accept(Path path, boolean defaultPolicy) {
037        // path should be in canonical form
038        boolean match = segmentsMatch(pattern, path);
039        return match ? !defaultPolicy : defaultPolicy;
040    }
041
042    protected static boolean segmentsMatch(Path pattern, Path path) {
043        int patternLen = pattern.segmentCount();
044        int k = 0;
045        for (int i = 0, len = path.segmentCount(); i < len; i++) {
046            if (k >= patternLen) {
047                return false;
048            }
049            String segPattern = pattern.segment(k);
050            String segment = path.segment(i);
051            if (segPattern.equals("**")) {
052                k++;
053                if (k == patternLen) {
054                    return true;
055                }
056                // skip non matching segments
057                String match = pattern.segment(k);
058                for (; i < len; i++) {
059                    if (segmentMatch(match, path.segment(i))) {
060                        k++;
061                        break;
062                    }
063                }
064            } else if (segmentMatch(segPattern, segment)) {
065                k++;
066            } else {
067                return false;
068            }
069        }
070        return k >= patternLen;
071    }
072
073    public static boolean segmentMatch(String pattern, String segment) {
074        if (pattern.equals("*")) {
075            return true;
076        }
077        int p = pattern.indexOf('*');
078        if (p == -1) {
079            return pattern.equals(segment);
080        }
081        if (p == 0) {
082            if (!segment.endsWith(pattern.substring(1))) {
083                return false;
084            }
085        } else if (p == pattern.length() - 1) {
086            if (!segment.startsWith(pattern.substring(0, p))) {
087                return false;
088            }
089        } else {
090            String prefix = pattern.substring(0, p);
091            String suffix = pattern.substring(p + 1);
092            if (!segment.startsWith(prefix) || !segment.endsWith(suffix)) {
093                return false;
094            }
095        }
096        return true;
097    }
098
099}