8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2008 Sun Microsystems Inc. All Rights Reserved
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The contents of this file are subject to the terms
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * of the Common Development and Distribution License
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * (the License). You may not use this file except in
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * compliance with the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * You can obtain a copy of the License at
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * opensso/legal/CDDLv1.0.txt
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * permission and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Header Notice in each file and include the License file
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * at opensso/legal/CDDLv1.0.txt.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * If applicable, add the following below the CDDL Header,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * with the fields enclosed by brackets [] replaced by
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * your own identifying information:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * "Portions Copyrighted [year] [name of copyright owner]"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * $Id: MapDuplicateKeyChecker.java,v 1.3 2008/07/03 09:39:14 veiming Exp $
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpackage com.sun.identity.common.configuration;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Iterator;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.Set;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport java.util.HashSet;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster/**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This helper class is used by the map validators to detect if a duplicate key
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * is in the set. Many of the map properties in Agent Properties. e.g.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <code>com.sun.identity.agents.config.filter.mode</code> are validated with
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * pattern matching, and additionally need to check if there is more than one
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * setting for the exact same key.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The values in set of properties should be, for example
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * [somecontextroot]=somevalue and "somecontextroot" should only be set to one
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * value.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Precondition :Assumes that values in the Set dont allow the characters "["
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * or "]" inside the brackets, so it use bracket as a special character in
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * parsing.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Duplicates are exact duplicates, since set does not distinguish between
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * letter case of a key, so "Key" is a different key from "key". We dont check
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * for duplicates such as this type of possible case.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * However, we do check for exact duplicate context root name within whole
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * values, so if user inputs [mycontextroot]=ALL and [mycontextroot]=NONE then
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * both values will be in the set, and this code will detect that
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * "mycontextroot" is a duplicate so set will be considered invalid.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpublic class MapDuplicateKeyChecker {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /**
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Values in set are of the form [somekey]=somevalue and this value
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * is later used in code which will use the "somekey" as a key. So we
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * need to check for the case of duplicate key eg:
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * [samekey]=value
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * [samekey]=another_value_for_same_key
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * So need to parse values and get the keys and see if any duplicates.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This method should only be called after a validation method has
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * determined that the set of values is valid in terms of patter matching.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * For case sensitivity, note if key is "KEY" or "key" or "Key"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * they are each considered distinct and not duplicates.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param values must be a valid set of inputs. Must be valid in the sense
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * that each of its values are like [somekey]=somevalue
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster *
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return true if set is good and contains no duplicate keys
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster */
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster static boolean checkForNoDuplicateKeyInValue(Set values) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster boolean valid = true;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster HashSet keySet = new HashSet();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((values != null) && !values.isEmpty()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (Iterator i = values.iterator(); (i.hasNext() && valid);) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String str = ((String)i.next()).trim();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (str.length() > 0) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //extract key from whole value
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int startIndex = str.indexOf("[");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //global values do not have brackets, so dont check
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //for key if no starting bracket, else extract key and
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //check if it is a duplicate of key already in keySet
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if(startIndex != -1) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int endIndex = str.indexOf("]");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster str=str.substring(startIndex+1, endIndex).trim();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (keySet.add(str) == false) valid=false;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster return valid;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster }
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster}