1 16 package org.outerj.daisy.publisher.serverimpl.docpreparation; 17 18 import org.xml.sax.*; 19 import org.xml.sax.helpers.AttributesImpl ; 20 import org.outerj.daisy.repository.*; 21 import org.outerj.daisy.xmlutil.SaxBuffer; 22 import org.outerj.daisy.util.Constants; 23 import org.outerj.daisy.publisher.serverimpl.AbstractHandler; 24 import org.outerj.daisy.publisher.serverimpl.PublisherImpl; 25 import org.outerj.daisy.publisher.serverimpl.StripDocumentHandler; 26 import org.outerj.daisy.publisher.serverimpl.requestmodel.PublisherContext; 27 import org.outerj.daisy.publisher.serverimpl.requestmodel.PublisherContextImpl; 28 import org.outerj.daisy.publisher.serverimpl.requestmodel.PublisherVersionMode; 29 import org.outerx.daisy.x10.DocumentDocument; 30 31 import java.util.ArrayList ; 32 import java.util.regex.Matcher ; 33 34 50 public class IncludesProcessor extends AbstractHandler implements ContentHandler { 51 private boolean inInclude; 52 private StringBuffer includeBuffer; 53 private SaxBuffer includeSaxBuffer; 54 private int nestedElementCounter = 0; 55 private int includeElementNesting; 56 private ContentProcessor owner; 57 private long documentBranchId = -1; 58 private long documentLanguageId; 59 60 private long currentDocumentId; 62 private long currentBranchId; 63 private long currentLanguageId; 64 private long currentVersionId; 65 66 public IncludesProcessor(Document document, ContentHandler consumer, ContentProcessor owner) { 67 super(consumer); 68 this.owner = owner; 69 this.documentBranchId = document.getBranchId(); 70 this.documentLanguageId = document.getLanguageId(); 71 } 72 73 public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException { 74 nestedElementCounter++; 75 76 if (!inInclude) { 77 if (localName.equals("pre") && namespaceURI.equals("")) { 78 String clazz = atts.getValue("class"); 79 if (clazz != null && clazz.equals("include")) { 80 inInclude = true; 81 includeBuffer = new StringBuffer (); 82 includeSaxBuffer = new SaxBuffer(); 83 includeElementNesting = nestedElementCounter; 84 } 85 } 86 } 87 88 if (!inInclude) 89 consumer.startElement(namespaceURI, localName, qName, atts); 90 else 91 includeSaxBuffer.startElement(namespaceURI, localName, qName, atts); 92 } 93 94 public void endElement(String namespaceURI, String localName, String qName) throws SAXException { 95 if (!inInclude) { 96 consumer.endElement(namespaceURI, localName, qName); 97 } else { 98 includeSaxBuffer.endElement(namespaceURI, localName, qName); 99 } 100 101 if (inInclude && includeElementNesting == nestedElementCounter) { 102 inInclude = false; 103 104 String url = includeBuffer.toString(); 105 url = url.trim(); 106 107 if (url.startsWith("daisy:")) { 108 int spacePos = url.indexOf(' '); 110 if (spacePos != -1) 111 url = url.substring(0, spacePos); 112 processDaisyInclude(url); 113 } else { 114 includeSaxBuffer.toSAX(consumer); 116 } 117 } 118 119 nestedElementCounter--; 120 } 121 122 125 private void processDaisyInclude(String url) throws SAXException { 126 if (documentBranchId == -1) 127 throw new SAXException("Error in " + getClass().getName() + ": documentBranchId was not yet determined when an include was encountered."); 128 129 long documentId; 130 long versionId = owner.getPublisherContext().getVersionMode() == PublisherVersionMode.LAST ? -2 : -1; 132 Matcher matcher = Constants.DAISY_LINK_PATTERN.matcher(url); 133 if (!matcher.matches()) { 134 outputError("Error including document: Invalid document reference: " + url); 135 return; 136 } 137 138 String documentIdString = matcher.group(1); 139 String branch = matcher.group(3); 140 String language = matcher.group(5); 141 String versionString = matcher.group(7); 142 143 try { 144 documentId = Long.parseLong(documentIdString); 145 if (versionString != null) { 146 if (versionString.equalsIgnoreCase("last")) { 147 versionId = -2; 148 } else if (versionString.equalsIgnoreCase("live")) { 149 versionId = -1; 150 } else { 151 versionId = Long.parseLong(versionString); 152 } 153 } 154 } catch (NumberFormatException e) { 155 outputError("Error including document: Invalid document reference: " + url); 156 return; 157 } 158 159 if (branch == null || branch.equals("")) 162 branch = String.valueOf(documentBranchId); 163 if (language == null || language.equals("")) 164 language = String.valueOf(documentLanguageId); 165 166 Document document; 167 Version version; 168 DocumentDocument documentDocument; 169 try { 170 document = owner.getPreparationPipe().getRepository().getDocument(documentId, branch, language, false); 171 if (versionId != -1 && versionId != -2) { 172 version = document.getVersion(versionId); 173 } else if (versionId == -2) { 174 version = document.getLastVersion(); 175 } else { 176 version = document.getLiveVersion(); 177 if (version == null) { 178 outputError("Error including document: no live version available. (document id: " + documentId + ")"); 179 return; 180 } 181 } 182 documentDocument = document.getXml(version.getId()); 183 } catch (Exception e) { 184 StringBuffer error = new StringBuffer ("Error including document: "); 185 error.append(e.getMessage()); 186 Throwable cause = e.getCause(); 187 while (cause != null) { 188 error.append(": ").append(cause.getMessage()); 189 } 190 outputError(error.toString()); 191 return; 192 } 193 194 currentDocumentId = documentId; 195 currentBranchId = documentDocument.getDocument().getBranchId(); 196 currentLanguageId = documentDocument.getDocument().getLanguageId(); 197 currentVersionId = documentDocument.getDocument().getDataVersionId(); 198 199 String recursionDescription = detectRecursiveInclude(); 200 if (recursionDescription != null) { 201 outputError("Error including document: recursive include detected: " + recursionDescription); 202 } else { 203 PublisherContext publisherContext = owner.getPublisherContext(); 204 PreparedDocuments preparedDocuments = publisherContext.getPreparedDocuments(); 205 if (preparedDocuments == null) 206 throw new SAXException("Unexpected error: preparedDocuments is not available in IncludesProcessor."); 207 PublisherImpl publisher = publisherContext.getPublisher(); 208 PublisherContextImpl childPublisherContext = new PublisherContextImpl(publisherContext); 209 childPublisherContext.setContentProcessor(owner); 210 childPublisherContext.setDocumentVariant(document.getId(), document.getBranchId(), document.getLanguageId()); 211 childPublisherContext.setVersionId(version.getId()); 212 213 PreparedDocuments.PreparedDocument preparedDocument = preparedDocuments.getNewPreparedDocument(document.getVariantKey()); 214 try { 215 publisher.performRequest(preparedDocuments.getPubReqSet(), document, version, childPublisherContext, 216 new StripDocumentHandler(preparedDocument.getSaxBuffer())); 217 } catch (Exception e) { 218 throw new SAXException(e); 219 } 220 221 AttributesImpl attrs = new AttributesImpl (); 222 attrs.addAttribute("", "id", "id", "CDATA", String.valueOf(preparedDocument.getId())); 223 consumer.startElement(PublisherImpl.NAMESPACE, "daisyPreparedInclude", "daisyPreparedInclude", attrs); 224 consumer.endElement(PublisherImpl.NAMESPACE, "daisyPreparedInclude", "daisyPreparedInclude"); 225 } 226 227 currentDocumentId = -1; 228 currentBranchId = -1; 229 currentLanguageId = -1; 230 currentVersionId = -1; 231 } 232 233 237 private String detectRecursiveInclude() { 238 ArrayList parents = new ArrayList (); 239 parents.add(this); 240 241 ContentProcessor cpParent = owner.getParent(); 242 while (cpParent != null) { 243 IncludesProcessor parent = cpParent.getIncludesProcessor(); 244 parents.add(parent); 245 246 if (parent.currentDocumentId == this.currentDocumentId 247 && parent.currentBranchId == this.currentBranchId 248 && parent.currentLanguageId == this.currentLanguageId 249 && parent.currentVersionId == this.currentVersionId) { 250 251 StringBuffer recursionDescription = new StringBuffer (); 253 for (int i = parents.size() - 1; i >=0; i--) { 254 IncludesProcessor current = (IncludesProcessor)parents.get(i); 255 if (recursionDescription.length() > 0) 256 recursionDescription.append(" -> "); 257 recursionDescription.append("document ").append(current.currentDocumentId).append(", branch ").append(current.currentBranchId).append(", language ").append(current.currentLanguageId).append(", version ").append(current.currentVersionId); 258 } 259 260 return recursionDescription.toString(); 261 } 262 cpParent = cpParent.getParent(); 263 } 264 return null; 265 } 266 267 public void endDocument() throws SAXException { 268 if (!inInclude) 269 consumer.endDocument(); 270 else 271 includeSaxBuffer.endDocument(); 272 } 273 274 public void startDocument() throws SAXException { 275 if (!inInclude) 276 consumer.startDocument(); 277 else 278 includeSaxBuffer.startDocument(); 279 } 280 281 public void characters(char ch[], int start, int length) throws SAXException { 282 if (inInclude) { 283 includeBuffer.append(ch, start, length); 284 includeSaxBuffer.characters(ch, start, length); 285 } else { 286 consumer.characters(ch, start, length); 287 } 288 } 289 290 public void ignorableWhitespace(char ch[], int start, int length) throws SAXException { 291 if (!inInclude) 292 consumer.ignorableWhitespace(ch, start, length); 293 else 294 includeSaxBuffer.characters(ch, start, length); 295 } 296 297 public void endPrefixMapping(String prefix) throws SAXException { 298 if (!inInclude) 299 consumer.endPrefixMapping(prefix); 300 else 301 includeSaxBuffer.endPrefixMapping(prefix); 302 } 303 304 public void skippedEntity(String name) throws SAXException { 305 if (!inInclude) 306 consumer.skippedEntity(name); 307 else 308 includeSaxBuffer.skippedEntity(name); 309 } 310 311 public void setDocumentLocator(Locator locator) { 312 if (!inInclude) 313 consumer.setDocumentLocator(locator); 314 else 315 includeSaxBuffer.setDocumentLocator(locator); 316 } 317 318 public void processingInstruction(String target, String data) throws SAXException { 319 if (!inInclude) 320 consumer.processingInstruction(target, data); 321 else 322 includeSaxBuffer.processingInstruction(target, data); 323 } 324 325 public void startPrefixMapping(String prefix, String uri) throws SAXException { 326 if (!inInclude) 327 consumer.startPrefixMapping(prefix, uri); 328 else 329 includeSaxBuffer.startPrefixMapping(prefix, uri); 330 } 331 332 } 333 | Popular Tags |