View Javadoc
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 }