1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.ws.security.message.token;
21
22 import org.apache.ws.security.WSConstants;
23 import org.apache.ws.security.WSSecurityException;
24 import org.apache.ws.security.util.DOM2Writer;
25 import org.apache.ws.security.util.DateUtil;
26 import org.apache.ws.security.util.WSSecurityUtil;
27 import org.apache.ws.security.util.XmlSchemaDateFormat;
28 import org.w3c.dom.Document;
29 import org.w3c.dom.Element;
30 import org.w3c.dom.Node;
31 import org.w3c.dom.Text;
32
33 import java.text.ParseException;
34 import java.text.SimpleDateFormat;
35 import java.text.DateFormat;
36 import java.util.ArrayList;
37 import java.util.Date;
38 import java.util.List;
39 import java.util.TimeZone;
40
41
42
43
44
45
46
47 public class Timestamp {
48
49 private static final org.apache.commons.logging.Log LOG =
50 org.apache.commons.logging.LogFactory.getLog(Timestamp.class);
51
52 protected Element element = null;
53 protected List<Element> customElements = null;
54 protected Date createdDate;
55 protected Date expiresDate;
56
57
58
59
60
61
62
63
64 public Timestamp(Element timestampElement) throws WSSecurityException {
65 this(timestampElement, true);
66 }
67
68
69
70
71
72
73
74
75
76 public Timestamp(Element timestampElement, boolean bspCompliant) throws WSSecurityException {
77
78 element = timestampElement;
79 customElements = new ArrayList<Element>();
80
81 String strCreated = null;
82 String strExpires = null;
83
84 for (Node currentChild = element.getFirstChild();
85 currentChild != null;
86 currentChild = currentChild.getNextSibling()
87 ) {
88 if (Node.ELEMENT_NODE == currentChild.getNodeType()) {
89 Element currentChildElement = (Element) currentChild;
90 if (WSConstants.CREATED_LN.equals(currentChild.getLocalName()) &&
91 WSConstants.WSU_NS.equals(currentChild.getNamespaceURI())) {
92 if (strCreated == null) {
93 String valueType = currentChildElement.getAttributeNS(null, "ValueType");
94 if (bspCompliant && valueType != null && !"".equals(valueType)) {
95
96 throw new WSSecurityException(
97 WSSecurityException.INVALID_SECURITY, "invalidTimestamp"
98 );
99 }
100 strCreated = ((Text)currentChildElement.getFirstChild()).getData();
101 } else {
102
103 throw new WSSecurityException(
104 WSSecurityException.INVALID_SECURITY, "invalidTimestamp"
105 );
106 }
107 } else if (WSConstants.EXPIRES_LN.equals(currentChild.getLocalName()) &&
108 WSConstants.WSU_NS.equals(currentChild.getNamespaceURI())) {
109 if (strExpires != null || (bspCompliant && strCreated == null)) {
110
111
112
113
114 throw new WSSecurityException(
115 WSSecurityException.INVALID_SECURITY, "invalidTimestamp"
116 );
117 } else {
118 String valueType = currentChildElement.getAttributeNS(null, "ValueType");
119 if (bspCompliant && valueType != null && !"".equals(valueType)) {
120
121 throw new WSSecurityException(
122 WSSecurityException.INVALID_SECURITY, "invalidTimestamp"
123 );
124 }
125 strExpires = ((Text)currentChildElement.getFirstChild()).getData();
126 }
127 } else {
128 if (bspCompliant) {
129 throw new WSSecurityException(
130 WSSecurityException.INVALID_SECURITY, "invalidTimestamp"
131 );
132 }
133 customElements.add(currentChildElement);
134 }
135 }
136 }
137
138
139 if (bspCompliant && strCreated == null) {
140 throw new WSSecurityException(
141 WSSecurityException.INVALID_SECURITY, "invalidTimestamp"
142 );
143 }
144
145
146 DateFormat zulu = new XmlSchemaDateFormat();
147 if (bspCompliant) {
148 zulu.setLenient(false);
149 }
150 try {
151 if (LOG.isDebugEnabled()) {
152 LOG.debug("Current time: " + zulu.format(new Date()));
153 }
154 if (strCreated != null) {
155 createdDate = zulu.parse(strCreated);
156 if (LOG.isDebugEnabled()) {
157 LOG.debug("Timestamp created: " + zulu.format(createdDate));
158 }
159 }
160 if (strExpires != null) {
161 expiresDate = zulu.parse(strExpires);
162 if (LOG.isDebugEnabled()) {
163 LOG.debug("Timestamp expires: " + zulu.format(expiresDate));
164 }
165 }
166 } catch (ParseException e) {
167 throw new WSSecurityException(
168 WSSecurityException.INVALID_SECURITY, "invalidTimestamp", null, e
169 );
170 }
171 }
172
173
174
175
176
177
178
179
180
181 public Timestamp(boolean milliseconds, Document doc, int ttl) {
182
183 customElements = new ArrayList<Element>();
184 element =
185 doc.createElementNS(
186 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.TIMESTAMP_TOKEN_LN
187 );
188
189 DateFormat zulu = null;
190 if (milliseconds) {
191 zulu = new XmlSchemaDateFormat();
192 } else {
193 zulu = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
194 zulu.setTimeZone(TimeZone.getTimeZone("UTC"));
195 }
196 Element elementCreated =
197 doc.createElementNS(
198 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.CREATED_LN
199 );
200 createdDate = new Date();
201 elementCreated.appendChild(doc.createTextNode(zulu.format(createdDate)));
202 element.appendChild(elementCreated);
203 if (ttl != 0) {
204 expiresDate = new Date();
205 expiresDate.setTime(createdDate.getTime() + ((long)ttl * 1000L));
206
207 Element elementExpires =
208 doc.createElementNS(
209 WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":" + WSConstants.EXPIRES_LN
210 );
211 elementExpires.appendChild(doc.createTextNode(zulu.format(expiresDate)));
212 element.appendChild(elementExpires);
213 }
214 }
215
216
217
218
219
220 public void addWSUNamespace() {
221 WSSecurityUtil.setNamespace(element, WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
222 }
223
224
225
226
227
228
229 public Element getElement() {
230 return element;
231 }
232
233
234
235
236
237
238 public String toString() {
239 return DOM2Writer.nodeToString((Node) element);
240 }
241
242
243
244
245
246
247 public Date getCreated() {
248 return createdDate;
249 }
250
251
252
253
254
255
256 public Date getExpires() {
257 return expiresDate;
258 }
259
260
261
262
263 public void addCustomElement(Document doc, Element customElement) {
264 customElements.add(customElement);
265 element.appendChild(customElement);
266 }
267
268
269
270
271
272
273 public List<Element> getCustomElements() {
274 return customElements;
275 }
276
277
278
279
280
281 public void setID(String id) {
282 element.setAttributeNS(WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":Id", id);
283 }
284
285
286
287
288 public String getID() {
289 return element.getAttributeNS(WSConstants.WSU_NS, "Id");
290 }
291
292
293
294
295
296 public boolean isExpired() {
297 if (expiresDate != null) {
298 Date rightNow = new Date();
299 return expiresDate.before(rightNow);
300 }
301 return false;
302 }
303
304
305
306
307
308
309
310
311
312
313 public boolean verifyCreated(
314 int timeToLive,
315 int futureTimeToLive
316 ) {
317 return DateUtil.verifyCreated(createdDate, timeToLive, futureTimeToLive);
318 }
319
320
321 @Override
322 public int hashCode() {
323 int result = 17;
324 if (createdDate != null) {
325 result = 31 * result + createdDate.hashCode();
326 }
327 if (expiresDate != null) {
328 result = 31 * result + expiresDate.hashCode();
329 }
330 return result;
331 }
332
333 @Override
334 public boolean equals(Object object) {
335 if (!(object instanceof Timestamp)) {
336 return false;
337 }
338 Timestamp timestamp = (Timestamp)object;
339 if (!compare(timestamp.getCreated(), getCreated())) {
340 return false;
341 }
342 if (!compare(timestamp.getExpires(), getExpires())) {
343 return false;
344 }
345 return true;
346 }
347
348 private boolean compare(Date item1, Date item2) {
349 if (item1 == null && item2 != null) {
350 return false;
351 } else if (item1 != null && !item1.equals(item2)) {
352 return false;
353 }
354 return true;
355 }
356
357 }