5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster/**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Copyright (c) 2009 Sun Microsystems Inc. All Rights Reserved
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * The contents of this file are subject to the terms
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * of the Common Development and Distribution License
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * (the License). You may not use this file except in
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * compliance with the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * You can obtain a copy of the License at
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * opensso/legal/CDDLv1.0.txt
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * See the License for the specific language governing
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * permission and limitations under the License.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * When distributing Covered Code, include this CDDL
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Header Notice in each file and include the License file
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * at opensso/legal/CDDLv1.0.txt.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * If applicable, add the following below the CDDL Header,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * with the fields enclosed by brackets [] replaced by
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * your own identifying information:
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * $Id: HttpURLResourceName.java,v 1.1 2009/11/24 21:42:35 madan_ranganath Exp $
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterpackage com.sun.identity.shared.whitelist;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna/** This implementation of {@link ResourceName} extends
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna * {@link URLResourceName} to add special handling of resources which end
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna * in delimiter ({@link org.forgerock.openam.shared.resourcename.BaseURLResourceName})
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna * followed by a multi level wildcard. Wildcard card at the end matches across levels.
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * so <code>http://abc.com/b/c/d/*</code> matches <code>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * http://abc.com/b/c/d/e/f/g.html</code>
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * while <code>http://abc.com/"*"/d</code> matches only string of type
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * <code>http://abc.com/a/d</code>. So embedded wildcard matches only at that
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * level where specified, while wildcard at the end, matches
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * across levels.
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Behaviour of existing URLResourceName was not changed to
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * maintain backward compatibility.
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna *
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna * @see {@see BaseURLResourceName}
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Fosterpublic class HttpURLResourceName extends URLResourceName {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster /**
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Compares two resources.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * Description: The targetResource may contain wildcard '*' which
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * matches zero or more characters. The wildcard character
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * can show up anywhere within the string. The targetResource
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * can contain any number of wildcard characters.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * One of the five possible match types is returned based
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * on how the two resource strings are related. The comparison
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * starts from the beginning of the reource strings.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * ResourceMatch.NO_MATCH means two resources don't match.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * ResourceMatch.EXACT_MATCH means two resources match.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * ResourceMatch.SUB_RESOURCE_MATCH means targetResource is
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * a sub resource of the requestResource.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * ResourceMatch.SUPER_RESOURCE_MATCH means targetResource
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * is a super resource of the requestResource.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * ResourceMatch.WILDCARD_MATCH means two resources match
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * with respect to the wildcard.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param requestResource name of the resource which will be compared
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param targetResource name of the resource which will be compared with
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @param wildcardCompare flag for wildcard comparison
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster *
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * @return returns <code>ResourceMatch</code> that
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * specifies if the resources are exact match, or
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster * otherwise.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster */
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster public ResourceMatch compare(String requestResource,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String targetResource,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster boolean wildcardCompare)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((requestResource == null) || (targetResource == null)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return ResourceMatch.NO_MATCH;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (debug.messageEnabled()) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("HttpURLResourceName.compare: "
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster + "request resource=" + requestResource
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster + "; policy resource=" + targetResource);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // The wildcards should not match the special character '?' if present
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // in the resources.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int requestIndex = requestResource.indexOf("?");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster int targetIndex = targetResource.indexOf("?");
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((requestIndex >= 0) || (targetIndex >= 0)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ResourceMatch result = ResourceMatch.NO_MATCH;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster // separate the resources at '?' if any.
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String requestSubstring1 = requestResource;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String requestSubstring2 = null;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (requestIndex >= 0) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster requestSubstring1 = requestResource.substring(0, requestIndex);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (requestResource.length() > (requestIndex+1)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster requestSubstring2 = requestResource.substring(requestIndex+1);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String targetSubstring1 = targetResource;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster String targetSubstring2 = null;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (targetIndex >= 0) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster targetSubstring1 = targetResource.substring(0, targetIndex);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (targetResource.length() > (targetIndex+1)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster targetSubstring2 = targetResource.substring(targetIndex+1);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (debug.messageEnabled()) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("HttpURLResourceName.compare: "
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster + "request resource substring1=" + requestSubstring1
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster + "; request resource substring2=" + requestSubstring2
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster + "; policy resource substring1=" + targetSubstring1
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster + "; policy resource substring2=" + targetSubstring2);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ResourceMatch substring1Res =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster compare(requestSubstring1, targetSubstring1, wildcardCompare);
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna if ((substring1Res == ResourceMatch.EXACT_MATCH) || (substring1Res == ResourceMatch.WILDCARD_MATCH)) {
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna if (targetSubstring2 != null && targetSubstring2.equals(wildcard) && requestResource.contains("?") &&
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna ((requestSubstring2 == null) || (requestSubstring2.trim().length() == 0))) {
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna return ResourceMatch.WILDCARD_MATCH;
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna }
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna if ((requestSubstring2 == null) || (requestSubstring2.trim().length() == 0)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return ResourceMatch.SUB_RESOURCE_MATCH;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((targetSubstring2 == null)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster || (targetSubstring2.trim().length() == 0)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return ResourceMatch.SUPER_RESOURCE_MATCH;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster ResourceMatch substring2Res =
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster compare(requestSubstring2, targetSubstring2, wildcardCompare);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((substring2Res == ResourceMatch.EXACT_MATCH)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster || (substring2Res == ResourceMatch.WILDCARD_MATCH)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (substring1Res == substring2Res) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster result = substring2Res;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster result = ResourceMatch.WILDCARD_MATCH;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster result = substring1Res;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (debug.messageEnabled()) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("HttpURLResourceName.compare: with query string "
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster + "; result=" + result);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return result;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna if ((!wildcardCompare) || !targetResource.endsWith(delimiter+wildcard)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return (super.compare(requestResource, targetResource,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster wildcardCompare));
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster
c4329510051cce0c6b3efc1fae122ec4c5d61efaDavid Luna ResourceMatch res = super.compare(requestResource, targetResource,
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster wildcardCompare);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if ((res == ResourceMatch.EXACT_MATCH)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster || (res == ResourceMatch.WILDCARD_MATCH)
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster || (res == ResourceMatch.SUPER_RESOURCE_MATCH)) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster res = ResourceMatch.WILDCARD_MATCH;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else if (res == ResourceMatch.SUB_RESOURCE_MATCH) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster res = ResourceMatch.SUB_RESOURCE_MATCH;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster } else {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster res = ResourceMatch.NO_MATCH;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster if (debug.messageEnabled()) {
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster debug.message("HttpURLResourceName.compare: result=" + res);
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster return res;
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster }
5c099afa7c9361afc2f4477fec0e3018588d7840Allan Foster}