001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.portal.transformation;
018:
019: import java.io.IOException;
020: import java.io.Serializable;
021: import java.util.Map;
022:
023: import org.apache.avalon.framework.parameters.Parameters;
024: import org.apache.cocoon.ProcessingException;
025: import org.apache.cocoon.caching.CacheableProcessingComponent;
026: import org.apache.cocoon.environment.SourceResolver;
027: import org.apache.cocoon.transformation.AbstractTransformer;
028: import org.apache.cocoon.xml.XMLUtils;
029: import org.apache.commons.lang.BooleanUtils;
030: import org.apache.excalibur.source.SourceValidity;
031: import org.apache.excalibur.source.impl.validity.NOPValidity;
032: import org.xml.sax.Attributes;
033: import org.xml.sax.SAXException;
034:
035: /**
036: * This transformer is an utility transformer for dealing with (x)html content.
037: * It has two operating modes:
038: *
039: * Add Mode (default): The transformer simply adds an html and a body element
040: * around the sax stream.
041: *
042: * Remove Mode: The transformer removes all surrounding elements like html and body
043: * and only passes everything on to the next pipeline component that's contained
044: * in a body element.
045: *
046: * @author <a href="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
047: * @author <a href="mailto:volker.schmitt@basf-it-services.com">Volker Schmitt</a>
048: *
049: * @version CVS $Id: HTMLRootTransformer.java 433543 2006-08-22 06:22:54Z crossley $
050: */
051: public class HTMLRootTransformer extends AbstractTransformer implements
052: CacheableProcessingComponent {
053:
054: /** the operating mode: true means adding the root elements, false means removing them */
055: protected boolean addMode;
056:
057: /** do we remove the root tag? */
058: protected boolean ignoreRootElement;
059: protected int ignoreRootElementCount;
060:
061: protected boolean insideBodyTag;
062:
063: /* (non-Javadoc)
064: * @see org.apache.cocoon.sitemap.SitemapModelComponent#setup(org.apache.cocoon.environment.SourceResolver, java.util.Map, java.lang.String, org.apache.avalon.framework.parameters.Parameters)
065: */
066: public void setup(SourceResolver resolver, Map objectModel,
067: String src, Parameters par) throws ProcessingException,
068: SAXException, IOException {
069: this .addMode = par.getParameterAsBoolean("add-mode", true);
070: this .ignoreRootElement = par.getParameterAsBoolean(
071: "ignore-root", false);
072: this .ignoreRootElementCount = 0;
073: this .insideBodyTag = false;
074: }
075:
076: /* (non-Javadoc)
077: * @see org.xml.sax.ContentHandler#endDocument()
078: */
079: public void endDocument() throws SAXException {
080: if (this .addMode) {
081: XMLUtils.endElement(this .xmlConsumer, "body");
082: XMLUtils.endElement(this .xmlConsumer, "html");
083: }
084: super .endDocument();
085: }
086:
087: /* (non-Javadoc)
088: * @see org.xml.sax.ContentHandler#startDocument()
089: */
090: public void startDocument() throws SAXException {
091: super .startDocument();
092: if (this .addMode) {
093: XMLUtils.startElement(this .xmlConsumer, "html");
094: XMLUtils.startElement(this .xmlConsumer, "body");
095: }
096: }
097:
098: /* (non-Javadoc)
099: * @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)
100: */
101: public void startElement(String uri, String local, String qName,
102: Attributes attr) throws SAXException {
103: if (!this .ignoreRootElement || this .ignoreRootElementCount > 0) {
104: if (this .addMode || this .insideBodyTag) {
105: this .contentHandler.startElement(uri, local, qName,
106: attr);
107: }
108: }
109: if ("body".equals(local)) {
110: this .insideBodyTag = true;
111: }
112: this .ignoreRootElementCount++;
113: }
114:
115: /* (non-Javadoc)
116: * @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)
117: */
118: public void endElement(String uri, String local, String qName)
119: throws SAXException {
120: if ("body".equals(local)) {
121: this .insideBodyTag = false;
122: }
123: this .ignoreRootElementCount--;
124: if (!this .ignoreRootElement || this .ignoreRootElementCount > 0) {
125: if (this .addMode || this .insideBodyTag) {
126: this .contentHandler.endElement(uri, local, qName);
127: }
128: }
129: }
130:
131: /* (non-Javadoc)
132: * @see org.xml.sax.ContentHandler#characters(char[], int, int)
133: */
134: public void characters(char[] c, int start, int len)
135: throws SAXException {
136: if (this .addMode || this .insideBodyTag) {
137: super .characters(c, start, len);
138: }
139: }
140:
141: /* (non-Javadoc)
142: * @see org.apache.cocoon.caching.CacheableProcessingComponent#getKey()
143: */
144: public Serializable getKey() {
145: return new Boolean[] {
146: BooleanUtils.toBooleanObject(this .addMode),
147: BooleanUtils.toBooleanObject(this .ignoreRootElement) };
148: }
149:
150: /* (non-Javadoc)
151: * @see org.apache.cocoon.caching.CacheableProcessingComponent#getValidity()
152: */
153: public SourceValidity getValidity() {
154: return NOPValidity.SHARED_INSTANCE;
155: }
156: }
|