KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > n3 > nanoxml > NonValidator


1 /* NonValidator.java NanoXML/Java
2  *
3  * $Revision: 1422 $
4  * $Date: 2006-03-21 19:14:56 +0100 (Tue, 21 Mar 2006) $
5  * $Name$
6  *
7  * This file is part of NanoXML 2 for Java.
8  * Copyright (C) 2001 Marc De Scheemaecker, All Rights Reserved.
9  *
10  * This software is provided 'as-is', without any express or implied warranty.
11  * In no event will the authors be held liable for any damages arising from the
12  * use of this software.
13  *
14  * Permission is granted to anyone to use this software for any purpose,
15  * including commercial applications, and to alter it and redistribute it
16  * freely, subject to the following restrictions:
17  *
18  * 1. The origin of this software must not be misrepresented; you must not
19  * claim that you wrote the original software. If you use this software in
20  * a product, an acknowledgment in the product documentation would be
21  * appreciated but is not required.
22  *
23  * 2. Altered source versions must be plainly marked as such, and must not be
24  * misrepresented as being the original software.
25  *
26  * 3. This notice may not be removed or altered from any source distribution.
27  */

28
29 package net.n3.nanoxml;
30
31 import java.io.Reader JavaDoc;
32 import java.io.StringReader JavaDoc;
33 import java.util.Enumeration JavaDoc;
34 import java.util.Hashtable JavaDoc;
35 import java.util.Properties JavaDoc;
36 import java.util.Stack JavaDoc;
37
38 /**
39  * NonValidator processes the DTD and handles entity definitions. It does not do any validation
40  * itself.
41  *
42  * @author Marc De Scheemaecker
43  * @version $Name$, $Revision: 1422 $
44  */

