| 1 16 package org.outerj.daisy.books.publisher.impl.publicationprocess; 17 18 import org.outerj.daisy.books.publisher.impl.BookInstanceLayout; 19 import org.outerj.daisy.xmlutil.XmlSerializer; 20 import org.outerj.daisy.xmlutil.LocalSAXParserFactory; 21 import org.xml.sax.*; 22 23 import javax.xml.parsers.SAXParser ; 24 import java.io.InputStream ; 25 import java.io.OutputStream ; 26 import java.io.IOException ; 27 import java.util.Set ; 28 import java.util.HashSet ; 29 import java.util.Iterator ; 30 31 public class WriteChunksTask implements PublicationProcessTask { 32 private final String chunkFileExtension; 33 private final String outputPrefix; 34 private final String input; 35 private final String applyPipeline; 36 private final String pipelineOutputPrefix; 37 private final String chunkAfterPipelineFileExtension; 38 39 public WriteChunksTask(String input, String outputPrefix, String chunkFileExtension, String applyPipeline, 40 String pipelineOutputPrefix, String chunkAfterPipelineFileExtension) { 41 this.input = input; 42 this.outputPrefix = outputPrefix; 43 this.chunkFileExtension = chunkFileExtension; 44 this.applyPipeline = applyPipeline; 45 this.pipelineOutputPrefix = pipelineOutputPrefix; 46 this.chunkAfterPipelineFileExtension = chunkAfterPipelineFileExtension != null ? chunkAfterPipelineFileExtension : ""; 47 } 48 49 public void run(PublicationContext context) throws Exception { 50 context.getPublicationLog().info("Running write chunks task."); 51 52 String publicationOutputPath = BookInstanceLayout.getPublicationOutputPath(context.getPublicationOutputName()); 53 String inputXml = publicationOutputPath + input; 54 55 InputStream is = null; 56 ChunkWriterHandler chunkWriter = null; 57 try { 58 SAXParser parser = LocalSAXParserFactory.getSAXParserFactory().newSAXParser(); 59 chunkWriter = new ChunkWriterHandler(context); 60 parser.getXMLReader().setContentHandler(chunkWriter); 61 is = context.getBookInstance().getResource(inputXml); 62 parser.getXMLReader().parse(new InputSource(is)); 63 } finally { 64 if (is != null) 65 is.close(); 66 if (chunkWriter != null) 67 chunkWriter.dispose(); 68 } 69 70 if (applyPipeline != null) { 72 Iterator writtenChunksIt = chunkWriter.getWrittenChunks().iterator(); 73 while (writtenChunksIt.hasNext()) { 74 String chunkName = (String )writtenChunksIt.next(); 75 String input = publicationOutputPath + outputPrefix + chunkName + chunkFileExtension; 76 String output = publicationOutputPath + pipelineOutputPrefix + chunkName + chunkAfterPipelineFileExtension; 77 ApplyPipelineTask.applyPipeline(context, applyPipeline, input, output); 78 } 79 } 80 } 81 82 class ChunkWriterHandler implements ContentHandler { 83 private final PublicationContext context; 84 private OutputStream os; 85 private XmlSerializer consumer; 86 private int nesting = 0; 87 private Set writtenChunks = new HashSet (); 88 89 public ChunkWriterHandler(PublicationContext context) { 90 this.context = context; 91 } 92 93 public void dispose() throws IOException { 94 if (os != null) 95 os.close(); 96 } 97 98 public Set getWrittenChunks() { 99 return writtenChunks; 100 } 101 102 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { 103 nesting++; 104 if (nesting == 2 && namespaceURI.equals("") && localName.equals("chunk")) { 105 if (os != null || consumer != null) 106 throw new SAXException("Chunk writer assertion error: new chunk and previous one is not yet finished."); 107 108 String chunkName = atts.getValue("name"); 109 String publicationOutputPath = BookInstanceLayout.getPublicationOutputPath(context.getPublicationOutputName()); 110 String outputBasePath = publicationOutputPath + outputPrefix + chunkName; 111 writtenChunks.add(chunkName); 112 String outputPath = outputBasePath + chunkFileExtension; 113 try { 114 os = context.getBookInstance().getResourceOutputStream(outputPath); 115 consumer = new XmlSerializer(os); 116 } catch (Exception e) { 117 throw new SAXException("Error initialising chunk output.", e); 118 } 119 consumer.startDocument(); 120 } else if (nesting == 1 && !(namespaceURI.equals("") && localName.equals("chunks"))) { 121 throw new SAXException("Invalid input: expected 'chunks' root element but got: " + qName); 122 } else if (consumer != null) { 123 consumer.startElement(namespaceURI, localName, qName, atts); 124 } 125 } 126 127 public void endElement(String namespaceURI, String localName, String qName) throws SAXException { 128 if (nesting == 2 && namespaceURI.equals("") && localName.equals("chunk")) { 129 consumer.endDocument(); 130 consumer = null; 131 try { 132 os.close(); 133 os = null; 134 } catch (IOException e) { 135 throw new SAXException("Error closing chunk output stream.", e); 136 } 137 } else if (consumer != null) { 138 consumer.endElement(namespaceURI, localName, qName); 139 } 140 nesting--; 141 } 142 143 public void characters(char ch[], int start, int length) throws SAXException { 144 if (consumer != null) 145 consumer.characters(ch, start, length); 146 } 147 148 public void ignorableWhitespace(char ch[], int start, int length) throws SAXException { 149 if (consumer != null) 150 consumer.ignorableWhitespace(ch, start, length); 151 } 152 153 public void endPrefixMapping(String prefix) throws SAXException { 154 if (consumer != null) 155 consumer.endPrefixMapping(prefix); 156 } 157 158 public void skippedEntity(String name) throws SAXException { 159 if (consumer != null) 160 consumer.skippedEntity(name); 161 } 162 163 public void setDocumentLocator(Locator locator) { 164 } 166 167 public void processingInstruction(String target, String data) throws SAXException { 168 if (consumer != null) 169 consumer.processingInstruction(target, data); 170 } 171 172 public void startPrefixMapping(String prefix, String uri) throws SAXException { 173 if (consumer != null) 174 consumer.startPrefixMapping(prefix, uri); 175 } 176 177 public void startDocument() throws SAXException { 178 } 180 181 public void endDocument() throws SAXException { 182 } 184 } 185 } 186 | Popular Tags |