1 /*
2  * Copyright (C) 2014 jsonwebtoken.io
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package io.jsonwebtoken.impl;
17
18 import io.jsonwebtoken.lang.Assert;
19
20 import java.util.Collection;
21 import java.util.Date;
22 import java.util.LinkedHashMap;
23 import java.util.Map;
24 import java.util.Set;
25
26 public class JwtMap implements Map<String,Object> {
27
28     private final Map<String, Object> map;
29
30     public JwtMap() {
31         this(new LinkedHashMap<String, Object>());
32     }
33
34     public JwtMap(Map<String, Object> map) {
35         Assert.notNull(map, "Map argument cannot be null.");
36         this.map = map;
37     }
38
39     protected String getString(String name) {
40         Object v = get(name);
41         return v != null ? String.valueOf(v) : null;
42     }
43
44     protected static Date toDate(Object v, String name) {
45         if (v == null) {
46             return null;
47         } else if (v instanceof Date) {
48             return (Date) v;
49         } else if (v instanceof Number) {
50             // https://github.com/jwtk/jjwt/issues/122:
51             // The JWT RFC *mandates* NumericDate values are represented as seconds.
52             // Because Because java.util.Date requires milliseconds, we need to multiply by 1000:
53             long seconds = ((Number) v).longValue();
54             long millis = seconds * 1000;
55             return new Date(millis);
56         } else if (v instanceof String) {
57             // https://github.com/jwtk/jjwt/issues/122
58             // The JWT RFC *mandates* NumericDate values are represented as seconds.
59             // Because Because java.util.Date requires milliseconds, we need to multiply by 1000:
60             long seconds = Long.parseLong((String) v);
61             long millis = seconds * 1000;
62             return new Date(millis);
63         } else {
64             throw new IllegalStateException("Cannot convert '" + name + "' value [" + v + "] to Date instance.");
65         }
66     }
67
68     protected void setValue(String name, Object v) {
69         if (v == null) {
70             map.remove(name);
71         } else {
72             map.put(name, v);
73         }
74     }
75
76     protected Date getDate(String name) {
77         Object v = map.get(name);
78         return toDate(v, name);
79     }
80
81     protected void setDate(String name, Date d) {
82         if (d == null) {
83             map.remove(name);
84         } else {
85             long seconds = d.getTime() / 1000;
86             map.put(name, seconds);
87         }
88     }
89
90     @Override
91     public int size() {
92         return map.size();
93     }
94
95     @Override
96     public boolean isEmpty() {
97         return map.isEmpty();
98     }
99
100     @Override
101     public boolean containsKey(Object o) {
102         return map.containsKey(o);
103     }
104
105     @Override
106     public boolean containsValue(Object o) {
107         return map.containsValue(o);
108     }
109
110     @Override
111     public Object get(Object o) {
112         return map.get(o);
113     }
114
115     @Override
116     public Object put(String s, Object o) {
117         if (o == null) {
118             return map.remove(s);
119         } else {
120             return map.put(s, o);
121         }
122     }
123
124     @Override
125     public Object remove(Object o) {
126         return map.remove(o);
127     }
128
129     @SuppressWarnings("NullableProblems")
130     @Override
131     public void putAll(Map<? extends String, ?> m) {
132         if (m == null) {
133             return;
134         }
135         for (String s : m.keySet()) {
136             map.put(s, m.get(s));
137         }
138     }
139
140     @Override
141     public void clear() {
142         map.clear();
143     }
144
145     @Override
146     public Set<String> keySet() {
147         return map.keySet();
148     }
149
150     @Override
151     public Collection<Object> values() {
152         return map.values();
153     }
154
155     @Override
156     public Set<Entry<String, Object>> entrySet() {
157         return map.entrySet();
158     }
159
160     @Override
161     public String toString() {
162         return map.toString();
163     }
164
165     @Override
166     public int hashCode() {
167         return map.hashCode();
168     }
169
170     @Override
171     public boolean equals(Object obj) {
172         return map.equals(obj);
173     }
174 }
175