45 public class NonValidator implements IXMLValidator
46 {
47
48     /**
49      * Delimiter for CDATA sections.
50      */

51     private static final char[] END_OF_CONDSECTION = { '>', ']', ']'};
52
53     /**
54      * The parameter entity resolver.
55      */

56     protected IXMLEntityResolver parameterEntityResolver;
57
58     /**
59      * The parameter entity level.
60      */

61     protected int peLevel;
62
63     /**
64      * Contains the default values for attributes for the different element types.
65      */

66     protected Hashtable JavaDoc attributeDefaultValues;
67
68     /**
69      * The stack of elements to be processed.
70      */

71     protected Stack JavaDoc currentElements;
72
73     /**
74      * Creates the "validator".
75      */

76     public NonValidator()
77     {
78         this.attributeDefaultValues = new Hashtable JavaDoc();
79         this.currentElements = new Stack JavaDoc();
80         this.parameterEntityResolver = new XMLEntityResolver();
81         this.peLevel = 0;
82     }
83
84     /**
85      * Cleans up the object when it's destroyed.
86      */

87     protected void finalize() throws Throwable JavaDoc
88     {
89         this.parameterEntityResolver = null;
90         this.attributeDefaultValues.clear();
91         this.attributeDefaultValues = null;
92         this.currentElements.clear();
93         this.currentElements = null;
94         super.finalize();
95     }
96
97     /**
98      * Sets the parameter entity resolver.
99      *
100      * @param resolver the entity resolver.
101      */

102     public void setParameterEntityResolver(IXMLEntityResolver resolver)
103     {
104         this.parameterEntityResolver = resolver;
105     }
106
107     /**
108      * Returns the parameter entity resolver.
109      *
110      * @return the entity resolver.
111      */

112     public IXMLEntityResolver getParameterEntityResolver()
113     {
114         return this.parameterEntityResolver;
115     }
116
117     /**
118      * Parses the DTD. The validator object is responsible for reading the full DTD.
119      *
120      * @param publicID the public ID, which may be null.
121      * @param reader the reader to read the DTD from.
122      * @param entityResolver the entity resolver.
123      * @param external true if the DTD is external.
124      *
125      * @throws java.lang.Exception if something went wrong.
126      */

127     public void parseDTD(String JavaDoc publicID, IXMLReader reader, IXMLEntityResolver entityResolver,
128             boolean external) throws Exception JavaDoc
129     {
130         XMLUtil.skipWhitespace(reader, '%', null, null);
131
132         for (;;)
133         {
134             char ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
135
136             if (ch == '<')
137             {
138                 this.processElement(reader, entityResolver);
139             }
140             else if (ch == ']')
141             {
142                 return; // end internal DTD
143
}
144             else
145             {
146                 XMLUtil.errorInvalidInput(reader.getSystemID(), reader.getLineNr(), "" + ch);
147             }
148
149             do
150             {
151                 if (external && (peLevel == 0) && reader.atEOFOfCurrentStream()) { return; // end
152
// external
153
// DTD
154
}
155
156                 ch = reader.read();
157             }
158             while ((ch == ' ') || (ch == '\t') || (ch == '\n') || (ch == '\r'));
159
160             reader.unread(ch);
161             XMLUtil.skipWhitespace(reader, '%', null, null);
162         }
163     }
164
165     /**
166      * Processes an element in the DTD.
167      *
168      * @param reader the reader to read data from
169      * @param entityResolver the entity resolver
170      *
171      * @throws java.lang.Exception if something went wrong.
172      */

173     protected void processElement(IXMLReader reader, IXMLEntityResolver entityResolver)
174             throws Exception JavaDoc
175     {
176         char ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
177
178         if (ch != '!')
179         {
180             XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
181             return;
182         }
183
184         ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
185
186         switch (ch)
187         {
188         case '-':
189             XMLUtil.skipComment(reader, this.parameterEntityResolver);
190             break;
191
192         case '[':
193             this.processConditionalSection(reader, entityResolver);
194             break;
195
196         case 'E':
197             this.processEntity(reader, entityResolver);
198             break;
199
200         case 'A':
201             this.processAttList(reader, entityResolver);
202             break;
203
204         default:
205             XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
206         }
207     }
208
209     /**
210      * Processes a conditional section.
211      *
212      * @param reader the reader to read data from
213      * @param entityResolver the entity resolver
214      *
215      * @throws java.lang.Exception if something went wrong.
216      */

217     protected void processConditionalSection(IXMLReader reader, IXMLEntityResolver entityResolver)
218             throws Exception JavaDoc
219     {
220         XMLUtil.skipWhitespace(reader, '%', null, null);
221
222         char ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
223
224         if (ch != 'I')
225         {
226             XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
227             return;
228         }
229
230         ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
231
232         switch (ch)
233         {
234         case 'G':
235             this.processIgnoreSection(reader, entityResolver);
236             return;
237
238         case 'N':
239             break;
240
241         default:
242             XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
243             return;
244         }
245
246         if (!XMLUtil.checkLiteral(reader, '%', this.parameterEntityResolver, "CLUDE"))
247         {
248             XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
249             return;
250         }
251
252         XMLUtil.skipWhitespace(reader, '%', null, null);
253
254         ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
255
256         if (ch != '[')
257         {
258             XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
259             return;
260         }
261
262         Reader JavaDoc subreader = new ContentReader(reader, this.parameterEntityResolver, '\0',
263                 NonValidator.END_OF_CONDSECTION, true, "");
264         StringBuffer JavaDoc buf = new StringBuffer JavaDoc(1024);
265
266         for (;;)
267         {
268             int ch2 = subreader.read();
269
270             if (ch2 < 0)
271             {
272                 break;
273             }
274
275             buf.append((char) ch2);
276         }
277
278         subreader.close();
279         reader.startNewStream(new StringReader JavaDoc(buf.toString()));
280     }
281
282     /**
283      * Processes an ignore section.
284      *
285      * @param reader the reader to read data from
286      * @param entityResolver the entity resolver
287      *
288      * @throws java.lang.Exception if something went wrong.
289      */

290     protected void processIgnoreSection(IXMLReader reader, IXMLEntityResolver entityResolver)
291             throws Exception JavaDoc
292     {
293         if (!XMLUtil.checkLiteral(reader, '%', this.parameterEntityResolver, "NORE"))
294         {
295             XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
296             return;
297         }
298
299         XMLUtil.skipWhitespace(reader, '%', null, null);
300
301         char ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
302
303         if (ch != '[')
304         {
305             XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
306             return;
307         }
308
309         Reader JavaDoc subreader = new ContentReader(reader, this.parameterEntityResolver, '\0',
310                 NonValidator.END_OF_CONDSECTION, true, "");
311         subreader.close();
312     }
313
314     /**
315      * Processes an ATTLIST element.
316      *
317      * @param reader the reader to read data from
318      * @param entityResolver the entity resolver
319      *
320      * @throws java.lang.Exception if something went wrong.
321      */

322     protected void processAttList(IXMLReader reader, IXMLEntityResolver entityResolver)
323             throws Exception JavaDoc
324     {
325         if (!XMLUtil.checkLiteral(reader, '%', this.parameterEntityResolver, "TTLIST"))
326         {
327             XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
328             return;
329         }
330
331         XMLUtil.skipWhitespace(reader, '%', null, null);
332         String JavaDoc elementName = XMLUtil.scanIdentifier(reader, '%', this.parameterEntityResolver);
333         XMLUtil.skipWhitespace(reader, '%', null, null);
334         char ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
335         Properties JavaDoc props = new Properties JavaDoc();
336
337         while (ch != '>')
338         {
339             reader.unread(ch);
340             String JavaDoc attName = XMLUtil.scanIdentifier(reader, '%', this.parameterEntityResolver);
341             XMLUtil.skipWhitespace(reader, '%', null, null);
342             ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
343
344             if (ch == '(')
345             {
346                 while (ch != ')')
347                 {
348                     ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
349                 }
350             }
351             else
352             {
353                 reader.unread(ch);
354                 XMLUtil.scanIdentifier(reader, '%', this.parameterEntityResolver);
355             }
356
357             XMLUtil.skipWhitespace(reader, '%', null, null);
358             ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
359
360             if (ch == '#')
361             {
362                 String JavaDoc str = XMLUtil.scanIdentifier(reader, '%', this.parameterEntityResolver);
363                 XMLUtil.skipWhitespace(reader, '%', null, null);
364
365                 if (!"FIXED".equals(str))
366                 {
367                     XMLUtil.skipWhitespace(reader, '%', null, null);
368                     ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
369                     continue;
370                 }
371             }
372             else
373             {
374                 reader.unread(ch);
375             }
376
377             String JavaDoc value = XMLUtil.scanString(reader, '%', false, this.parameterEntityResolver);
378             props.put(attName, value);
379             XMLUtil.skipWhitespace(reader, '%', null, null);
380             ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
381         }
382
383         if (!props.isEmpty())
384         {
385             this.attributeDefaultValues.put(elementName, props);
386         }
387     }
388
389     /**
390      * Processes an ENTITY element.
391      *
392      * @param reader the reader to read data from
393      * @param entityResolver the entity resolver
394      *
395      * @throws java.lang.Exception if something went wrong.
396      */

397     protected void processEntity(IXMLReader reader, IXMLEntityResolver entityResolver)
398             throws Exception JavaDoc
399     {
400         if (!XMLUtil.checkLiteral(reader, '%', this.parameterEntityResolver, "NTITY"))
401         {
402             XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
403             return;
404         }
405
406         XMLUtil.skipWhitespace(reader, '\0', null, null);
407         char ch = XMLUtil.read(reader, null, '\0', this.parameterEntityResolver);
408
409         if (ch == '%')
410         {
411             XMLUtil.skipWhitespace(reader, '%', null, null);
412             entityResolver = this.parameterEntityResolver;
413         }
414         else
415         {
416             reader.unread(ch);
417         }
418
419         String JavaDoc key = XMLUtil.scanIdentifier(reader, '%', this.parameterEntityResolver);
420         XMLUtil.skipWhitespace(reader, '%', null, null);
421         ch = XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
422         String JavaDoc systemID = null;
423         String JavaDoc publicID = null;
424
425         switch (ch)
426         {
427         case 'P':
428             if (!XMLUtil.checkLiteral(reader, '%', this.parameterEntityResolver, "UBLIC"))
429             {
430                 XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
431                 return;
432             }
433
434             XMLUtil.skipWhitespace(reader, '%', null, null);
435             publicID = XMLUtil.scanString(reader, '%', false, this.parameterEntityResolver);
436             XMLUtil.skipWhitespace(reader, '%', null, null);
437             systemID = XMLUtil.scanString(reader, '%', false, this.parameterEntityResolver);
438             XMLUtil.skipWhitespace(reader, '%', null, null);
439             XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
440             break;
441
442         case 'S':
443             if (!XMLUtil.checkLiteral(reader, '%', this.parameterEntityResolver, "YSTEM"))
444             {
445                 XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
446                 return;
447             }
448
449             XMLUtil.skipWhitespace(reader, '%', null, null);
450             systemID = XMLUtil.scanString(reader, '%', false, this.parameterEntityResolver);
451             XMLUtil.skipWhitespace(reader, '%', null, null);
452             XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
453             break;
454
455         case '"':
456         case '\'':
457             reader.unread(ch);
458             String JavaDoc value = XMLUtil.scanString(reader, '%', false, this.parameterEntityResolver);
459             entityResolver.addInternalEntity(key, value);
460             XMLUtil.skipWhitespace(reader, '%', null, null);
461             XMLUtil.read(reader, null, '%', this.parameterEntityResolver);
462             break;
463         default:
464             XMLUtil.skipTag(reader, '%', this.parameterEntityResolver);
465         }
466
467         if (systemID != null)
468         {
469             entityResolver.addExternalEntity(key, publicID, systemID);
470         }
471     }
472
473     /**
474      * Indicates that an element has been started.
475      *
476      * @param name the name of the element.
477      * @param nsPrefix the prefix used to identify the namespace
478      * @param nsSystemId the system ID associated with the namespace
479      * @param systemId the system ID of the XML data of the element.
480      * @param lineNr the line number in the XML data of the element.
481      */

482     public void elementStarted(String JavaDoc name, String JavaDoc nsPrefix, String JavaDoc nsSystemId, String JavaDoc systemId,
483             int lineNr)
484     {
485         Properties JavaDoc attribs = (Properties JavaDoc) this.attributeDefaultValues.get(name);
486
487         if (attribs == null)
488         {
489             attribs = new Properties JavaDoc();
490         }
491         else
492         {
493             attribs = (Properties JavaDoc) attribs.clone();
494         }
495
496         this.currentElements.push(attribs);
497     }
498
499     /**
500      * Indicates that the current element has ended.
501      *
502      * @param name the name of the element.
503      * @param nsPrefix the prefix used to identify the namespace
504      * @param nsSystemId the system ID associated with the namespace
505      * @param systemId the system ID of the XML data of the element.
506      * @param lineNr the line number in the XML data of the element.
507      */

508     public void elementEnded(String JavaDoc name, String JavaDoc nsPrefix, String JavaDoc nsSystemId, String JavaDoc systemId,
509             int lineNr)
510     {
511         // nothing to do
512
}
513
514     /**
515      * This method is called when the attributes of an XML element have been processed. If there are
516      * attributes with a default value which have not been specified yet, they have to be put into
517      * <I>extraAttributes</I>.
518      *
519      * @param name the name of the element.
520      * @param nsPrefix the prefix used to identify the namespace
521      * @param nsSystemId the system ID associated with the namespace
522      * @param extraAttributes where to put extra attributes.
523      * @param systemId the system ID of the XML data of the element.
524      * @param lineNr the line number in the XML data of the element.
525      */

526     public void elementAttributesProcessed(String JavaDoc name, String JavaDoc nsPrefix, String JavaDoc nsSystemId,
527             Properties JavaDoc extraAttributes, String JavaDoc systemId, int lineNr)
528     {
529         Properties JavaDoc props = (Properties JavaDoc) this.currentElements.pop();
530         Enumeration JavaDoc enumeration = props.keys();
531
532         while (enumeration.hasMoreElements())
533         {
534             String JavaDoc key = (String JavaDoc) enumeration.nextElement();
535             extraAttributes.put(key, props.get(key));
536         }
537     }
538
539     /**
540      * Indicates that an attribute has been added to the current element.
541      *
542      * @param key the name of the attribute.
543      * @param nsPrefix the prefix used to identify the namespace
544      * @param nsSystemId the system ID associated with the namespace
545      * @param value the value of the attribute.
546      * @param systemId the system ID of the XML data of the element.
547      * @param lineNr the line number in the XML data of the element.
548      */

549     public void attributeAdded(String JavaDoc key, String JavaDoc nsPrefix, String JavaDoc nsSystemId, String JavaDoc value,
550             String JavaDoc systemId, int lineNr)
551     {
552         Properties JavaDoc props = (Properties JavaDoc) this.currentElements.peek();
553
554         if (props.containsKey(key))
555         {
556             props.remove(key);
557         }
558     }
559
560     /**
561      * Indicates that a new #PCDATA element has been encountered.
562      *
563      * @param systemId the system ID of the XML data of the element.
564      * @param lineNr the line number in the XML data of the element.
565      */

566     public void PCDataAdded(String JavaDoc systemId, int lineNr)
567     {
568         // nothing to do
569
}
570
571 }
572
Popular Tags