All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jakarta.security.jacc.URLPatternSpec Maven / Gradle / Ivy

There is a newer version: 11.0.0-M4
Show newest version
/*
 * Copyright (c) 1997, 2020 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package jakarta.security.jacc;

import java.util.Arrays;

/**
 * This class extends the URLPattern class and is used to represent URLPatternSpec objects. URLPatternSpec objects occur
 * within WebResourcePermission and WebUserDataPermission objects.
 *
 * @author Ron Monzillo
 * @author Gary Ellison
 */
class URLPatternSpec extends URLPattern {

    private static String EMPTY_STRING = "";

    private transient int hashCodeValue;
    private String canonicalSpec;
    private final String urlPatternList;
    private URLPattern[] urlPatternArray;

    /**
     * Creates a new URLPatternSpec that identifies the web resources to which a WebResourcePermission or
     * WebUserDataPermission applies.
     *
     * 

* The syntax of the name parameter is as follows: * *

     *
     *          URLPatternList ::= URLPattern | URLPatternList colon URLPattern
     *
     *          URLPatternSpec ::= URLPattern | URLPattern colon URLPatternList
     *
     *          name ::= URLPatternSpec
     * 
* * The first URLPattern in a URLPatternSpec may be any of the pattern types, exact, path-prefix, extension, or default * as defined in the Jakarta Servlet Specification). When a URLPatternSpec includes a URLPatternList, the patterns * of the URLPatternList identify the resources to which the permission does NOT apply and depend on the pattern type * and value of the first pattern as follows: * *
    *
  • No pattern may exist in the URLPatternList that matches the first pattern. *
  • If the first pattern is a path-prefix pattern, only exact patterns matched by the first pattern and path-prefix * patterns matched by, but different from, the first pattern may occur in the URLPatternList. *
  • If the first pattern is an extension pattern, only exact patterns that are matched by the first pattern and * path-prefix patterns may occur in the URLPatternList. *
  • If the first pattern is the default pattern, "/", any pattern except the default pattern may occur in the * URLPatternList. *
  • If the first pattern is an exact pattern a URLPatternList must not be present in the URLPatternSpec. *
* * @param urlPatternSpec a String containing a URLPatternSpec that identifies the application specific web resources to * which the permission pertains. All URLPatterns in the URLPatternSpec are relative to the context path of the deployed * web application module, and the same URLPattern must not occur more than once in a URLPatternSpec. */ public URLPatternSpec(String urlPatternSpec) { super(getFirstPattern(urlPatternSpec)); int colon = urlPatternSpec.indexOf(":"); if (colon >= 0) { urlPatternList = urlPatternSpec.substring(colon + 1); setURLPatternArray(); } else { urlPatternList = null; } } /** * This method returns a String containing the first URLPattern in this URLPatternSpec. */ public String getURLPattern() { return super.toString(); } /* * Checks two URLPatternSpec objects for equality. A reference URLPatternSpec is equivalent to an argument * URLPatternSpec if their first patterns are equivalent, and the patterns of its URLPatternList collectively match * exactly the same set of patterns as are matched by the patterns of the URLPatternList of the argument URLPatternSpec. */ @Override public boolean equals(Object o) { if (o == null || !(o instanceof URLPatternSpec)) { return false; } URLPatternSpec that = (URLPatternSpec) o; return this.toString().equals(that.toString()); } /** * Returns the hash code value for this URLPatternSpec properties of the returned hash code must be as follows: *

*

    *
  • During the lifetime of a Java application, the hashCode method must return the same integer value, every time it * is called on a URLPatternSpec object. The value returned by hashCode for a particular URlPatternSpec need not remain * consistent from one execution of an application to another. *
  • If two URLPatternSpec objects are equal according to the equals method, then calling the hashCode method on each * of the two objects must produce the same integer result (within an application). *
*

* * @return the integer hash code value for this object. */ @Override public int hashCode() { if (hashCodeValue == 0) { hashCodeValue = this.toString().hashCode(); } return hashCodeValue; } /** * Determines if the argument URLPatternSpec is "implied by" this URLPatternSpec. * *

* For this to be the case, all of the following must be true: *

    *
  • The argument is an instanceof URLPatternSpec, and *
  • The first Pattern in the argument URLPatternSpec is matched by the first URLPattern of * this URLPatternSpec. *
  • The first Pattern in the argument URLPatternSpec is NOT matched by any URLPattern in the * URLPatternList of this URLPatternSpec. *
  • If the first Pattern in the argument URLPatternSpec matches the first Pattern in this * URLPatternSpec, then every URLPattern in the URLPatternList of this URLPatternSpec is * matched by a URLPattern in the URLPatternList of the argument URLPatternSpec. *
* * URLPattern matching is performed using the Jakarta Servlet matching rules where two URL patterns match if they are * related as follows: *
    *
  • their pattern values are String equivalent, or *
  • this pattern is the path-prefix pattern "/*", or *
  • this pattern is a path-prefix pattern (that is, it starts with "/" and ends with "/*") and the argument pattern * starts with the substring of this pattern, minus its last 2 characters, and the next character of the argument * pattern, if there is one, is "/", or *
  • this pattern is an extension pattern (that is, it starts with "*.") and the argument pattern ends with this * pattern, or *
  • the reference pattern is the special default pattern, "/", which matches all argument patterns. *
* *

* All of the comparisons described above are case sensitive. * * @param that "this" URLPatternSpec is checked to see if it implies the argument URLPatternSpec. * @return true if the specified URLPatternSpec is implied by this URLPatternSpec, false if not. */ public boolean implies(URLPatternSpec that) { if (that == null) { return false; } if (!super.implies(that)) { return false; } for (int i = 0; urlPatternArray != null && i < urlPatternArray.length; i++) { if (urlPatternArray[i] != null && urlPatternArray[i].implies(that)) { return false; } } if (urlPatternArray != null && ((URLPattern) that).implies(this)) { if (that.urlPatternArray == null) { return false; } boolean flags[] = new boolean[urlPatternArray.length]; for (int i = 0; i < flags.length; i++) { flags[i] = false; } int count = 0; for (int j = 0; j < that.urlPatternArray.length; j++) { for (int i = 0; i < flags.length; i++) { if (!flags[i]) { if (urlPatternArray[i] == null || (that.urlPatternArray[j] != null && that.urlPatternArray[j].implies(urlPatternArray[i]))) { count += 1; flags[i] = true; if (count == flags.length) { return true; } } } } } return count == flags.length; } return true; } /* * This method returns a canonical String representation of the URLPatternSpec. By this time, the patterns have already * been sorted, and pruned by setURLPatternArray, such that all this method has to do is glue them together into a * string. */ @Override public String toString() { if (canonicalSpec == null) { if (urlPatternList == null) { canonicalSpec = super.toString(); } else { StringBuilder specBuilder = null; for (URLPattern urlPattern : urlPatternArray) { if (urlPattern != null) { if (specBuilder == null) { specBuilder = new StringBuilder(urlPattern.toString()); } else { specBuilder.append(":" + urlPattern.toString()); } } } if (specBuilder == null) { canonicalSpec = super.toString(); } else { canonicalSpec = super.toString() + ":" + specBuilder.toString(); } } } return canonicalSpec; } // ----------------- Private Methods --------------------- private static String getFirstPattern(String urlPatternSpec) { if (urlPatternSpec == null) { throw new IllegalArgumentException("Invalid URLPatternSpec"); } int colon = urlPatternSpec.indexOf(":"); if (colon < 0) { return urlPatternSpec; } if (colon > 0) { return urlPatternSpec.substring(0, colon); } if (colon == 0) { return EMPTY_STRING; } throw new IllegalArgumentException("Invalid URLPatternSpec"); } private void setURLPatternArray() { if (urlPatternArray == null && urlPatternList != null) { String[] tokens = urlPatternList.split(":", -1); int count = tokens.length; if (count == 0) { throw new IllegalArgumentException("colon followed by empty URLPatternList"); } urlPatternArray = new URLPattern[count]; int firstType = this.patternType(); for (int i = 0; i < count; i++) { urlPatternArray[i] = new URLPattern(tokens[i]); if (urlPatternArray[i].implies(this)) { throw new IllegalArgumentException("pattern in URLPatternList implies first pattern"); } switch (firstType) { case URLPattern.PT_PREFIX: case URLPattern.PT_EXTENSION: switch (urlPatternArray[i].patternType()) { case URLPattern.PT_PREFIX: if (firstType == URLPattern.PT_PREFIX) { if (super.equals(urlPatternArray[i]) || !super.implies(urlPatternArray[i])) { throw new IllegalArgumentException("Invalid prefix pattern in URLPatternList"); } } break; case URLPattern.PT_EXACT: if (!super.implies(urlPatternArray[i])) { throw new IllegalArgumentException("Invalid exact pattern in URLPatternList"); } break; default: throw new IllegalArgumentException("Invalid pattern type in URLPatternList"); } case URLPattern.PT_DEFAULT: if (super.equals(urlPatternArray[i])) { throw new IllegalArgumentException("Invalid default pattern in URLPatternList"); } break; case URLPattern.PT_EXACT: throw new IllegalArgumentException("invalid URLPatternSpec"); default: throw new IllegalArgumentException("Invalid pattern type in URLPatternList"); } } Arrays.sort(urlPatternArray); for (int i = 0; i < urlPatternArray.length; i++) { if (urlPatternArray[i] != null) { switch (urlPatternArray[i].patternType()) { case URLPattern.PT_PREFIX: for (int j = i + 1; j < urlPatternArray.length; j++) { if (urlPatternArray[i].implies(urlPatternArray[j])) { urlPatternArray[j] = null; } } break; default: break; } } } } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy