KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xml > internal > security > c14n > implementations > NameSpaceSymbTable


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
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  */

17 package com.sun.org.apache.xml.internal.security.c14n.implementations;
18
19 import java.lang.reflect.Array JavaDoc;
20 import java.util.AbstractList JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Arrays JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Map JavaDoc;
28
29
30
31 import org.w3c.dom.Attr JavaDoc;
32 import org.w3c.dom.Node JavaDoc;
33
34
35
36 /**
37  * A stack based Symble Table.
38  *<br>For speed reasons all the symbols are introduced in the same map,
39  * and at the same time in a list so it can be removed when the frame is pop back.
40  * @author Raul Benito
41  **/

42 public class NameSpaceSymbTable {
43     
44     /**The map betwen prefix-> entry table. */
45     SymbMap symb = new SymbMap();
46     /**The level of nameSpaces (for Inclusive visibility).*/
47     int nameSpaces=0;
48     /**The stacks for removing the definitions when doing pop.*/
49     List JavaDoc level = new ArrayList JavaDoc();
50     boolean cloned=true;
51     static final String JavaDoc XMLNS="xmlns";
52     /**
53      * Default constractor
54      **/

55     public NameSpaceSymbTable() {
56         //Insert the default binding for xmlns.
57
NameSpaceSymbEntry ne=new NameSpaceSymbEntry("",null,true);
58         ne.lastrendered="";
59         symb.put(XMLNS,ne);
60     }
61     
62     /**
63      * Get all the unrendered nodes in the name space.
64      * For Inclusive rendering
65      * @param result the list where to fill the unrendered xmlns definitions.
66      **/

67     public void getUnrenderedNodes(Collection JavaDoc result) {
68        //List result=new ArrayList();
69
Iterator JavaDoc it=symb.entrySet().iterator();
70        while (it.hasNext()) {
71             NameSpaceSymbEntry n=(NameSpaceSymbEntry)(it.next());
72             //put them rendered?
73
if ((!n.rendered) && (n.n!=null)) {
74                 result.add(n.n);
75                 n.rendered=true;
76             }
77        }
78     }
79     
80     /**
81      * Push a frame for visible namespace.
82      * For Inclusive rendering.
83      **/

84     public void outputNodePush() {
85         nameSpaces++;
86         push();
87     }
88     
89     /**
90      * Pop a frame for visible namespace.
91      **/

92     public void outputNodePop() {
93         nameSpaces--;
94         pop();
95     }
96     
97     /**
98      * Push a frame for a node.
99      * Inclusive or Exclusive.
100      **/

101     public void push() {
102         //Put the number of namespace definitions in the stack.
103
/**if (cloned) {
104             Object ob[]= {symb,cloned ? symb : null};
105             level.add(ob);
106         } **/

107         level.add(null);
108         cloned=false;
109     }
110     
111     /**
112      * Pop a frame.
113      * Inclusive or Exclusive.
114      **/

115     public void pop() {
116         int size=level.size()-1;
117         Object JavaDoc ob= level.remove(size);
118         if (ob!=null) {
119             symb=(SymbMap)ob;
120             if (size==0) {
121                cloned=false;
122             } else
123             cloned=(level.get(size-1)!=symb);
124         } else {
125             cloned=false;
126         }
127         
128         
129     }
130     
131     final void needsClone() {
132         if (!cloned) {
133             level.remove(level.size()-1);
134             level.add(symb);
135             symb=(SymbMap) symb.clone();
136             cloned=true;
137         }
138     }
139     
140     
141     /**
142      * Gets the attribute node that defines the binding for the prefix.
143      * @param prefix the prefix to obtain the attribute.
144      * @return null if there is no need to render the prefix. Otherwise the node of
145      * definition.
146      **/

147     public Attr JavaDoc getMapping(String JavaDoc prefix) {
148         NameSpaceSymbEntry entry=symb.get(prefix);
149         if (entry==null) {
150             //There is no definition for the prefix(a bug?).
151
return null;
152         }
153         if (entry.rendered) {
154             //No need to render an entry already rendered.
155
return null;
156         }
157         // Mark this entry as render.
158
entry=(NameSpaceSymbEntry) entry.clone();
159         needsClone();
160         symb.put(prefix,entry);
161         entry.rendered=true;
162         entry.level=nameSpaces;
163         entry.lastrendered=entry.uri;
164         // Return the node for outputing.
165
return entry.n;
166     }
167     
168     /**
169      * Gets a definition without mark it as render.
170      * For render in exclusive c14n the namespaces in the include prefixes.
171      * @param prefix The prefix whose definition is neaded.
172      * @return the attr to render, null if there is no need to render
173      **/

174     public Attr JavaDoc getMappingWithoutRendered(String JavaDoc prefix) {
175         NameSpaceSymbEntry entry= symb.get(prefix);
176         if (entry==null) {
177             return null;
178         }
179         if (entry.rendered) {
180             return null;
181         }
182         return entry.n;
183     }
184     
185     /**
186      * Adds the mapping for a prefix.
187      * @param prefix the prefix of definition
188      * @param uri the Uri of the definition
189      * @param n the attribute that have the definition
190      * @return true if there is already defined.
191      **/

192     public boolean addMapping(String JavaDoc prefix, String JavaDoc uri,Attr JavaDoc n) {
193         NameSpaceSymbEntry ob = symb.get(prefix);
194         if ((ob!=null) && uri.equals(ob.uri)) {
195             //If we have it previously defined. Don't keep working.
196
return false;
197         }
198         //Creates and entry in the table for this new definition.
199
NameSpaceSymbEntry ne=new NameSpaceSymbEntry(uri,n,false);
200         needsClone();
201         symb.put(prefix, ne);
202         if (ob != null) {
203             //We have a previous definition store it for the pop.
204
//Check if a previous definition(not the inmidiatly one) has been rendered.
205
ne.lastrendered=ob.lastrendered;
206             if ((ob.lastrendered!=null)&& (ob.lastrendered.equals(uri))) {
207                 //Yes it is. Mark as rendered.
208
ne.rendered=true;
209             }
210         }
211         return true;
212     }
213
214     /**
215      * Adds a definition and mark it as render.
216      * For inclusive c14n.
217      * @param prefix the prefix of definition
218      * @param uri the Uri of the definition
219      * @param n the attribute that have the definition
220      * @return the attr to render, null if there is no need to render
221      **/

222     public Node JavaDoc addMappingAndRender(String JavaDoc prefix, String JavaDoc uri,Attr JavaDoc n) {
223         NameSpaceSymbEntry ob = symb.get(prefix);
224         
225         if ((ob!=null) && uri.equals(ob.uri)) {
226             if (!ob.rendered) {
227                 ob=(NameSpaceSymbEntry) ob.clone();
228                 needsClone();
229                 symb.put(prefix,ob);
230                 ob.lastrendered=uri;
231                 ob.rendered=true;
232                 return ob.n;
233             }
234             return null;
235         }
236         
237         NameSpaceSymbEntry ne=new NameSpaceSymbEntry(uri,n,true);
238         ne.lastrendered=uri;
239         needsClone();
240         symb.put(prefix, ne);
241         if (ob != null) {
242             
243             if ((ob.lastrendered!=null)&& (ob.lastrendered.equals(uri))) {
244                 ne.rendered=true;
245                 return null;
246             }
247         }
248         return ne.n;
249     }
250     /**
251      * Adds & gets(if needed) the attribute node that defines the binding for the prefix.
252      * Take on account if the rules of rendering in the inclusive c14n.
253      * For inclusive c14n.
254      * @param prefix the prefix to obtain the attribute.
255      * @param outputNode the container element is an output element.
256      * @param uri the Uri of the definition
257      * @param n the attribute that have the definition
258      * @return null if there is no need to render the prefix. Otherwise the node of
259      * definition.
260      **/

261     public Node JavaDoc addMappingAndRenderXNodeSet(String JavaDoc prefix, String JavaDoc uri,Attr JavaDoc n,boolean outputNode) {
262         NameSpaceSymbEntry ob = symb.get(prefix);
263         int visibleNameSpaces=nameSpaces;
264         if ((ob!=null) && uri.equals(ob.uri)) {
265             if (!ob.rendered) {
266                 ob=(NameSpaceSymbEntry)ob.clone();
267                 needsClone();
268                 symb.put(prefix,ob);
269                 ob.rendered=true;
270                 ob.level=visibleNameSpaces;
271                 return ob.n;
272             }
273             ob=(NameSpaceSymbEntry)ob.clone();
274             needsClone();
275             symb.put(prefix,ob);
276             if (outputNode && (((visibleNameSpaces-ob.level)<2) || XMLNS.equals(prefix)) ) {
277                 ob.level=visibleNameSpaces;
278                 return null; //Already rendered, just return nulll
279
}
280             ob.level=visibleNameSpaces;
281             return ob.n;
282         }
283         
284         NameSpaceSymbEntry ne=new NameSpaceSymbEntry(uri,n,true);
285         ne.level=nameSpaces;
286         ne.rendered=true;
287         needsClone();
288         symb.put(prefix, ne);
289         if (ob != null) {
290             ne.lastrendered=ob.lastrendered;
291             
292             if ((ob.lastrendered!=null)&& (ob.lastrendered.equals(uri))) {
293                 ne.rendered=true;
294             }
295         }
296         return ne.n;
297     }
298 }
299
300 /**
301  * The internal structure of NameSpaceSymbTable.
302  **/

