/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You 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.cocoon.slop.generation; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.io.Serializable; import java.util.Map; import org.apache.avalon.framework.parameters.Parameters; import org.apache.cocoon.ProcessingException; import org.apache.cocoon.caching.CacheableProcessingComponent; import org.apache.cocoon.environment.SourceResolver; import org.apache.cocoon.generation.ServiceableGenerator; import org.apache.cocoon.slop.interfaces.SlopParser; import org.apache.cocoon.slop.parsing.SimpleSlopParser; import org.apache.excalibur.source.Source; import org.apache.excalibur.source.SourceException; import org.apache.excalibur.source.SourceValidity; import org.xml.sax.SAXException; import org.xml.sax.helpers.LocatorImpl; /** * SlopGenerator: Simple Line-Oriented Parsing of text files. * General code structure lifted from the Chaperon TextGenerator - thanks Stephan! * * @author <a href="mailto:bdelacretaz@apache.org">Bertrand Delacretaz</a> * @version CVS $Id$ */ public class SlopGenerator extends ServiceableGenerator implements CacheableProcessingComponent { private Source inputSource = null; private String encoding = null; private SlopParser parser = null; private boolean preserveSpace = false; private String validTagnameChars = null; /** * Recycle this component. * All instance variables are set to <code>null</code>. */ public void recycle() { if (inputSource != null) { super.resolver.release(inputSource); } inputSource = null; encoding = null; preserveSpace = false; parser = null; validTagnameChars = null; super.recycle(); } /** * Set the SourceResolver, objectModel Map, the source and sitemap * Parameters used to process the request. * * @param resolver Source resolver * @param objectmodel Object model * @param src Source * @param parameters Parameters * * @throws java.io.IOException * @throws org.apache.cocoon.ProcessingException * @throws org.xml.sax.SAXException */ public void setup(SourceResolver resolver, Map objectmodel, String src, Parameters parameters) throws ProcessingException, SAXException, IOException { super.setup(resolver, objectmodel, src, parameters); try { encoding = parameters.getParameter("encoding", null); preserveSpace = parameters.getParameterAsBoolean("preserve-space",false); validTagnameChars = parameters.getParameter("valid-tagname-chars",null); inputSource = resolver.resolveURI(src); final SimpleSlopParser ssp = new SimpleSlopParser(); parser = ssp; ssp.setPreserveWhitespace(preserveSpace); ssp.setValidTagnameChars(validTagnameChars); } catch (SourceException se) { throw new ProcessingException("Error during resolving of '" + src + "'.", se); } } /** * Generate the unique key. * This key must be unique inside the space of this component. * * @return The generated key hashes the src */ public Serializable getKey() { return inputSource.getURI(); } /** * Generate the validity object. * * @return The generated validity object or <code>null</code> if the * component is currently not cacheable. */ public SourceValidity getValidity() { return this.inputSource.getValidity(); } /** * Generate XML data. * * @throws java.io.IOException * @throws org.apache.cocoon.ProcessingException * @throws org.xml.sax.SAXException */ public void generate() throws IOException, SAXException, ProcessingException { // access input data, using specified encoding if any InputStreamReader in = null; try { if (this.inputSource.getInputStream() == null) { throw new ProcessingException("Source '" + this.inputSource.getURI() + "' not found"); } if (encoding != null) { in = new InputStreamReader(this.inputSource.getInputStream(), encoding); } else { in = new InputStreamReader(this.inputSource.getInputStream()); } } catch (SourceException se) { throw new ProcessingException("Error during resolving of '" + this.source + "'.", se); } // setup a Locator in case parser detects input errors final LocatorImpl locator = new LocatorImpl(); locator.setSystemId(this.inputSource.getURI()); locator.setLineNumber(1); locator.setColumnNumber(1); contentHandler.setDocumentLocator(locator); // start parsing, read and process all input lines parser.startDocument(contentHandler); LineNumberReader reader = new LineNumberReader(in); String line, newline = null; while (true) { if (newline == null) { line = reader.readLine(); } else { line = newline; } if (line == null) { break; } newline = reader.readLine(); locator.setLineNumber(reader.getLineNumber()); locator.setColumnNumber(1); parser.processLine(line); if (newline == null) { break; } } // done parsing parser.endDocument(); } }