001    /*
002     * Copyright (C) 2014 XStream Committers.
003     * All rights reserved.
004     *
005     * Created on 09. January 2014 by Joerg Schaible
006     */
007    package com.thoughtworks.xstream.security;
008    
009    /**
010     * Permission for any type with a name matching one of the provided wildcard expressions.
011     * 
012     * <p>
013     * Supported are patterns with path expressions using dot as separator:
014     * </p>
015     * <ul>
016     * <li>?: one non-control character except separator, e.g. for 'java.net.Inet?Address'</li>
017     * <li>*: arbitrary number of non-control characters except separator, e.g. for types in a package like 'java.lang.*'</li>
018     * <li>**: arbitrary number of non-control characters including separator, e.g. for types in a package and subpackages like 'java.lang.**'</li>
019     * </ul>
020     * <p>
021     * The complete range of UTF-8 characters is supported except control characters.
022     * </p>
023     * 
024     * @author J&ouml;rg Schaible
025     * @since 1.4.7
026     */
027    public class WildcardTypePermission extends RegExpTypePermission {
028    
029        /**
030         * @since 1.4.7
031         */
032        public WildcardTypePermission(final String[] patterns) {
033            super(getRegExpPatterns(patterns));
034        }
035    
036        private static String[] getRegExpPatterns(final String[] wildcards) {
037            if (wildcards == null)
038                return null;
039            final String[] regexps = new String[wildcards.length];
040            for (int i = 0; i < wildcards.length; ++i) {
041                final String wildcardExpression = wildcards[i];
042                final StringBuffer result = new StringBuffer(wildcardExpression.length() * 2);
043                result.append("(?u)");
044                final int length = wildcardExpression.length();
045                for (int j = 0; j < length; j++) {
046                    final char ch = wildcardExpression.charAt(j);
047                    switch (ch) {
048                    case '\\':
049                    case '.':
050                    case '+':
051                    case '|':
052                    case '[':
053                    case ']':
054                    case '(':
055                    case ')':
056                    case '^':
057                    case '$':
058                        result.append('\\').append(ch);
059                        break;
060    
061                    case '?':
062                        result.append('.');
063                        break;
064    
065                    case '*':
066                        // see "General Category Property" in http://www.unicode.org/reports/tr18/
067                        if (j + 1 < length && wildcardExpression.charAt(j + 1) == '*') {
068                            result.append("[\\P{C}]*");
069                            j++;
070                        } else {
071                            result.append("[\\P{C}&&[^").append('.').append("]]*");
072                        }
073                        break;
074    
075                    default:
076                        result.append(ch);
077                        break;
078                    }
079                }
080                regexps[i] = result.toString();
081            }
082            return regexps;
083        }
084    }