1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.opensaml.xml;
18
19 import java.util.Collection;
20
21 import java.util.Iterator;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25
26 import javax.xml.namespace.QName;
27
28 import org.opensaml.xml.util.DatatypeHelper;
29 import org.opensaml.xml.util.LazyMap;
30 import org.opensaml.xml.util.LazySet;
31 import org.opensaml.xml.util.XMLConstants;
32
33
34
35
36
37
38
39
40
41 public class NamespaceManager {
42
43
44 public static final String DEFAULT_NS_TOKEN = "#default";
45
46
47 private static final Namespace XML_NAMESPACE =
48 new Namespace(XMLConstants.XML_NS, XMLConstants.XML_PREFIX);
49
50
51 private static final Namespace XSI_NAMESPACE =
52 new Namespace(XMLConstants.XSI_NS, XMLConstants.XSI_PREFIX);
53
54
55 private XMLObject owner;
56
57
58 private Namespace elementName;
59
60
61 private Namespace elementType;
62
63
64 private Set<Namespace> decls;
65
66
67 private Set<Namespace> usage;
68
69
70 private Set<Namespace> attrNames;
71
72
73 private Map<String, Namespace> attrValues;
74
75
76 private Namespace contentValue;
77
78
79
80
81
82
83 public NamespaceManager(XMLObject owningObject) {
84 owner = owningObject;
85
86 decls = new LazySet<Namespace>();
87 usage = new LazySet<Namespace>();
88 attrNames = new LazySet<Namespace>();
89 attrValues = new LazyMap<String, Namespace>();
90 }
91
92
93
94
95
96
97
98
99
100 public static String generateAttributeID(QName name) {
101 return name.toString();
102 }
103
104
105
106
107
108
109 public XMLObject getOwner() {
110 return owner;
111 }
112
113
114
115
116
117
118 public Set<Namespace> getNamespaces() {
119 Set<Namespace> namespaces = mergeNamespaceCollections(decls, usage, attrNames, attrValues.values());
120 addNamespace(namespaces, getElementNameNamespace());
121 addNamespace(namespaces, getElementTypeNamespace());
122 addNamespace(namespaces, contentValue);
123 return namespaces;
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137 public void registerNamespace(Namespace namespace) {
138 addNamespace(usage, namespace);
139 }
140
141
142
143
144
145
146
147
148
149
150
151 public void deregisterNamespace(Namespace namespace) {
152 removeNamespace(usage, namespace);
153 }
154
155
156
157
158
159
160 public void registerNamespaceDeclaration(Namespace namespace) {
161 namespace.setAlwaysDeclare(true);
162 addNamespace(decls, namespace);
163 }
164
165
166
167
168
169
170 public void deregisterNamespaceDeclaration(Namespace namespace) {
171 removeNamespace(decls, namespace);
172 }
173
174
175
176
177
178
179 public void registerAttributeName(QName attributeName) {
180 if (checkQName(attributeName)) {
181 addNamespace(attrNames, buildNamespace(attributeName));
182 }
183 }
184
185
186
187
188
189
190 public void deregisterAttributeName(QName attributeName) {
191 if (checkQName(attributeName)) {
192 removeNamespace(attrNames, buildNamespace(attributeName));
193 }
194 }
195
196
197
198
199
200
201
202 public void registerAttributeValue(String attributeID, QName attributeValue) {
203 if (checkQName(attributeValue)) {
204 attrValues.put(attributeID, buildNamespace(attributeValue));
205 }
206 }
207
208
209
210
211
212
213 public void deregisterAttributeValue(String attributeID) {
214 attrValues.remove(attributeID);
215 }
216
217
218
219
220
221
222 public void registerContentValue(QName content) {
223 if (checkQName(content)) {
224 contentValue = buildNamespace(content);
225 }
226 }
227
228
229
230
231
232 public void deregisterContentValue() {
233 contentValue = null;
234 }
235
236
237
238
239
240
241
242
243
244
245
246
247 public Set<String> getNonVisibleNamespacePrefixes() {
248 LazySet<String> prefixes = new LazySet<String>();
249 addPrefixes(prefixes, getNonVisibleNamespaces());
250 return prefixes;
251 }
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270 public Set<Namespace> getNonVisibleNamespaces() {
271 LazySet<Namespace> nonVisibleCandidates = new LazySet<Namespace>();
272
273
274 List<XMLObject> children = getOwner().getOrderedChildren();
275 if (children != null) {
276 for(XMLObject child : getOwner().getOrderedChildren()) {
277 if (child != null) {
278 Set<Namespace> childNonVisibleNamespaces = child.getNamespaceManager().getNonVisibleNamespaces();
279 if (childNonVisibleNamespaces != null && ! childNonVisibleNamespaces.isEmpty()) {
280 nonVisibleCandidates.addAll(childNonVisibleNamespaces);
281 }
282 }
283 }
284 }
285
286
287 nonVisibleCandidates.addAll(getNonVisibleNamespaceCandidates());
288
289
290 nonVisibleCandidates.removeAll(getVisibleNamespaces());
291
292
293 nonVisibleCandidates.remove(XML_NAMESPACE);
294
295
296
297 return nonVisibleCandidates;
298
299 }
300
301
302
303
304
305
306
307
308
309
310
311
312
313 public Set<Namespace> getAllNamespacesInSubtreeScope() {
314 LazySet<Namespace> namespaces = new LazySet<Namespace>();
315
316
317 List<XMLObject> children = getOwner().getOrderedChildren();
318 if (children != null) {
319 for(XMLObject child : getOwner().getOrderedChildren()) {
320 if (child != null) {
321 Set<Namespace> childNamespaces = child.getNamespaceManager().getAllNamespacesInSubtreeScope();
322 if (childNamespaces != null && ! childNamespaces.isEmpty()) {
323 namespaces.addAll(childNamespaces);
324 }
325 }
326 }
327 }
328
329
330 for (Namespace myNS : getNamespaces()) {
331 namespaces.add(copyNamespace(myNS));
332 }
333
334 return namespaces;
335 }
336
337
338
339
340
341
342 public void registerElementName(QName name) {
343 if (checkQName(name)) {
344 elementName = buildNamespace(name);
345 }
346 }
347
348
349
350
351
352
353 public void registerElementType(QName type) {
354 if (type != null) {
355 if (checkQName(type)) {
356 elementType = buildNamespace(type);
357 }
358 } else {
359 elementType = null;
360 }
361 }
362
363
364
365
366
367
368 private Namespace getElementNameNamespace() {
369 if (elementName == null && checkQName(owner.getElementQName())) {
370 elementName = buildNamespace(owner.getElementQName());
371 }
372 return elementName;
373 }
374
375
376
377
378
379
380 private Namespace getElementTypeNamespace() {
381 if (elementType == null) {
382 QName type = owner.getSchemaType();
383 if (type != null && checkQName(type)) {
384 elementType = buildNamespace(type);
385 }
386 }
387 return elementType;
388 }
389
390
391
392
393
394
395
396 private Namespace buildNamespace(QName name) {
397 String uri = DatatypeHelper.safeTrimOrNullString(name.getNamespaceURI());
398 if (uri == null) {
399 throw new IllegalArgumentException("A non-empty namespace URI must be supplied");
400 }
401 String prefix = DatatypeHelper.safeTrimOrNullString(name.getPrefix());
402 return new Namespace(uri, prefix);
403 }
404
405
406
407
408
409
410
411
412 private void addNamespace(Set<Namespace> namespaces, Namespace newNamespace) {
413 if (newNamespace == null) {
414 return;
415 }
416
417 if (namespaces.size() == 0) {
418 namespaces.add(newNamespace);
419 return;
420 }
421
422 for (Namespace namespace : namespaces) {
423 if (DatatypeHelper.safeEquals(namespace.getNamespaceURI(), newNamespace.getNamespaceURI()) &&
424 DatatypeHelper.safeEquals(namespace.getNamespacePrefix(), newNamespace.getNamespacePrefix())) {
425 if (newNamespace.alwaysDeclare() && !namespace.alwaysDeclare()) {
426
427
428 namespaces.remove(namespace);
429 namespaces.add(newNamespace);
430 return;
431 } else {
432
433 return;
434 }
435 }
436 }
437
438 namespaces.add(newNamespace);
439 }
440
441
442
443
444
445
446
447
448
449 private void removeNamespace(Set<Namespace> namespaces, Namespace oldNamespace) {
450 if (oldNamespace == null) {
451 return;
452 }
453
454 Iterator<Namespace> iter = namespaces.iterator();
455 while (iter.hasNext()) {
456 Namespace namespace = iter.next();
457 if (DatatypeHelper.safeEquals(namespace.getNamespaceURI(), oldNamespace.getNamespaceURI()) &&
458 DatatypeHelper.safeEquals(namespace.getNamespacePrefix(), oldNamespace.getNamespacePrefix())) {
459 iter.remove();
460 }
461 }
462
463 }
464
465
466
467
468
469
470
471
472 private Set<Namespace> mergeNamespaceCollections(Collection<Namespace> ... namespaces) {
473 LazySet<Namespace> newNamespaces = new LazySet<Namespace>();
474
475 for (Collection<Namespace> nsCollection : namespaces) {
476 for (Namespace ns : nsCollection) {
477 if (ns != null) {
478 addNamespace(newNamespaces, ns);
479 }
480 }
481 }
482
483 return newNamespaces;
484 }
485
486
487
488
489
490
491
492
493
494
495
496
497 private Set<Namespace> getVisibleNamespaces() {
498 LazySet<Namespace> namespaces = new LazySet<Namespace>();
499
500
501 if (getElementNameNamespace() != null) {
502 namespaces.add(copyNamespace(getElementNameNamespace()));
503 }
504
505
506 if (getElementTypeNamespace() != null) {
507 namespaces.add(copyNamespace(XSI_NAMESPACE));
508 }
509
510
511 for (Namespace attribName : attrNames) {
512 if (attribName != null) {
513 namespaces.add(copyNamespace(attribName));
514 }
515 }
516
517 return namespaces;
518 }
519
520
521
522
523
524
525
526
527
528
529
530
531 private Set<Namespace> getNonVisibleNamespaceCandidates() {
532 LazySet<Namespace> namespaces = new LazySet<Namespace>();
533
534
535 if (getElementTypeNamespace() != null) {
536 namespaces.add(copyNamespace(getElementTypeNamespace()));
537 }
538
539
540 for (Namespace attribValue : attrValues.values()) {
541 if (attribValue != null) {
542 namespaces.add(copyNamespace(attribValue));
543 }
544 }
545 if (contentValue != null) {
546 namespaces.add(copyNamespace(contentValue));
547 }
548
549 return namespaces;
550 }
551
552
553
554
555
556
557
558 private Namespace copyNamespace(Namespace orig) {
559 if (orig == null) {
560 return null;
561 } else {
562 return new Namespace(orig.getNamespaceURI(), orig.getNamespacePrefix());
563 }
564 }
565
566
567
568
569
570
571
572
573 private void addPrefixes(Set<String> prefixes, Collection<Namespace> namespaces) {
574 for (Namespace ns : namespaces) {
575 String prefix = DatatypeHelper.safeTrimOrNullString(ns.getNamespacePrefix());
576 if (prefix == null) {
577 prefix = DEFAULT_NS_TOKEN;
578 }
579 prefixes.add(prefix);
580 }
581 }
582
583
584
585
586
587
588
589
590 private boolean checkQName(QName name) {
591 return !DatatypeHelper.isEmpty(name.getNamespaceURI());
592 }
593
594 }