1 /* 2 * The contents of this file are subject to the terms of the Common Development and 3 * Distribution License (the License). You may not use this file except in compliance with the 4 * License. 5 * 6 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 7 * specific language governing permission and limitations under the License. 8 * 9 * When distributing Covered Software, include this CDDL Header Notice in each file and include 10 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 11 * Header, with the fields enclosed by brackets [] replaced by your own identifying 12 * information: "Portions copyright [year] [name of copyright owner]". 13 * 14 * Copyright 2013-2017 ForgeRock AS. 15 */ 16 17 package org.forgerock.json.jose.jwt; 18 19 import java.util.LinkedHashMap; 20 import java.util.List; 21 import java.util.Map; 22 import java.util.Set; 23 24 import org.forgerock.json.JsonValue; 25 import org.forgerock.json.jose.exceptions.JwtRuntimeException; 26 import org.forgerock.json.jose.utils.Utils; 27 28 /** 29 * A base implementation class for a JSON Web object. 30 * <p> 31 * Provides a set of methods which are common across JWT, JWS, JWE and JWK implementations. 32 * 33 * @since 2.0.0 34 */ 35 public abstract class JWObject { 36 37 private final JsonValue jsonValue; 38 39 /** 40 * Constructs a new, empty JWObject. 41 */ 42 public JWObject() { 43 this.jsonValue = new JsonValue(new LinkedHashMap<>()); 44 } 45 46 /** 47 * Checks that the given value is of an assignable type from the required class. 48 * <p> 49 * Will throw a JwtRuntimeException if the value is not of the required type 50 * 51 * @param value The value to check is of the required type. 52 * @param requiredClazz The class of the required type. 53 * @see #isValueOfType(Object, Class) 54 */ 55 protected void checkValueIsOfType(Object value, Class<?> requiredClazz) { 56 if (!requiredClazz.isAssignableFrom(value.getClass())) { 57 throw new JwtRuntimeException("Value is not of the required type. Required, " + requiredClazz.getName() 58 + ", actual, " + value.getClass().getName()); 59 } 60 } 61 62 /** 63 * Checks that the given List's type is of an assignable type from the required class. 64 * <p> 65 * Will throw a JwtRuntimeException if the value is not of the required type 66 * 67 * @param value The List to check the type is of the required type. 68 * @param requiredClazz The class of the required type. 69 * @see #checkValueIsOfType(Object, Class) 70 */ 71 protected void checkListValuesAreOfType(List<?> value, Class<?> requiredClazz) { 72 if (value.size() > 0) { 73 checkValueIsOfType(value.get(0), requiredClazz); 74 } 75 } 76 77 /** 78 * Checks to see if the given value is of an assignable type from the required class. 79 * 80 * @param value The value to check is of the required type. 81 * @param requiredClazz The class of the required type. 82 * @return <code>true</code> if the value if of the required type. 83 * @see #checkValueIsOfType(Object, Class) 84 */ 85 protected boolean isValueOfType(Object value, Class<?> requiredClazz) { 86 return requiredClazz.isAssignableFrom(value.getClass()); 87 } 88 89 /** 90 * Sets or removes the value of the specified member. 91 * <p> 92 * If the value is not null, then the value is set as the value of the given key. 93 * <p> 94 * Otherwise, if the value is null and the key already exist with a value assigned to it, then the key and its value 95 * will be removed. If the specified key is not defined, calling this method has no effect. 96 * 97 * @param key the {@code Map} key identifying the value to set or to remove. 98 * @param value the object value to assign to the member. 99 */ 100 public void put(String key, Object value) { 101 if (value != null) { 102 jsonValue.put(key, value); 103 } else if (jsonValue.isDefined(key)) { 104 jsonValue.remove(key); 105 } 106 } 107 108 /** 109 * Returns the specified item value. If no such member value exists, then a JSON value containing {@code null} is 110 * returned. 111 * 112 * @param key the {@code Map} key identifying the item to return. 113 * @return a JSON value containing the value or {@code null}. 114 */ 115 public JsonValue get(String key) { 116 return jsonValue.get(key); 117 } 118 119 /** 120 * Returns {@code true} if this JWObject contains the specified item. 121 * 122 * @param key the {@code Map} key of the item to seek. 123 * @return {@code true} if this JSON value contains the specified member. 124 */ 125 public boolean isDefined(String key) { 126 return jsonValue.isDefined(key); 127 } 128 129 /** 130 * Returns the set of keys for this JWObject's values. 131 * <p> 132 * The order of the resulting keys is undefined. If there are no values set, this method returns an empty set. 133 * 134 * @return A Set of keys. 135 */ 136 public Set<String> keys() { 137 return jsonValue.keys(); 138 } 139 140 /** 141 * Returns the {@code Map} of keys and values stored by {@link #put}. 142 * 143 * @return {@code Map} of this JWObject's keys and values. 144 */ 145 Map<String, Object> getAll() { 146 return jsonValue.asMap(); 147 } 148 149 /** 150 * Returns a string representation of the JWObject. The result is guaranteed to be valid JSON object syntax. 151 * 152 * @return A JSON String representation. 153 */ 154 @Override 155 public String toString() { 156 return Utils.writeJsonObject(jsonValue.asMap()); 157 } 158 159 /** 160 * Returns a json representation of the JWObject. 161 * 162 * @return A JSON representation. 163 */ 164 public JsonValue toJsonValue() { 165 return jsonValue.copy(); 166 } 167 }