001: /*
002: * The contents of this file are subject to the terms
003: * of the Common Development and Distribution License
004: * (the License). You may not use this file except in
005: * compliance with the License.
006: *
007: * You can obtain a copy of the license at
008: * https://glassfish.dev.java.net/public/CDDLv1.0.html.
009: * See the License for the specific language governing
010: * permissions and limitations under the License.
011: *
012: * When distributing Covered Code, include this CDDL
013: * Header Notice in each file and include the License file
014: * at https://glassfish.dev.java.net/public/CDDLv1.0.html.
015: * If applicable, add the following below the CDDL Header,
016: * with the fields enclosed by brackets [] replaced by
017: * you own identifying information:
018: * "Portions Copyrighted [year] [name of copyright owner]"
019: *
020: * Copyright 2006 Sun Microsystems Inc. All Rights Reserved
021: */
022:
023: /*
024: * SAXC14nCanonicalzerImpl.java
025: *
026: * Created on August 20, 2005, 5:10 PM
027: *
028: * To change this template, choose Tools | Options and locate the template under
029: * the Source Creation and Management node. Right-click the template and choose
030: * Open. You can then make changes to the template in the Source Editor.
031: */
032:
033: package com.sun.xml.wss.impl.c14n;
034:
035: import java.io.IOException;
036: import java.util.ArrayList;
037: import java.util.Iterator;
038:
039: import org.xml.sax.Attributes;
040: import org.xml.sax.ContentHandler;
041: import org.xml.sax.Locator;
042: import org.xml.sax.SAXException;
043: import org.xml.sax.helpers.NamespaceSupport;
044:
045: /**
046: *
047: * @author K.Venugopal@sun.com
048: */
049: public class SAXC14nCanonicalizerImpl extends BaseCanonicalizer
050: implements ContentHandler {
051:
052: NamespaceSupport nsContext = new NamespaceSupport();
053:
054: //boolean firstElement = true;
055:
056: /** Creates a new instance of SAXC14nCanonicalzerImpl */
057: public SAXC14nCanonicalizerImpl() {
058: //_attrResult = new TreeSet (new AttrSorter (false));
059: _attrResult = new ArrayList();
060: for (int i = 0; i < 4; i++) {
061: _attrs.add(new Attribute());
062: }
063: }
064:
065: public NamespaceSupport getNSContext() {
066: return nsContext;
067: }
068:
069: /**
070: * Receive notification of a parser warning.
071: *
072: * <p>The default implementation does nothing. Application writers
073: * may override this method in a subclass to take specific actions
074: * for each warning, such as inserting the message in a log file or
075: * printing it to the console.</p>
076: *
077: * @param e The warning information encoded as an exception.
078: * @exception org.xml.sax.SAXException Any SAX exception, possibly
079: * wrapping another exception.
080: * @see org.xml.sax.ErrorHandler#warning
081: * @see org.xml.sax.SAXParseException
082: */
083: public void warning(org.xml.sax.SAXParseException e)
084: throws SAXException {
085:
086: }
087:
088: /**
089: * Receive notification of a recoverable parser error.
090: *
091: * <p>The default implementation does nothing. Application writers
092: * may override this method in a subclass to take specific actions
093: * for each error, such as inserting the message in a log file or
094: * printing it to the console.</p>
095: *
096: * @param e The warning information encoded as an exception.
097: * @exception org.xml.sax.SAXException Any SAX exception, possibly
098: * wrapping another exception.
099: * @see org.xml.sax.ErrorHandler#warning
100: * @see org.xml.sax.SAXParseException
101: */
102: public void error(org.xml.sax.SAXParseException e)
103: throws SAXException {
104:
105: }
106:
107: /**
108: * Report a fatal XML parsing error.
109: *
110: * <p>The default implementation throws a SAXParseException.
111: * Application writers may override this method in a subclass if
112: * they need to take specific actions for each fatal error (such as
113: * collecting all of the errors into a single report): in any case,
114: * the application must stop all regular processing when this
115: * method is invoked, since the document is no longer reliable, and
116: * the parser may no longer report parsing events.</p>
117: *
118: * @param e The error information encoded as an exception.
119: * @exception org.xml.sax.SAXException Any SAX exception, possibly
120: * wrapping another exception.
121: * @see org.xml.sax.ErrorHandler#fatalError
122: * @see org.xml.sax.SAXParseException
123: */
124: public void fatalError(org.xml.sax.SAXParseException e)
125: throws SAXException {
126:
127: }
128:
129: public void comment(char[] ch, int start, int length)
130: throws SAXException {
131:
132: }
133:
134: /**
135: * Receive notification of character data inside an element.
136: *
137: * <p>By default, do nothing. Application writers may override this
138: * method to take specific actions for each chunk of character data
139: * (such as adding the data to a node or buffer, or printing it to
140: * a file).</p>
141: *
142: * @param ch The characters.
143: * @param start The start position in the character array.
144: * @param length The number of characters to use from the
145: * character array.
146: * @exception org.xml.sax.SAXException Any SAX exception, possibly
147: * wrapping another exception.
148: * @see org.xml.sax.ContentHandler#characters
149: */
150: public void characters(char[] ch, int start, int length)
151: throws SAXException {
152: try {
153: outputTextToWriter(ch, start, length, _stream);
154: } catch (IOException ex) {
155: throw new RuntimeException(ex);
156: }
157: }
158:
159: /**
160: * Receive notification of ignorable whitespace in element content.
161: *
162: * <p>By default, do nothing. Application writers may override this
163: * method to take specific actions for each chunk of ignorable
164: * whitespace (such as adding data to a node or buffer, or printing
165: * it to a file).</p>
166: *
167: * @param ch The whitespace characters.
168: * @param start The start position in the character array.
169: * @param length The number of characters to use from the
170: * character array.
171: * @exception org.xml.sax.SAXException Any SAX exception, possibly
172: * wrapping another exception.
173: * @see org.xml.sax.ContentHandler#ignorableWhitespace
174: */
175: public void ignorableWhitespace(char[] ch, int start, int length)
176: throws SAXException {
177:
178: }
179:
180: public void endEntity(String name) throws SAXException {
181:
182: }
183:
184: public void startEntity(String name) throws SAXException {
185:
186: }
187:
188: /**
189: * Receive notification of the end of a Namespace mapping.
190: *
191: * <p>By default, do nothing. Application writers may override this
192: * method in a subclass to take specific actions at the end of
193: * each prefix mapping.</p>
194: *
195: * @param prefix The Namespace prefix being declared.
196: * @exception org.xml.sax.SAXException Any SAX exception, possibly
197: * wrapping another exception.
198: * @see org.xml.sax.ContentHandler#endPrefixMapping
199: */
200: public void endPrefixMapping(String prefix) throws SAXException {
201:
202: }
203:
204: /**
205: * Receive a Locator object for document events.
206: *
207: * <p>By default, do nothing. Application writers may override this
208: * method in a subclass if they wish to store the locator for use
209: * with other document events.</p>
210: *
211: * @param locator A locator for all SAX document events.
212: * @see org.xml.sax.ContentHandler#setDocumentLocator
213: * @see org.xml.sax.Locator
214: */
215: public void setDocumentLocator(Locator locator) {
216:
217: }
218:
219: /**
220: * Receive notification of a skipped entity.
221: *
222: * <p>By default, do nothing. Application writers may override this
223: * method in a subclass to take specific actions for each
224: * processing instruction, such as setting status variables or
225: * invoking other methods.</p>
226: *
227: * @param name The name of the skipped entity.
228: * @exception org.xml.sax.SAXException Any SAX exception, possibly
229: * wrapping another exception.
230: * @see org.xml.sax.ContentHandler#processingInstruction
231: */
232: public void skippedEntity(String name) throws SAXException {
233: }
234:
235: /**
236: * Receive notification of an unparsed entity declaration.
237: *
238: * <p>By default, do nothing. Application writers may override this
239: * method in a subclass to keep track of the unparsed entities
240: * declared in a document.</p>
241: *
242: * @param name The entity name.
243: * @param publicId The entity public identifier, or null if not
244: * available.
245: * @param systemId The entity system identifier.
246: * @param notationName The name of the associated notation.
247: * @exception org.xml.sax.SAXException Any SAX exception, possibly
248: * wrapping another exception.
249: * @see org.xml.sax.DTDHandler#unparsedEntityDecl
250: */
251: public void unparsedEntityDecl(String name, String publicId,
252: String systemId, String notationName) throws SAXException {
253:
254: }
255:
256: /**
257: * Receive notification of the start of a Namespace mapping.
258: *
259: * <p>By default, do nothing. Application writers may override this
260: * method in a subclass to take specific actions at the start of
261: * each Namespace prefix scope (such as storing the prefix mapping).</p>
262: *
263: * @param prefix The Namespace prefix being declared.
264: * @param uri The Namespace URI mapped to the prefix.
265: * @exception org.xml.sax.SAXException Any SAX exception, possibly
266: * wrapping another exception.
267: * @see org.xml.sax.ContentHandler#startPrefixMapping
268: */
269: public void startPrefixMapping(String prefix, String uri)
270: throws SAXException {
271:
272: String dURI = nsContext.getURI(prefix);
273: boolean add = false;
274: if (dURI == null || !uri.equals(dURI)) {
275: add = true;
276: }
277:
278: if (add && !_ncContextState[_depth]) {
279: nsContext.pushContext();
280:
281: _ncContextState[_depth] = true;
282: }
283: if (add) {
284: if (prefix.length() == 0) {
285: _defURI = uri;
286: } else {
287: nsContext.declarePrefix(prefix, uri);
288: AttributeNS attrNS = getAttributeNS();
289: attrNS.setPrefix(prefix);
290: attrNS.setUri(uri);
291: _nsResult.add(attrNS);
292: }
293: }
294: }
295:
296: public void reset() {
297: super .reset();
298: nsContext.reset();
299: }
300:
301: /**
302: * Receive notification of the start of an element.
303: *
304: * <p>By default, do nothing. Application writers may override this
305: * method in a subclass to take specific actions at the start of
306: * each element (such as allocating a new tree node or writing
307: * output to a file).</p>
308: *
309: * @param uri The Namespace URI, or the empty string if the
310: * element has no Namespace URI or if Namespace
311: * processing is not being performed.
312: * @param localName The local name (without prefix), or the
313: * empty string if Namespace processing is not being
314: * performed.
315: * @param qName The qualified name (with prefix), or the
316: * empty string if qualified names are not available.
317: * @param attributes The attributes attached to the element. If
318: * there are no attributes, it shall be an empty
319: * Attributes object.
320: * @exception org.xml.sax.SAXException Any SAX exception, possibly
321: * wrapping another exception.
322: * @see org.xml.sax.ContentHandler#startElement
323: */
324: public void startElement(String uri, String localName,
325: String qName, Attributes attributes) throws SAXException {
326: try {
327:
328: _depth++;
329: _ncContextState[_depth] = false;
330: _stream.write('<');
331: if (qName.length() > 0) {
332: writeStringToUtf8(qName, _stream);
333: } else {
334: writeStringToUtf8(localName, _stream);
335: }
336: if (attributes.getLength() > 0 || _nsResult.size() > 0) {
337: handleAttributes(attributes);
338: }
339: _stream.write('>');
340:
341: _attrNSPos = 0;
342: _attrPos = 0;
343:
344: _defURI = null;
345:
346: _nsResult.clear();
347: _attrResult.clear();
348: } catch (IOException ex) {
349: throw new RuntimeException(ex);
350: }
351: }
352:
353: /**
354: * Receive notification of the beginning of the document.
355: *
356: * <p>By default, do nothing. Application writers may override this
357: * method in a subclass to take specific actions at the beginning
358: * of a document (such as allocating the root node of a tree or
359: * creating an output file).</p>
360: *
361: * @exception org.xml.sax.SAXException Any SAX exception, possibly
362: * wrapping another exception.
363: * @see org.xml.sax.ContentHandler#startDocument
364: */
365: public void startDocument() throws SAXException {
366:
367: //super.startDocument ();
368: }
369:
370: public void startDTD(String name, String publicId, String systemId)
371: throws SAXException {
372:
373: // super.startDTD (name, publicId, systemId);
374: }
375:
376: public void startCDATA() throws SAXException {
377:
378: //super.startCDATA ();
379: }
380:
381: /**
382: * Tells the parser to resolve the systemId against the baseURI
383: * and read the entity text from that resulting absolute URI.
384: * Note that because the older
385: * {@link DefaultHandler#resolveEntity DefaultHandler.resolveEntity()},
386: * method is overridden to call this one, this method may sometimes
387: * be invoked with null <em>name</em> and <em>baseURI</em>, and
388: * with the <em>systemId</em> already absolutized.
389: */
390: public org.xml.sax.InputSource resolveEntity(String name,
391: String publicId, String baseURI, String systemId)
392: throws SAXException, java.io.IOException {
393: throw new UnsupportedOperationException("Not yet implemented");
394: }
395:
396: /**
397: * Invokes
398: * {@link EntityResolver2#resolveEntity EntityResolver2.resolveEntity()}
399: * with null entity name and base URI.
400: * You only need to override that method to use this class.
401: */
402: public org.xml.sax.InputSource resolveEntity(String publicId,
403: String systemId) throws SAXException, java.io.IOException {
404: return null;
405: }
406:
407: public void internalEntityDecl(String name, String value)
408: throws SAXException {
409: throw new UnsupportedOperationException("Not yet implemented");
410:
411: }
412:
413: /**
414: * Tells the parser that if no external subset has been declared
415: * in the document text, none should be used.
416: */
417: public org.xml.sax.InputSource getExternalSubset(String name,
418: String baseURI) throws SAXException, java.io.IOException {
419: throw new UnsupportedOperationException("Not yet implemented");
420: }
421:
422: public void externalEntityDecl(String name, String publicId,
423: String systemId) throws SAXException {
424: }
425:
426: public void endDTD() throws SAXException {
427: }
428:
429: public void endCDATA() throws SAXException {
430: }
431:
432: public void elementDecl(String name, String model)
433: throws SAXException {
434: }
435:
436: public void attributeDecl(String eName, String aName, String type,
437: String mode, String value) throws SAXException {
438:
439: }
440:
441: /**
442: * Receive notification of the end of the document.
443: *
444: * <p>By default, do nothing. Application writers may override this
445: * method in a subclass to take specific actions at the end
446: * of a document (such as finalising a tree or closing an output
447: * file).</p>
448: *
449: * @exception org.xml.sax.SAXException Any SAX exception, possibly
450: * wrapping another exception.
451: * @see org.xml.sax.ContentHandler#endDocument
452: */
453: public void endDocument() throws SAXException {
454:
455: }
456:
457: /**
458: * Receive notification of the end of an element.
459: *
460: * <p>By default, do nothing. Application writers may override this
461: * method in a subclass to take specific actions at the end of
462: * each element (such as finalising a tree node or writing
463: * output to a file).</p>
464: *
465: * @param uri The Namespace URI, or the empty string if the
466: * element has no Namespace URI or if Namespace
467: * processing is not being performed.
468: * @param localName The local name (without prefix), or the
469: * empty string if Namespace processing is not being
470: * performed.
471: * @param qName The qualified name (with prefix), or the
472: * empty string if qualified names are not available.
473: * @exception org.xml.sax.SAXException Any SAX exception, possibly
474: * wrapping another exception.
475: * @see org.xml.sax.ContentHandler#endElement
476: */
477: public void endElement(String uri, String localName, String qName)
478: throws SAXException {
479: _depth--;
480: if (_ncContextState[_depth]) {
481: nsContext.popContext();
482: _ncContextState[_depth] = false;
483: }
484: try {
485: _stream.write(_END_TAG);
486: if (qName.length() > 0) {
487: writeStringToUtf8(qName, _stream);
488: } else {
489: writeStringToUtf8(localName, _stream);
490: }
491: _stream.write('>');
492: } catch (IOException io) {
493: throw new RuntimeException(io);
494: }
495: }
496:
497: /**
498: * Receive notification of a notation declaration.
499: *
500: * <p>By default, do nothing. Application writers may override this
501: * method in a subclass if they wish to keep track of the notations
502: * declared in a document.</p>
503: *
504: * @param name The notation name.
505: * @param publicId The notation public identifier, or null if not
506: * available.
507: * @param systemId The notation system identifier.
508: * @exception org.xml.sax.SAXException Any SAX exception, possibly
509: * wrapping another exception.
510: * @see org.xml.sax.DTDHandler#notationDecl
511: */
512: public void notationDecl(String name, String publicId,
513: String systemId) throws SAXException {
514: }
515:
516: /**
517: * Receive notification of a processing instruction.
518: *
519: * <p>By default, do nothing. Application writers may override this
520: * method in a subclass to take specific actions for each
521: * processing instruction, such as setting status variables or
522: * invoking other methods.</p>
523: *
524: * @param target The processing instruction target.
525: * @param data The processing instruction data, or null if
526: * none is supplied.
527: * @exception org.xml.sax.SAXException Any SAX exception, possibly
528: * wrapping another exception.
529: * @see org.xml.sax.ContentHandler#processingInstruction
530: */
531: public void processingInstruction(String target, String data)
532: throws SAXException {
533: }
534:
535: //TODO:: Optimize
536: private void handleAttributes(Attributes attributes) {
537: int length = attributes.getLength();
538: String localName = null;
539: boolean contextPushed = false;
540: try {
541:
542: for (int i = 0; i < length; i++) {
543: Attribute attr = getAttribute();
544: attr.setPosition(i);
545: attr.setAttributes(attributes);
546: _attrResult.add(attr);
547: }
548:
549: if (_defURI != null) {
550: outputAttrToWriter("xmlns", _defURI, _stream);
551: }
552: Iterator itr = _nsResult.iterator();
553: writeAttributesNS(itr);
554: BaseCanonicalizer.sort(_attrResult);
555: writeAttributes(attributes, _attrResult.iterator());
556: _nsResult.clear();
557: _attrResult.clear();
558: } catch (IOException io) {
559: throw new RuntimeException(io);
560: }
561: }
562:
563: protected Attribute getAttribute() {
564: if (_attrPos < _attrs.size()) {
565: return (Attribute) _attrs.get(_attrPos++);
566: } else {
567: for (int i = 0; i < 4; i++) {
568: _attrs.add(new Attribute());
569: }
570: return (Attribute) _attrs.get(_attrPos++);
571: }
572: }
573:
574: }
|