/** * Get the image binary data, with hexical output. For RTF transformation * * @param dirName - The directory name that will be added to the path of the image file. * @param fileName - The file name of the image file. * @return java.lang.String - The Hexical binary of image data converted to String. */ public static String getBinData(final String dirName, final String fileName) { final DITAOTJavaLogger logger = new DITAOTJavaLogger(); final File imgInput = new File(dirName, toFile(fileName).getPath()); FileInputStream binInput = null; try { String binStr = null; final StringBuilder ret = new StringBuilder(16 * 1024); binInput = new FileInputStream(imgInput); int bin = binInput.read(); while (bin != -1) { binStr = Integer.toHexString(bin); if (binStr.length() < 2) { ret.append("0"); } ret.append(binStr); bin = binInput.read(); } return ret.toString(); } catch (final Exception e) { logger.error(MessageUtils.getInstance().getMessage("DOTJ023E").toString()); logger.error(e.getMessage(), e); return null; } finally { if (binInput != null) { try { binInput.close(); } catch (final IOException ioe) { logger.error(ioe.getMessage(), ioe); } } } }
/** Constructor. */ public SeparateChunkTopicParser() { super(true); try { reader = getXMLReader(); reader.setContentHandler(this); reader.setFeature(FEATURE_NAMESPACE_PREFIX, true); } catch (final Exception e) { throw new RuntimeException("Failed to initialize XML parser: " + e.getMessage(), e); } }
/** Constructor. */ public ConrefPushReader() { pushtable = new Hashtable<>(); try { reader = XMLUtils.getXMLReader(); reader.setFeature(FEATURE_NAMESPACE_PREFIX, false); reader.setFeature(FEATURE_NAMESPACE, true); reader.setContentHandler(this); } catch (final Exception e) { throw new RuntimeException("Failed to initialize XML parser: " + e.getMessage(), e); } final DocumentBuilder documentBuilder = XMLUtils.getDocumentBuilder(); pushDocument = documentBuilder.newDocument(); }
@Override public void startElement( final String uri, final String localName, final String name, final Attributes atts) throws SAXException { if (ignoreDepth > 0) { ignoreDepth++; return; } if (PR_D_CODEREF.matches(atts)) { ignoreDepth++; try { final URI hrefValue = toURI(atts.getValue(ATTRIBUTE_NAME_HREF)); if (hrefValue != null) { File codeFile = toFile(stripFragment(currentFile.resolve(hrefValue))).getAbsoluteFile(); if (!codeFile.exists()) { final URI rel = job.tempDir.toURI().relativize(codeFile.toURI()); final Job.FileInfo fi = job.getFileInfo(rel); if (fi != null && fi.src.getScheme().equals("file")) { codeFile = new File(fi.src); } } if (codeFile.exists()) { logger.debug("Resolve coderef " + codeFile); final Charset charset = getCharset(atts.getValue(ATTRIBUTE_NAME_FORMAT)); try (BufferedReader codeReader = new BufferedReader(new InputStreamReader(new FileInputStream(codeFile), charset))) { copyLines(codeReader, new Range(hrefValue)); } catch (final Exception e) { logger.error("Failed to process code reference " + codeFile, e); } } else { logger.warn( MessageUtils.getInstance() .getMessage("DOTJ051E", hrefValue.toString()) .setLocation(atts) .toString()); } } else { // logger.logDebug("Code reference target not defined"); } } catch (final Exception e) { logger.error(e.getMessage(), e); } } else { super.startElement(uri, localName, name, atts); } }
@Override public void read(final File filename) { assert filename.isAbsolute(); fileDir = filename.getParentFile().getAbsoluteFile(); parsefilename = new File(filename.getName()); start = false; pushcontentWriter = getXMLStreamWriter(); pushType = null; try { reader.parse(filename.toURI().toString()); } catch (final RuntimeException e) { throw e; } catch (final Exception e) { logger.error(e.getMessage(), e); e.printStackTrace(); } }
/** * Get the first topic id. * * @param path file path * @param dir file dir * @param useCatalog whether use catalog file for validation * @return topic id */ public static String getFirstTopicId(final URI path, final File dir, final boolean useCatalog) { if (path == null && dir == null) { return null; } final DITAOTLogger logger = new DITAOTJavaLogger(); final StringBuilder firstTopicId = new StringBuilder(); final TopicIdParser parser = new TopicIdParser(firstTopicId); try { final XMLReader reader = XMLUtils.getXMLReader(); reader.setContentHandler(parser); if (useCatalog) { reader.setEntityResolver(CatalogUtils.getCatalogResolver()); } reader.parse(dir.toURI().resolve(path).toString()); } catch (final Exception e) { logger.error(e.getMessage(), e); } return firstTopicId.toString(); }
@Override public void write(final File filename) throws DITAOTException { // pass map's directory path filePath = filename; final String hrefValue = getValue(rootTopicref, ATTRIBUTE_NAME_HREF); final String copytoValue = getValue(rootTopicref, ATTRIBUTE_NAME_COPY_TO); final String scopeValue = getCascadeValue(rootTopicref, ATTRIBUTE_NAME_SCOPE); // Chimera path, has fragment String parseFilePath; final Collection<String> chunkValue = split(getValue(rootTopicref, ATTRIBUTE_NAME_CHUNK)); final String processRoleValue = getCascadeValue(rootTopicref, ATTRIBUTE_NAME_PROCESSING_ROLE); boolean dotchunk = false; if (copytoValue != null && !chunkValue.contains(CHUNK_TO_CONTENT)) { if (hrefValue != null && getFragment(hrefValue) != null) { parseFilePath = setFragment(copytoValue, getFragment(hrefValue)); } else { parseFilePath = copytoValue; } } else { parseFilePath = hrefValue; } // if @copy-to is processed in chunk module, the list file needs to be // updated. // Because @copy-to should be included in fulltopiclist, and the source // of coyy-to should be excluded in fulltopiclist. if (copytoValue != null && chunkValue.contains(CHUNK_TO_CONTENT)) { copyto.add(copytoValue); if (hrefValue != null && getFragment(hrefValue) != null) { copytoSource.add(stripFragment(hrefValue)); copytotarget2source.put(toURI(copytoValue), toURI(stripFragment(hrefValue))); } else { copytoSource.add(hrefValue); copytotarget2source.put(toURI(copytoValue), toURI(hrefValue)); } } try { if (parseFilePath != null && !ATTR_SCOPE_VALUE_EXTERNAL.equals(scopeValue) && !ATTR_PROCESSING_ROLE_VALUE_RESOURCE_ONLY.equals(processRoleValue)) { // if the path to target file make sense currentParsingFile = resolve(filePath, parseFilePath); File outputFileName; /* * FIXME: we have code flaws here, references in ditamap need to * be updated to new created file. */ String id = null; String firstTopicID = null; if (getFragment(parseFilePath) != null) { id = getFragment(parseFilePath); if (chunkValue.contains(CHUNK_SELECT_BRANCH)) { outputFileName = resolve(filePath, id + FILE_EXTENSION_DITA); targetTopicId = id; startFromFirstTopic = false; selectMethod = CHUNK_SELECT_BRANCH; } else if (chunkValue.contains(CHUNK_SELECT_DOCUMENT)) { firstTopicID = getFirstTopicId(resolve(filePath, parseFilePath).getPath()); topicDoc = getTopicDoc(resolve(filePath, parseFilePath).getPath()); if (firstTopicID != null) { outputFileName = resolve(filePath, firstTopicID + FILE_EXTENSION_DITA); targetTopicId = firstTopicID; } else { outputFileName = new File(currentParsingFile.getPath() + FILE_EXTENSION_CHUNK); dotchunk = true; targetTopicId = null; } selectMethod = CHUNK_SELECT_DOCUMENT; } else { outputFileName = resolve(filePath, id + FILE_EXTENSION_DITA); targetTopicId = id; startFromFirstTopic = false; selectMethod = CHUNK_SELECT_TOPIC; } } else { firstTopicID = getFirstTopicId(resolve(filePath, parseFilePath).getPath()); topicDoc = getTopicDoc(resolve(filePath, parseFilePath).getPath()); if (firstTopicID != null) { outputFileName = resolve(filePath, firstTopicID + FILE_EXTENSION_DITA); targetTopicId = firstTopicID; } else { outputFileName = new File(currentParsingFile.getPath() + FILE_EXTENSION_CHUNK); dotchunk = true; targetTopicId = null; } selectMethod = CHUNK_SELECT_DOCUMENT; } if (copytoValue != null) { // use @copy-to value as the new file name outputFileName = resolve(filePath, copytoValue); } if (outputFileName.exists()) { final File t = outputFileName; outputFileName = resolve(filePath, generateFilename()); conflictTable.put(outputFileName.getPath(), t.getPath()); dotchunk = false; } output = new OutputStreamWriter(new FileOutputStream(outputFileName), UTF8); outputFile = outputFileName; if (!dotchunk) { changeTable.put( resolveTopic(filePath, parseFilePath), setFragment(outputFileName.getPath(), id)); // new generated file changeTable.put(outputFileName.getPath(), outputFileName.getPath()); } // change the href value if (firstTopicID == null) { rootTopicref.setAttribute( ATTRIBUTE_NAME_HREF, setFragment( toURI( getRelativePath( new File(filePath, FILE_NAME_STUB_DITAMAP), outputFileName)), id) .toString()); } else { rootTopicref.setAttribute( ATTRIBUTE_NAME_HREF, setFragment( toURI( getRelativePath( new File(filePath, FILE_NAME_STUB_DITAMAP), outputFileName)), firstTopicID) .toString()); } include = false; // just a mark? stub = rootTopicref.getOwnerDocument().createElement(ELEMENT_STUB); siblingStub = rootTopicref.getOwnerDocument().createElement(ELEMENT_STUB); // <element> // <stub/> // ... // </element> // <siblingstub/> // ... // Place stub if (rootTopicref.hasChildNodes()) { final NodeList list = rootTopicref.getElementsByTagName(MAP_TOPICMETA.localName); if (list.getLength() > 0) { final Node node = list.item(0); final Node nextSibling = node.getNextSibling(); // no sibling so node is the last child if (nextSibling == null) { node.getParentNode().appendChild(stub); } else { // has sibling node node.getParentNode().insertBefore(stub, nextSibling); } } else { // no topicmeta tag. rootTopicref.insertBefore(stub, rootTopicref.getFirstChild()); } // element.insertBefore(stub,element.getFirstChild()); } else { rootTopicref.appendChild(stub); } // Place siblingStub if (rootTopicref.getNextSibling() != null) { rootTopicref.getParentNode().insertBefore(siblingStub, rootTopicref.getNextSibling()); } else { rootTopicref.getParentNode().appendChild(siblingStub); } reader.setErrorHandler(new DITAOTXMLErrorHandler(currentParsingFile.getPath(), logger)); reader.parse(currentParsingFile.toURI().toString()); output.flush(); // remove stub and siblingStub stub.getParentNode().removeChild(stub); siblingStub.getParentNode().removeChild(siblingStub); } } catch (final RuntimeException e) { throw e; } catch (final Exception e) { logger.error(e.getMessage(), e); } finally { try { if (output != null) { output.close(); output = null; if (dotchunk && !currentParsingFile.delete()) { logger.error( MessageUtils.getInstance() .getMessage("DOTJ009E", currentParsingFile.getPath(), outputFile.getPath()) .toString()); } if (dotchunk && !outputFile.renameTo(currentParsingFile)) { logger.error( MessageUtils.getInstance() .getMessage("DOTJ009E", currentParsingFile.getPath(), outputFile.getPath()) .toString()); } } } catch (final Exception ex) { logger.error(ex.getMessage(), ex); } } if (!copyto.isEmpty()) { updateList(); } }
private void processChunk(final Element topicref, final File outputFile) { final String hrefValue = getValue(topicref, ATTRIBUTE_NAME_HREF); final Collection<String> chunkValue = split(getValue(topicref, ATTRIBUTE_NAME_CHUNK)); final String copytoValue = getValue(topicref, ATTRIBUTE_NAME_COPY_TO); final String scopeValue = getCascadeValue(topicref, ATTRIBUTE_NAME_SCOPE); final String classValue = getValue(topicref, ATTRIBUTE_NAME_CLASS); final String processRoleValue = getCascadeValue(topicref, ATTRIBUTE_NAME_PROCESSING_ROLE); File outputFileName = outputFile; Writer tempWriter = null; Set<String> tempTopicID = null; targetTopicId = null; selectMethod = CHUNK_SELECT_DOCUMENT; include = false; boolean needWriteDitaTag = true; try { String parseFilePath; if (copytoValue != null && !chunkValue.contains(CHUNK_TO_CONTENT)) { if (getFragment(hrefValue) != null) { parseFilePath = setFragment(copytoValue, getFragment(hrefValue)); } else { parseFilePath = copytoValue; } } else { parseFilePath = hrefValue; } // if @copy-to is processed in chunk module, the list file needs to // be updated. // Because @copy-to should be included in fulltopiclist, and the // source of coyy-to should be excluded in fulltopiclist. if (copytoValue != null && chunkValue.contains(CHUNK_TO_CONTENT) && hrefValue != null) { copyto.add(copytoValue); if (getFragment(hrefValue) != null) { copytoSource.add(stripFragment(hrefValue)); copytotarget2source.put(toURI(copytoValue), toURI(stripFragment(hrefValue))); } else { copytoSource.add(hrefValue); copytotarget2source.put(toURI(copytoValue), toURI(hrefValue)); } } if (parseFilePath != null && !ATTR_SCOPE_VALUE_EXTERNAL.equals(scopeValue)) { // now the path to target file make sense if (chunkValue.contains(CHUNK_TO_CONTENT)) { // if current element contains "to-content" in chunk // attribute // we need to create new buffer and flush the buffer to // file // after processing is finished tempWriter = output; tempTopicID = topicID; output = new StringWriter(); topicID = new HashSet<String>(); if (MAP_MAP.matches(classValue)) { // Very special case, we have a map element with // href value. // This is a map that needs to be chunked to // content. // No need to parse any file, just generate a stub // output. outputFileName = resolve(filePath, parseFilePath); needWriteDitaTag = false; } else if (copytoValue != null) { // use @copy-to value as the new file name outputFileName = resolve(filePath, copytoValue); } else if (hrefValue != null) { // try to use href value as the new file name if (chunkValue.contains(CHUNK_SELECT_TOPIC) || chunkValue.contains(CHUNK_SELECT_BRANCH)) { if (getFragment(hrefValue) != null) { // if we have an ID here, use it. outputFileName = resolve(filePath, getFragment(hrefValue) + FILE_EXTENSION_DITA); } else { // Find the first topic id in target file if // any. final String firstTopic = getFirstTopicId(resolve(filePath, hrefValue).getPath()); if (firstTopic != null) { outputFileName = resolve(filePath, firstTopic + FILE_EXTENSION_DITA); } else { outputFileName = resolve(filePath, hrefValue); } } } else { // otherwise, use the href value instead outputFileName = resolve(filePath, hrefValue); } } else { // use randomly generated file name outputFileName = resolve(filePath, generateFilename()); } // Check if there is any conflict if (outputFileName.exists() && !MAP_MAP.matches(classValue)) { final File t = outputFileName; outputFileName = resolve(filePath, generateFilename()); conflictTable.put(outputFileName.getPath(), t.getPath()); } // add newly generated file to changTable // the new entry in changeTable has same key and value // in order to indicate it is a newly generated file changeTable.put(outputFileName.getPath(), outputFileName.getPath()); } // "by-topic" couldn't reach here this.outputFile = outputFileName; final String path = resolveTopic(filePath, parseFilePath); // FIXME: Should be URI String newpath; if (getFragment(path) != null) { newpath = setFragment(outputFileName.getPath(), getFragment(path)); } else { final String firstTopicID = getFirstTopicId(path); if (firstTopicID != null) { newpath = setFragment(outputFileName.getPath(), firstTopicID); } else { newpath = outputFileName.getPath(); } } // add file name changes to changeTable, this will be // used in // TopicRefWriter's updateHref method, very important!!! changeTable.put(path, newpath); // update current element's @href value topicref.setAttribute( ATTRIBUTE_NAME_HREF, getRelativeUnixPath(filePath + UNIX_SEPARATOR + FILE_NAME_STUB_DITAMAP, newpath)); if (getFragment(parseFilePath) != null) { targetTopicId = getFragment(parseFilePath); } final String s = getChunkByToken(chunkValue, "select-", null); if (s != null) { selectMethod = s; // if the current topic href referred to a entire // topic file,it will be handled in "document" level. if (targetTopicId == null) { selectMethod = CHUNK_SELECT_DOCUMENT; } } final File tempPath = currentParsingFile; currentParsingFile = resolve(filePath, parseFilePath); if (!ATTR_PROCESSING_ROLE_VALUE_RESOURCE_ONLY.equals(processRoleValue)) { currentParsingFileTopicIDChangeTable = new HashMap<String, String>(); // TODO recursive point reader.parse(currentParsingFile.toURI().toString()); if (currentParsingFileTopicIDChangeTable.size() > 0) { final URI href = toURI(topicref.getAttribute(ATTRIBUTE_NAME_HREF)); final String pathtoElem = href.getFragment() != null ? href.getFragment() : ""; final String old_elementid = pathtoElem.contains(SLASH) ? pathtoElem.substring(0, pathtoElem.indexOf(SLASH)) : pathtoElem; if (!old_elementid.isEmpty()) { final String new_elementid = currentParsingFileTopicIDChangeTable.get(old_elementid); if (new_elementid != null && !new_elementid.isEmpty()) { topicref.setAttribute( ATTRIBUTE_NAME_HREF, setFragment(href, new_elementid).toString()); } } } currentParsingFileTopicIDChangeTable = null; } // restore the currentParsingFile currentParsingFile = tempPath; } if (topicref.hasChildNodes()) { // if current element has child nodes and chunk results for // this element has value // which means current element makes sense for chunk action. final StringWriter tempOutput = (StringWriter) output; output = new StringWriter(); final NodeList children = topicref.getChildNodes(); for (int i = 0; i < children.getLength(); i++) { final Node current = children.item(i); if (MAP_TOPICREF.matches(current)) { processChunk((Element) current, outputFileName); } } // merge results final StringBuffer parentResult = tempOutput.getBuffer(); final CharSequence tmpContent = ((StringWriter) output).getBuffer(); // Skip empty parents and @processing-role='resource-only' entries. // append into root topic if (parentResult.length() > 0 && parseFilePath != null && !ATTR_PROCESSING_ROLE_VALUE_RESOURCE_ONLY.equals(processRoleValue)) { insertAfter(hrefValue, parentResult, tmpContent); // replace contents } else { parentResult.append(tmpContent); } // restore back to parent's output this is a different temp output = tempOutput; } if (chunkValue.contains(CHUNK_TO_CONTENT)) { final String tmpContent = ((StringWriter) output).toString(); writeToContentChunk(tmpContent, outputFileName, needWriteDitaTag); // restore back original output output = tempWriter; topicID = tempTopicID; } } catch (final RuntimeException e) { throw e; } catch (final Exception e) { logger.error(e.getMessage(), e); } }