/* * � Copyright IBM Corp. 2011, 2014 * * Licensed 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. */ /* * Author: Maire Kehoe (mkehoe@ie.ibm.com) * Date: 2 Jan 2007 * ToolsUtil.java */ package com.ibm.xsp.tools; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.StringWriter; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.w3c.dom.Text; import org.xml.sax.ErrorHandler; import org.xml.sax.SAXException; import org.xml.sax.SAXParseException; import com.ibm.commons.xml.XMLException; /** * @author Maire Kehoe (mkehoe@ie.ibm.com) * 2 Jan 2007 * * Project: IBM Lotus Component Designer. * Unit: ToolsUtil.java */ public class ToolsUtil { private static String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$ public static void writeOut(File file, String str) { try { file.getParentFile().mkdirs(); file.createNewFile(); if( ! file.canWrite() ){ throw new RuntimeException("The file is not writable: "+file.getAbsolutePath()); } FileWriter out = new FileWriter(file); out.write(str); out.close(); } catch (IOException e) { e.printStackTrace(); throw new RuntimeException(e); } } public static String convertToString(Document document) throws XMLException { Node node = document.getDocumentElement(); return nodeToString(node) ; } private static String nodeToString(Node node) { StringWriter sw = new StringWriter(); try { Transformer t = TransformerFactory.newInstance().newTransformer(); t.setOutputProperty(OutputKeys.INDENT, "yes"); t.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "2"); t.transform(new DOMSource(node), new StreamResult(sw)); } catch (TransformerException te) { throw new RuntimeException(te); } String asStr = sw.toString(); String xmlDecl = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; String badStart = xmlDecl+"<"; if( asStr.startsWith(badStart) ){ // missing newline after xmlDecl asStr = xmlDecl+NEWLINE+asStr.substring(xmlDecl.length()); } // convert the newline character in render-markup elements from // to (hex encoding of same character), to be consistent // with the previous XML serializer. asStr = asStr.replace(" ", " "); return asStr+NEWLINE; } @SuppressWarnings("deprecation") public static Document readInFile(File file) throws Exception { String inUrl = file.toURL().toString(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(false); factory.setExpandEntityReferences(true); factory.setValidating(false); // Note the DomUtil parser doesn't expand entities correctly. // DocumentBuilder parser = DomUtil.getParser(); // TODO (mkehoe) this is expanding " in the description - it should // leave that the same DocumentBuilder parser = factory.newDocumentBuilder(); final List<String> errors = new ArrayList<String>(); parser.setErrorHandler(new ErrorHandler(){ public void fatalError(SAXParseException ex) throws SAXException { throw ex; } public void error(SAXParseException ex) throws SAXException { String msg = "Error: Line="+ex.getLineNumber()+": "+ex.getMessage(); System.err.println(msg); errors.add(msg); // throw ex; } public void warning(SAXParseException ex) throws SAXException { System.err.println("Warning: Line="+ex.getLineNumber()+": "+ex.getMessage()); // throw ex; } }); Document document = parser.parse(inUrl); if( !errors.isEmpty() ){ String allMsgs = ""; for (String msg : errors) { allMsgs += msg+", "; } allMsgs = allMsgs.substring(0, allMsgs.length()-2); throw new RuntimeException("Problem(s) parsing XML: "+allMsgs); } removeWhitespaceNodes(document.getDocumentElement()); return document; } private static void removeWhitespaceNodes(Node e) { // called after have read-in the nodes. // Later the nodeToString method will be used to // convert the node to string, while attempting to format with 2-space indent. // But if the tree already contains whitespace characters then it won't do the indent formatting, // and you end up with a mix of tabs, 2-space and 4-space indenting. // So removing the source-file indentation whitespace here, so can do consistent 2-space indent. NodeList kids = e.getChildNodes(); int i = 0; while( i < kids.getLength() ){ Node kid = kids.item(i); if( kid.getNodeType() == Node.TEXT_NODE && ((Text) kid).getTextContent().trim().isEmpty() ){ e.removeChild(kid); }else{ if( kid.getNodeType() == Node.ELEMENT_NODE ){ removeWhitespaceNodes(kid); } i++; } } } public static Map<String, String> processArgs(String[] args){ Map<String, String> argsMap = new HashMap<String, String>(args.length / 2); for(int i = 0; i < args.length; i += 2){ if(args[i].startsWith("--") && i + 1 <= args.length) argsMap.put(args[i], args[i + 1]); } // debug to check what args were taken in // for (Iterator iter = _argsMap.keySet().iterator(); iter.hasNext();) { // String key = (String) iter.next(); // System.out.println("key: " + key + ", value: " + _argsMap.get(key)); // } return argsMap; } }