8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
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 * You can obtain a copy of the License at
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * https://opensso.dev.java.net/public/CDDLv1.0.html or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * See the License for the specific language governing
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * permission and limitations under the License.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * When distributing Covered Code, include this CDDL
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Header Notice in each file and include the License file
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 * $Id: IDRepoResponseProvider.java,v 1.4 2008/06/25 05:43:51 qcheng Exp $
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Portions Copyrighted [2011] [ForgeRock AS]
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterimport com.sun.identity.policy.interfaces.ResponseProvider;
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This class is an out of the box implementation of
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <code>ResponseProvider</code> interface. It defines 2 types of user
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * attributes which it can fetch the values of: <code>STATIC</code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * and <code>DYNAMIC</code>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * It relies on underlying Identity repository service to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * fetch the attribute values for the Subject(s) defined in the policy.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * It computes a <code>Map</code> of response attributes
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * based on the sso token, resource name and <code>env</code> map passed
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * in the method call <code>getResponseDecision()</code>.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Policy framework would make a call to the ResponseProvider to fetch
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * response attributes in a policy only if the policy is applicable to a
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * request as determined by sso token, resource name, Subjects and Conditions.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Fosterpublic class IDRepoResponseProvider implements ResponseProvider {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster = Debug.getInstance(PolicyManager.POLICY_DEBUG_NAME);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final String STATIC_ATTRIBUTE = "StaticAttribute";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final String DYNAMIC_ATTRIBUTE = "DynamicAttribute";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final String ATTR_DELIMITER = "=";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public static final String VAL_DELIMITER = "|";
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private static List propertyNames = new ArrayList(2);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Set responseAttrNames = null; //for dynamic attributes
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private Set repoAttrNames = null; //for dynamic attributes
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * No argument constructor.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Initialize the IDRepoResponseProvider object by using the configuration
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * information passed by the Policy Framework.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param configParams the configuration information
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @exception PolicyException if an error occured during
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * initialization of the instance
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void initialize(Map configParams) throws PolicyException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.initialize():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "entering");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throw (new PolicyException(ResBundleUtils.rbName,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // get the organization name
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((orgNameSet != null) && (!orgNameSet.isEmpty())) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.initialize():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "initialized with:"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + ",validDynamicAttrNames=" + validDynamicAttrNames);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns a list of property names for the responseprovider.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return <code>List</code> of property names
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns the syntax for a property name
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @see com.sun.identity.policy.Syntax
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param property property name
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return <code>Syntax<code> for the property name
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public Syntax getPropertySyntax(String property) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Gets the display name for the property name.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The <code>locale</code> variable could be used by the plugin to
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * customize the display name for the given locale.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * The <code>locale</code> variable could be <code>null</code>, in which
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * case the plugin must use the default locale.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param property property name
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param locale locale for which the property name must be customized
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return display name for the property name.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws PolicyException
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public String getDisplayName(String property, Locale locale)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns a set of valid values given the property name. This method
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * is called if the property Syntax is either the SINGLE_CHOICE or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * MULTIPLE_CHOICE.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param property property name
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * from the PolicyConfig Service configured for the specified realm.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return Set of valid values for the property.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @exception PolicyException if unable to get the Syntax.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public Set getValidValues(String property) throws PolicyException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throw (new PolicyException(ResBundleUtils.rbName,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "idrepo_response_provider_not_yet_initialized", null, null));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Sets the properties of the responseProvider plugin.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This influences the response attribute-value Map that would be
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * computed by a call to method <code>getResponseDecision(Map)</code>
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * These attribute-value pairs are encapsulated in
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <code>ResponseAttribute</code> element tag which is a child of the
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * <code>PolicyDecision</code> element in the PolicyResponse xml
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * if the policy is applicable to the user for the resource, subject and
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * conditions defined.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param properties the properties of the responseProvider
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Keys of the properties have to be String.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Value corresponding to each key have to be a Set of String
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * elements. Each implementation of ResponseProvider could add
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * further restrictions on the keys and values of this map.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws PolicyException for any abnormal condition
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster public void setProperties(Map properties) throws PolicyException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.setProperties():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ( (properties == null) || ( properties.isEmpty()) ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ResBundleUtils.rbName, "properties_can_not_be_null_or_empty",
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //Check if the keys needed for this provider are present namely
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // STATIC_ATTRIBUTE and DYNAMIC_ATTRIBUTE
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (!properties.containsKey(STATIC_ATTRIBUTE) &&
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String args[] = { STATIC_ATTRIBUTE,DYNAMIC_ATTRIBUTE };
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ResBundleUtils.rbName, "missing_required_property",
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //validates STATIC_ATTRIBUTE and caches parsed static attributes map
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set staticSet = (Set)properties.get(STATIC_ATTRIBUTE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster //validates DYNAMIC_ATTRIBUTE and caches parsed
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // responseAttrNames, repoAttrNames, responseAttrToRepoAttr
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set dynamicSet = (Set)properties.get(DYNAMIC_ATTRIBUTE);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.setProperties():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "returning");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /** Gets the properties of the responseprovider
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return properties of the responseprovider
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @see #setProperties
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster ? null : Collections.unmodifiableMap(properties);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Gets the response attributes computed by this ResponseProvider object,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * based on the sso token and map of environment parameters
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param token single-sign-on token of the user
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @param env specific environment map of key/value pairs
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return a Map of response attributes.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Keys of the Map are attribute names STATIC_ATTRIBUTE or
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * DYNAMIC_ATTRIBUTE.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Value is a Set of Strings representing response attribute
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws PolicyException if the decision could not be computed
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @throws SSOException if SSO token is not valid
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Map env) throws PolicyException, SSOException {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.getResponseDecision():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "entering");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "getResponseDecision():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PolicyUtils.appendMapToMap(staticResponse, returnValues);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((repoAttrNames != null) && !repoAttrNames.isEmpty()) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (Iterator iter = responseAttrNames.iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (Iterator iter1 = idRepoAttrNames.iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "getResponseDecision():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "adding dynamicResponse=" + dynamicResponse);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PolicyUtils.appendMapToMap(dynamicResponse,returnValues);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "getResponseDecision(): Principal is null");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throw (new PolicyException(ResBundleUtils.rbName,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "getResponseDecision():" +"IdRepoException", ide);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.getResponseDecision():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This method validates the STATIC_ATTRIBUTE data
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * for format and caches parsed static attributes map
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Needs to be in "attr=val" format.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Else, throws PolicyException
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void validateStaticAttribute(Set staticSet)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.validateStaticAttribute():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster for (Iterator it = staticSet.iterator(); it.hasNext();) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if (attrValueString.indexOf(ATTR_DELIMITER) == -1 ) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + ".validateStaticAttribute():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + " Invalid format in defining StaticAttribute, needs"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + " to be attr=value format");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster throw new PolicyException(ResBundleUtils.rbName,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster int index = attrValueString.indexOf(ATTR_DELIMITER);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String attrName = attrValueString.substring(0,index).trim();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String attrValue = attrValueString.substring(index+1);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set values = PolicyUtils.delimStringToSet(attrValue,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster PolicyUtils.appendElementToMap(attrName, values,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "validateStaticAttribute():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "validateStaticAttribute():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "caching staticResponse:"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.validateStaticAttribute():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "returning");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * This method validates the DYNAMIC_ATTRIBUTE data
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * for format and caches parsed
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * responseAttrNames, repoAttrNames
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Strings in the Set need to be in "responseAttr=repoAttr" format
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Else, throws PolicyException
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void validateDynamicAttribute(Set dynamicSet)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.validateDynamicAttribute():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster /* check if the attribute names being set in DYNAMIC_ATTRIBUTE
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * are valid i.e are as defined in policy config service.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Parse and store responseAttrNames and repoAttrNames
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.validateDynamicAttribute():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster +"valid dynamic attributes:" + validDynamicAttrNames);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Set dynamicAttrs = ((Set)properties.get(DYNAMIC_ATTRIBUTE));
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.validateDynamicAttribute():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster +"selected dynamic attributes:" + dynamicAttrs);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Iterator dynamicAttrsIter = dynamicAttrs.iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String attr = (String) dynamicAttrsIter.next();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster +"validateDynamicAttribute():Invalid dynamic property "
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster String[] attrNames = parseDynamicAttrName(attr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster addToResponseAttrToRepoAttrMap(responseAttrName, repoAttrName);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "validateDynamicAttribute():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.validateDynamicAttribute():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "responseAttrToRepoAttr=" + responseAttrToRepoAttr);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster DEBUG.message("IDRepoResponseProvider.validateDynamicAttribute():"
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster + "returning");
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private String[] parseDynamicAttrName(String dynamicAttrName)
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "invalid_dynamic_property_being_set", args, null);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "invalid_dynamic_property_being_set", args, null);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster = dynamicAttrName.substring(0, delimiterIndex).trim();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster = dynamicAttrName.substring(delimiterIndex + 1).trim();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster if ((value1.length() == 0) || (value2.length() == 0)) {
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster "invalid_dynamic_property_being_set", args, null);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster private void addToResponseAttrToRepoAttrMap(String responseAttrName,
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster = (Set)responseAttrToRepoAttr.get(responseAttrName);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster responseAttrToRepoAttr.put(responseAttrName, idRepoAttrNames);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * Returns a copy of this object.
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster * @return a copy of this object
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster theClone = (IDRepoResponseProvider)super.clone();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster // this should never happen
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster theClone.validDynamicAttrNames = new HashSet();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster theClone.validDynamicAttrNames.addAll(validDynamicAttrNames);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Iterator iter = properties.keySet().iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Iterator iter = staticResponse.keySet().iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster theClone.responseAttrNames.addAll(responseAttrNames);
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster theClone.responseAttrToRepoAttr = new HashMap();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster Iterator iter = responseAttrToRepoAttr.keySet().iterator();
8af80418ba1ec431c8027fa9668e5678658d3611Allan Foster values.addAll((Set) responseAttrToRepoAttr.get(obj));