/**
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright (c) 2009 Sun Microsystems Inc. All Rights Reserved
*
* The contents of this file are subject to the terms
* of the Common Development and Distribution License
* (the License). You may not use this file except in
* compliance with the License.
*
* You can obtain a copy of the License at
* https://opensso.dev.java.net/public/CDDLv1.0.html or
* opensso/legal/CDDLv1.0.txt
* See the License for the specific language governing
* permission and limitations under the License.
*
* When distributing Covered Code, include this CDDL
* Header Notice in each file and include the License file
* at opensso/legal/CDDLv1.0.txt.
* If applicable, add the following below the CDDL Header,
* with the fields enclosed by brackets [] replaced by
* your own identifying information:
* "Portions Copyrighted [year] [name of copyright owner]"
*
* $Id: AttributeLookupCondition.java,v 1.1 2009/08/19 05:40:32 veiming Exp $
*/
/*
* Portions Copyrighted 2014-2015 ForgeRock AS.
*/
package com.sun.identity.entitlement;
import org.forgerock.openam.utils.StringUtils;
import org.json.JSONException;
import org.json.JSONObject;
import javax.security.auth.Subject;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* This condition evaluates if a given attribute from subject matches with
* the one in resource.
*/
public class AttributeLookupCondition extends EntitlementConditionAdaptor {
/**
* User Macro
*/
public static final String MACRO_USER = "$USER";
/**
* Resource Macro
*/
public static final String MACRO_RESOURCE = "$RES";
private String key;
private String value;
private String pConditionName = "";
/**
* Constructor.
*/
public AttributeLookupCondition() {
}
/**
* Constructor.
*
* @param key Matching key.
* @param value Matching value.
*/
public AttributeLookupCondition(String key, String value) {
this.key = key;
this.value = value;
}
/**
* Sets state of the object
*
* @param state State of the object encoded as string
*/
public void setState(String state) {
try {
JSONObject jo = new JSONObject(state);
setState(jo);
key = jo.optString("key");
value = jo.optString("value");
pConditionName = jo.optString("pConditionName");
} catch (JSONException e) {
PrivilegeManager.debug.error("AttributeLookupCondition.setState",e);
}
}
/**
* Returns state of the object.
*
* @return state of the object encoded as string.
*/
public String getState() {
return toString();
}
/**
* Returns ConditionDecision
of
* EntitlementCondition
evaluation.
*
* @param realm Realm name.
* @param subject EntitlementCondition who is under evaluation.
* @param resourceName Resource name.
* @param environment Environment parameters.
* @return ConditionDecision
of
* EntitlementCondition
evaluation
* @throws EntitlementException if error occurs.
*/
public ConditionDecision evaluate(
String realm,
Subject subject,
String resourceName,
Map> environment)
throws EntitlementException {
String evalKey = null;
// e.g. $USER.postaladdress;
int idxUserMacro = key.indexOf(MACRO_USER);
if (idxUserMacro != -1) {
String attrName = key.substring(MACRO_USER.length() +1);
evalKey = getAttributeFromSubject(subject, attrName);
} else {
evalKey = key;
}
// e.g. $RES.postaladdress;
String searchKey = value.replace(MACRO_RESOURCE, resourceName);
Set evalValues = environment.get(searchKey);
String evalVal = ((evalValues == null) || evalValues.isEmpty()) ?
null : (String)evalValues.iterator().next();
if ((evalKey == null) && (evalVal != null)) {
return getFailedDecision(key, evalVal);
} else if ((evalVal == null) && (evalKey != null)) {
return getFailedDecision(value, evalKey);
} else if ((evalVal == null) && (evalKey == null)) {
return getFailedDecision(key, value);
}
return new ConditionDecision(
evalValues.contains(evalKey), Collections.>emptyMap());
}
private ConditionDecision getFailedDecision(String prefix, String suffix) {
Map> advices = new HashMap>();
Set set = new HashSet();
set.add(prefix + "=" + suffix);
advices.put(getClass().getName(), set);
return new ConditionDecision(false, advices);
}
private String getAttributeFromSubject(Subject subject, String attrName) {
Set publicCreds = subject.getPublicCredentials();
String attrValue = null;
for (Iterator i = publicCreds.iterator();
i.hasNext() && (attrValue == null); ) {
Object o = i.next();
if (o instanceof String) {
String v = (String)o;
if (v.startsWith(attrName + "=")) {
attrValue = v.substring(attrName.length() + 1);
}
}
}
return attrValue;
}
/**
* Returns matching key.
*
* @return matching key.
*/
public String getKey() {
return key;
}
/**
* Returns OpenAM policy Condition name.
*
* @return subject name as used in OpenAM policy,
* this is relevant only when UserECondition was created from
* OpenAM policy Condition.
*/
public String getPConditionName() {
return pConditionName;
}
/**
* Returns matching value.
*
* @return matching value.
*/
public String getValue() {
return value;
}
/**
* Sets matching key.
*
* @param key Matching key.
*/
public void setKey(String key) {
this.key = key;
}
/**
* Sets OpenAM policy Condition name
* @param pConditionName subject name as used in OpenAM policy,
* this is relevant only when UserECondition was created from
* OpenAM policy Condition.
*/
public void setPConditionName(String pConditionName) {
this.pConditionName = pConditionName;
}
/**
* Set matching value.
* @param value Matching value.
*/
public void setValue(String value) {
this.value = value;
}
/**
* Returns JSONObject mapping of the object.
*
* @return JSONObject mapping of the object.
*/
public JSONObject toJSONObject() throws JSONException {
JSONObject jo = new JSONObject();
toJSONObject(jo);
jo.put("key", key);
jo.put("value", value);
jo.put("pConditionName", pConditionName);
return jo;
}
/**
* Returns true
if the passed in object is equal to this object
* @param obj object to check for equality
* @return true
if the passed in object is equal to this object
*/
@Override
public boolean equals(Object obj) {
if (!super.equals(obj)) {
return false;
}
if (!getClass().equals(obj.getClass())) {
return false;
}
AttributeLookupCondition object = (AttributeLookupCondition) obj;
if (key == null) {
if (object.key != null) {
return false;
}
} else {
if (!key.equals(object.key)) {
return false;
}
}
if (value == null) {
if (object.value != null) {
return false;
}
} else {
if (!value.equals(object.value)) {
return false;
}
}
if (pConditionName == null) {
if (object.pConditionName != null) {
return false;
}
} else {
if (!pConditionName.equals(object.pConditionName)) {
return false;
}
}
return true;
}
/**
* Returns hash code of the object.
*
* @return hash code of the object.
*/
@Override
public int hashCode() {
int code = super.hashCode();
if (key != null) {
code = 31*code + key.hashCode();
}
if (value != null) {
code = 31*code + value.hashCode();
}
if (pConditionName != null) {
code = 31*code + pConditionName.hashCode();
}
return code;
}
/**
* Returns string representation of the object.
*
* @return string representation of the object.
*/
@Override
public String toString() {
String s = null;
try {
s = toJSONObject().toString(2);
} catch (JSONException e) {
PrivilegeManager.debug.error("AttributeLookupCondition.setState",e);
}
return s;
}
@Override
public void validate() throws EntitlementException {
if (StringUtils.isBlank(key)) {
throw new EntitlementException(EntitlementException.PROPERTY_VALUE_NOT_DEFINED, "key");
}
if (value == null) {
throw new EntitlementException(EntitlementException.PROPERTY_VALUE_NOT_DEFINED, "value");
}
}
}