001 package com.nimbusds.jose;
002
003
004 import java.text.ParseException;
005
006 import java.util.Collections;
007 import java.util.HashSet;
008 import java.util.Set;
009
010 import net.minidev.json.JSONObject;
011
012 import com.nimbusds.jose.util.Base64URL;
013 import com.nimbusds.jose.util.JSONObjectUtils;
014
015
016 /**
017 * Plaintext JOSE header.
018 *
019 * <p>Supports all {@link #getReservedParameterNames reserved header parameters}
020 * of the plain specification:
021 *
022 * <ul>
023 * <li>alg (set to {@link Algorithm#NONE "none"}).
024 * <li>typ
025 * <li>cty
026 * </ul>
027 *
028 * <p>The header may also carry {@link #setCustomParameters custom parameters};
029 * these will be serialised and parsed along the reserved ones.
030 *
031 * <p>Example:
032 *
033 * <pre>
034 * {
035 * "alg" : "none"
036 * }
037 * </pre>
038 *
039 * @author Vladimir Dzhuvinov
040 * @version $version$ (2013-01-08)
041 */
042 public class PlainHeader extends Header implements ReadOnlyPlainHeader {
043
044
045 /**
046 * The reserved parameter names.
047 */
048 private static final Set<String> RESERVED_PARAMETER_NAMES;
049
050
051 /**
052 * Initialises the reserved parameter name set.
053 */
054 static {
055 Set<String> p = new HashSet<String>();
056
057 p.add("alg");
058 p.add("typ");
059 p.add("cty");
060
061 RESERVED_PARAMETER_NAMES = Collections.unmodifiableSet(p);
062 }
063
064
065 /**
066 * Creates a new plain header with algorithm
067 * {@link Algorithm#NONE none}.
068 */
069 public PlainHeader() {
070
071 super(Algorithm.NONE);
072 }
073
074
075 /**
076 * Gets the reserved parameter names for plain headers.
077 *
078 * @return The reserved parameter names, as an unmodifiable set.
079 */
080 public static Set<String> getReservedParameterNames() {
081
082 return RESERVED_PARAMETER_NAMES;
083 }
084
085
086 @Override
087 public Algorithm getAlgorithm() {
088
089 return alg;
090 }
091
092
093 /**
094 * @throws IllegalArgumentException If the specified parameter name
095 * matches a reserved parameter name.
096 */
097 @Override
098 public void setCustomParameter(final String name, final Object value) {
099
100 if (getReservedParameterNames().contains(name))
101 throw new IllegalArgumentException("The parameter name \"" + name + "\" matches a reserved name");
102
103 super.setCustomParameter(name, value);
104 }
105
106
107 @Override
108 public Set<String> getIncludedParameters() {
109
110 Set<String> includedParameters =
111 new HashSet<String>(getCustomParameters().keySet());
112
113 includedParameters.add("alg");
114
115 if (getType() != null)
116 includedParameters.add("typ");
117
118 if (getContentType() != null)
119 includedParameters.add("cty");
120
121 return includedParameters;
122 }
123
124
125 /**
126 * Parses a plain header from the specified JSON object.
127 *
128 * @param json The JSON object to parse. Must not be {@code null}.
129 *
130 * @return The plain header.
131 *
132 * @throws ParseException If the specified JSON object doesn't represent
133 * a valid plain header.
134 */
135 public static PlainHeader parse(final JSONObject json)
136 throws ParseException {
137
138 // Get the "alg" parameter
139 Algorithm alg = Header.parseAlgorithm(json);
140
141 if (alg != Algorithm.NONE)
142 throw new ParseException("The algorithm \"alg\" header parameter must be \"none\"", 0);
143
144
145 // Create a minimal header, type may be set later
146 PlainHeader h = new PlainHeader();
147
148
149 // Parse optional + custom parameters
150 for(final String name: json.keySet()) {
151
152 if (name.equals("alg"))
153 continue; // skip
154
155 else if (name.equals("typ"))
156 h.setType(new JOSEObjectType(JSONObjectUtils.getString(json, name)));
157
158 else if (name.equals("cty"))
159 h.setContentType(JSONObjectUtils.getString(json, name));
160
161 else
162 h.setCustomParameter(name, json.get(name));
163 }
164
165 return h;
166 }
167
168
169 /**
170 * Parses a plain header from the specified JSON string.
171 *
172 * @param s The JSON string to parse. Must not be {@code null}.
173 *
174 * @return The plain header.
175 *
176 * @throws ParseException If the specified JSON string doesn't
177 * represent a valid plain header.
178 */
179 public static PlainHeader parse(final String s)
180 throws ParseException {
181
182 JSONObject jsonObject = JSONObjectUtils.parseJSONObject(s);
183
184 return parse(jsonObject);
185 }
186
187
188 /**
189 * Parses a plain header from the specified Base64URL.
190 *
191 * @param base64URL The Base64URL to parse. Must not be {@code null}.
192 *
193 * @return The plain header.
194 *
195 * @throws ParseException If the specified Base64URL doesn't represent a
196 * valid plain header.
197 */
198 public static PlainHeader parse(final Base64URL base64URL)
199 throws ParseException {
200
201 if (base64URL == null)
202 throw new ParseException("The Base64URL must not be null", 0);
203
204 return parse(base64URL.decodeToString());
205 }
206 }