001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2016, Connect2id Ltd and contributors. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.openid.connect.sdk.federation.policy.operations; 019 020 021import java.util.AbstractMap; 022import java.util.List; 023import java.util.Map; 024 025import net.minidev.json.JSONObject; 026 027import com.nimbusds.oauth2.sdk.ParseException; 028import com.nimbusds.oauth2.sdk.util.JSONUtils; 029import com.nimbusds.openid.connect.sdk.federation.policy.language.*; 030 031 032/** 033 * Values set (value) operation. 034 * 035 * <p>Example policy: 036 * 037 * <pre> 038 * "require_auth_time" : { "value": true } 039 * </pre> 040 * 041 * <p>Input: 042 * 043 * <pre> 044 * "require_auth_time" : false 045 * </pre> 046 * 047 * <p>Result: 048 * 049 * <pre> 050 * "require_auth_time" : true 051 * </pre> 052 * 053 * <p>Related specifications: 054 * 055 * <ul> 056 * <li>OpenID Connect Federation 1.0, section 4.1.5. 057 * </ul> 058 */ 059public class ValueOperation implements PolicyOperation, 060 BooleanConfiguration, NumberConfiguration, StringConfiguration, StringListConfiguration, JSONObjectConfiguration, 061 UntypedOperation { 062 063 064 public static final OperationName NAME = new OperationName("value"); 065 066 067 private ConfigurationType configType; 068 069 070 private boolean booleanValue; 071 072 073 private Number numberValue = null; 074 075 076 private String stringValue; 077 078 079 private List<String> stringListValue; 080 081 082 private JSONObject jsonObjectValue; 083 084 085 @Override 086 public OperationName getOperationName() { 087 return NAME; 088 } 089 090 091 @Override 092 public void configure(final boolean parameter) { 093 configType = ConfigurationType.BOOLEAN; 094 this.booleanValue = parameter; 095 } 096 097 098 @Override 099 public void configure(final Number parameter) { 100 configType = ConfigurationType.NUMBER; 101 this.numberValue = parameter; 102 } 103 104 105 @Override 106 public void configure(final String parameter) { 107 configType = ConfigurationType.STRING; 108 this.stringValue = parameter; 109 } 110 111 112 @Override 113 public void configure(final List<String> parameter) { 114 configType = ConfigurationType.STRING_LIST; 115 this.stringListValue = parameter; 116 } 117 118 119 @Override 120 public void configure(final JSONObject parameter) { 121 configType = ConfigurationType.JSON_OBJECT; 122 this.jsonObjectValue = parameter; 123 } 124 125 126 @Override 127 public void parseConfiguration(final Object jsonEntity) throws ParseException { 128 if (jsonEntity instanceof Boolean) { 129 configure(JSONUtils.toBoolean(jsonEntity)); 130 } else if (jsonEntity instanceof Number) { 131 configure(JSONUtils.toNumber(jsonEntity)); 132 } else if (jsonEntity instanceof String) { 133 configure(JSONUtils.toString(jsonEntity)); 134 } else if (jsonEntity instanceof JSONObject) { 135 configure(JSONUtils.to(jsonEntity, JSONObject.class)); 136 } else { 137 configure(JSONUtils.toStringList(jsonEntity)); 138 } 139 } 140 141 142 @Override 143 public Map.Entry<String,Object> toJSONObjectEntry() { 144 if (configType == null) { 145 throw new IllegalStateException("The policy is not initialized"); 146 } 147 Object value; 148 if (configType.equals(ConfigurationType.BOOLEAN)) { 149 value = getBooleanConfiguration(); 150 } else if (configType.equals(ConfigurationType.NUMBER)) { 151 value = getNumberConfiguration(); 152 } else if (configType.equals(ConfigurationType.STRING)) { 153 value = getStringConfiguration(); 154 } else if (configType.equals(ConfigurationType.STRING_LIST)) { 155 value = getStringListConfiguration(); 156 } else if (configType.equals(ConfigurationType.JSON_OBJECT)) { 157 value = getJSONObjectConfiguration(); 158 } else { 159 throw new IllegalStateException("Unsupported configuration type: " + configType); 160 } 161 return new AbstractMap.SimpleImmutableEntry<>(getOperationName().getValue(), value); 162 } 163 164 165 @Override 166 public boolean getBooleanConfiguration() { 167 return booleanValue; 168 } 169 170 171 @Override 172 public Number getNumberConfiguration() { 173 return numberValue; 174 } 175 176 177 @Override 178 public String getStringConfiguration() { 179 return stringValue; 180 } 181 182 183 @Override 184 public List<String> getStringListConfiguration() { 185 return stringListValue; 186 } 187 188 189 @Override 190 public JSONObject getJSONObjectConfiguration() { 191 return jsonObjectValue; 192 } 193 194 195 @Override 196 public PolicyOperation merge(final PolicyOperation other) 197 throws PolicyViolationException { 198 199 ValueOperation otherTyped = Utils.castForMerge(other, ValueOperation.class); 200 201 if (configType == null || otherTyped.configType == null) { 202 throw new PolicyViolationException("The value operation is not initialized"); 203 } 204 205 if (configType.equals(ConfigurationType.STRING_LIST)) { 206 207 if (getStringListConfiguration() != null && getStringListConfiguration().equals(otherTyped.getStringListConfiguration())) { 208 ValueOperation copy = new ValueOperation(); 209 copy.configure(getStringListConfiguration()); 210 return copy; 211 } 212 } 213 214 if (configType.equals(ConfigurationType.STRING)) { 215 216 if (getStringConfiguration() != null && getStringConfiguration().equals(otherTyped.getStringConfiguration())) { 217 ValueOperation copy = new ValueOperation(); 218 copy.configure(getStringConfiguration()); 219 return copy; 220 } 221 } 222 223 if (configType.equals(ConfigurationType.BOOLEAN)) { 224 225 if (getBooleanConfiguration() == otherTyped.getBooleanConfiguration()) { 226 ValueOperation copy = new ValueOperation(); 227 copy.configure(getBooleanConfiguration()); 228 return copy; 229 } 230 } 231 232 if (configType.equals(ConfigurationType.NUMBER)) { 233 234 if (getNumberConfiguration() != null && getNumberConfiguration().equals(otherTyped.getNumberConfiguration())) { 235 ValueOperation copy = new ValueOperation(); 236 copy.configure(getNumberConfiguration()); 237 return copy; 238 } 239 } 240 241 if (configType.equals(ConfigurationType.JSON_OBJECT)) { 242 243 if (getJSONObjectConfiguration() == otherTyped.getJSONObjectConfiguration()) { 244 ValueOperation copy = new ValueOperation(); 245 copy.configure(getJSONObjectConfiguration()); 246 return copy; 247 } 248 } 249 250 throw new PolicyViolationException("Value mismatch"); 251 } 252 253 254 @Override 255 public Object apply(final Object value) { 256 257 if (configType == null) { 258 throw new IllegalStateException("The policy is not initialized"); 259 } 260 261 if (configType.equals(ConfigurationType.BOOLEAN)) { 262 return booleanValue; 263 } 264 if (configType.equals(ConfigurationType.NUMBER)) { 265 return numberValue; 266 } 267 if (configType.equals(ConfigurationType.STRING)) { 268 return stringValue; 269 } 270 if (configType.equals(ConfigurationType.JSON_OBJECT)) { 271 return jsonObjectValue; 272 } 273 return stringListValue; 274 } 275}