/* * Copyright 2000-2004 The Apache Software Foundation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.jetspeed.util; //standard java stuff import java.io.InputStream; import java.io.PrintWriter; import java.io.Reader; import java.io.UnsupportedEncodingException; import java.util.Vector; // SAX classes import org.xml.sax.AttributeList; import org.xml.sax.HandlerBase; import org.xml.sax.InputSource; import org.xml.sax.Parser; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import org.xml.sax.helpers.ParserFactory; // Jetspeed classes import org.apache.jetspeed.services.logging.JetspeedLogFactoryService; import org.apache.jetspeed.services.logging.JetspeedLogger; /** This class is used to either strip and/or insert PIs in a XML document. It uses SAX-1 API and outputs text to an output stream. WARNING: This behavior will be modified in the future. @author <A HREF="mailto:raphael@apache.org">Rapha謖 Luta</A> @version $Id: SAXPIFilter.java,v 1.8 2004/02/23 03:23:42 jford Exp $ */ public class SAXPIFilter extends HandlerBase { /** * Static initialization of the logger for this class */ private static final JetspeedLogger logger = JetspeedLogFactoryService.getLogger(SAXPIFilter.class.getName()); private static final String DEFAULT_PARSER_NAME = "org.apache.xerces.parsers.SAXParser"; protected PrintWriter out=new PrintWriter(System.out); private String pi; private boolean stripExistingPI; private Vector pis = new Vector(); /** Creates of simple parser which outputs its document to the PrintWriter passed as arguments. In this mode the parser may be used as a simple well-formedness checker. @param outPW the printWriter where to output parsed data */ public SAXPIFilter(PrintWriter outPW) throws UnsupportedEncodingException { this(outPW,false,null); } /** In this mode the parser may be used as a simple well-formedness checker or a PI stripper. @param outPW the printWriter where to output parsed data @param strip configure the parser to strip PIs if strip is true */ public SAXPIFilter(PrintWriter outPW, boolean strip) throws UnsupportedEncodingException { this( outPW, strip, null ); } /** In this mode the parser can strip existing PIs and insert new ones just after the document declaration @param outPW the printWriter where to output parsed data @param strip configure the parser to strip PIs if strip is true @param PI string reprensenting the PI to be output after the document declaration */ public SAXPIFilter(PrintWriter outPW, boolean strip, String PI) throws UnsupportedEncodingException { this.out=outPW; this.stripExistingPI=strip; this.pi=PI; } /** Get all permitted processing instructions */ public String[] getProcessingInstructions() { String[] ins = new String[ pis.size() ]; pis.copyInto( ins ); return ins; } public void addProcessingInstruction(String pi) { this.pis.addElement( pi ); } /** Parse and output the content of the URL given as parameter. @param uri URL where to fetch the document to be parsed */ public void print(String uri) { try { HandlerBase handler = this; Parser parser = ParserFactory.makeParser(DEFAULT_PARSER_NAME); parser.setDocumentHandler(handler); parser.setErrorHandler(handler); parser.parse(uri); } catch (Exception e) { logger.error("Exception", e); } } /** Parse and output the content of the stream @param in a content InputStream */ public void print(InputStream in) { try { HandlerBase handler = this; Parser parser = ParserFactory.makeParser(DEFAULT_PARSER_NAME); parser.setDocumentHandler(handler); parser.setErrorHandler(handler); parser.parse(new InputSource(in)); } catch (Exception e) { logger.error("Exception", e); } } /** Parse and output the content of the reader @param in a content Reader */ public void print(Reader in) { try { HandlerBase handler = this; Parser parser = ParserFactory.makeParser(DEFAULT_PARSER_NAME); parser.setDocumentHandler(handler); parser.setErrorHandler(handler); parser.parse(new InputSource(in)); } catch (Exception e) { logger.error("Exception", e); } } /** SAX Handler implementation */ public void processingInstruction(String target, String data) { if ( ! stripExistingPI ) { out.print( makeSAXPI( target, data ) ); } else { //cocoon-process //if your original XML document has cocoon tags leave them in. //add exceptable processing instructions here. if ( target.equals("cocoon-process") ) { this.addProcessingInstruction( makeSAXPI( target, data ) ); } } } private String makeSAXPI( String target, String data ) { StringBuffer buffer = new StringBuffer(); buffer.append("<?"); buffer.append( target ); if (data != null && data.length() > 0) { buffer.append(' '); buffer.append(data); } buffer.append("?>"); return buffer.toString(); } /** SAX Handler implementation */ public void startDocument() { if ( pi != null ) { out.print( pi ); } } /** SAX Handler implementation */ public void startElement(String name, AttributeList attrs) { out.print('<'); out.print(name); if (attrs != null) { int len = attrs.getLength(); for (int i = 0; i < len; i++) { out.print(' '); out.print(attrs.getName(i)); out.print("=\""); out.print(normalize(attrs.getValue(i))); out.print('"'); } } out.print('>'); } /** SAX Handler implementation */ public void characters(char ch[], int start, int length) { out.print(normalize(new String(ch, start, length))); } /** SAX Handler implementation */ public void ignorableWhitespace(char ch[], int start, int length) { characters(ch, start, length); } /** SAX Handler implementation */ public void endElement(String name) { out.print("</"); out.print(name); out.print('>'); } /** SAX Handler implementation */ public void endDocument() { out.flush(); } /** SAX Handler implementation */ public void warning(SAXParseException ex) { System.err.println("[Warning] "+ getLocationString(ex)+": "+ ex.getMessage()); } /** SAX Handler implementation */ public void error(SAXParseException ex) { System.err.println("[Error] "+ getLocationString(ex)+": "+ ex.getMessage()); } /** SAX Handler implementation */ public void fatalError(SAXParseException ex) throws SAXException { System.err.println("[Fatal Error] "+ getLocationString(ex)+": "+ ex.getMessage()); throw ex; } /** Retrieves the error location in the input stream */ private String getLocationString(SAXParseException ex) { StringBuffer str = new StringBuffer(); String systemId = ex.getSystemId(); if (systemId != null) { int index = systemId.lastIndexOf('/'); if (index != -1) systemId = systemId.substring(index + 1); str.append(systemId); } str.append(':'); str.append(ex.getLineNumber()); str.append(':'); str.append(ex.getColumnNumber()); return str.toString(); } /** Escapes characters data */ protected String normalize(String s) { StringBuffer str = new StringBuffer(); int len = (s != null) ? s.length() : 0; for (int i = 0; i < len; i++) { char ch = s.charAt(i); switch (ch) { case '<': { str.append("<"); break; } case '>': { str.append(">"); break; } case '&': { str.append("&"); break; } case '"': { str.append("""); break; } default: { str.append(ch); } } } return str.toString(); } }