303 class NameSpaceSymbEntry implements Cloneable JavaDoc {
304     NameSpaceSymbEntry(String JavaDoc name,Attr JavaDoc n,boolean rendered) {
305         this.uri=name;
306         this.rendered=rendered;
307         this.n=n;
308     }
309     /** @inheritDoc */
310     public Object JavaDoc clone() {
311         try {
312             return super.clone();
313         } catch (CloneNotSupportedException JavaDoc e) {
314             return null;
315         }
316     }
317     /** The level where the definition was rendered(Only for inclusive) */
318     int level=0;
319     /**The URI that the prefix defines */
320     String JavaDoc uri;
321     /**The last output in the URI for this prefix (This for speed reason).*/
322     String JavaDoc lastrendered=null;
323     /**This prefix-URI has been already render or not.*/
324     boolean rendered=false;
325     /**The attribute to include.*/
326     Attr JavaDoc n;
327 };
328
329 class SymbMap implements Cloneable JavaDoc{
330     int free=23;
331     NameSpaceSymbEntry[] entries=new NameSpaceSymbEntry[free];
332     String JavaDoc[] keys=new String JavaDoc[free];
333     
334     void put(String JavaDoc key, NameSpaceSymbEntry value) {
335         int index = index(key);
336         Object JavaDoc oldKey = keys[index];
337         keys[index] = key;
338         entries[index] = value;
339         if (oldKey==null || !oldKey.equals(key)) {
340             if (--free == 0) {
341                 free=entries.length;
342                 int newCapacity = free<<2;
343                 rehash(newCapacity);
344             }
345         }
346     }
347     
348     List JavaDoc entrySet() {
349         List JavaDoc a=new ArrayList JavaDoc();
350         for (int i=0;i<entries.length;i++) {
351             if ((entries[i]!=null) && !("".equals(entries[i]))) {
352                 a.add(entries[i]);
353             }
354         }
355         return a;
356     }
357
358
359     protected int index(Object JavaDoc obj) {
360         Object JavaDoc[] set = keys;
361         int length = set.length;
362         //abs of index
363
int index = (obj.hashCode() & 0x7fffffff) % length;
364         Object JavaDoc cur = set[index];
365
366         if (cur == null || (cur.equals( obj))) {
367             return index;
368         }
369         do {
370             index=index==length? 0:++index;
371             cur = set[index];
372         } while (cur != null && (!cur.equals(obj)));
373         return index;
374     }
375      /**
376      * rehashes the map to the new capacity.
377      *
378      * @param newCapacity an <code>int</code> value
379      */

380     protected void rehash(int newCapacity) {
381         int oldCapacity = keys.length;
382         String JavaDoc oldKeys[] = keys;
383         NameSpaceSymbEntry oldVals[] = entries;
384
385         keys = new String JavaDoc[newCapacity];
386         entries = new NameSpaceSymbEntry[newCapacity];
387
388         for (int i = oldCapacity; i-- > 0;) {
389             if(oldKeys[i] != null) {
390                 String JavaDoc o = oldKeys[i];
391                 int index = index(o);
392                 keys[index] = o;
393                 entries[index] = oldVals[i];
394             }
395         }
396     }
397      NameSpaceSymbEntry get(String JavaDoc key) {
398             return entries[index(key)];
399         }
400      protected Object JavaDoc clone() {
401         // TODO Auto-generated method stub
402
try {
403             SymbMap copy=(SymbMap) super.clone();
404             copy.entries=new NameSpaceSymbEntry[entries.length];
405             System.arraycopy(entries,0,copy.entries,0,entries.length);
406             copy.keys=new String JavaDoc[keys.length];
407             System.arraycopy(keys,0,copy.keys,0,keys.length);
408             
409             return copy;
410         } catch (CloneNotSupportedException JavaDoc e) {
411             // TODO Auto-generated catch block
412
e.printStackTrace();
413         }
414         return null;
415     }
416 }
417
Popular Tags