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 }