| 1 16 package org.outerj.daisy.install; 17 18 import java.io.BufferedReader ; 19 import java.io.ByteArrayInputStream ; 20 import java.io.File ; 21 import java.io.FileReader ; 22 import java.io.IOException ; 23 import java.io.InputStream ; 24 import java.io.InputStreamReader ; 25 import java.util.ArrayList ; 26 import java.util.Iterator ; 27 import java.util.List ; 28 import java.util.regex.Matcher ; 29 import java.util.regex.Pattern ; 30 31 import javax.xml.parsers.DocumentBuilder ; 32 import javax.xml.parsers.DocumentBuilderFactory ; 33 34 import org.apache.commons.cli.CommandLine; 35 import org.apache.commons.cli.CommandLineParser; 36 import org.apache.commons.cli.HelpFormatter; 37 import org.apache.commons.cli.Option; 38 import org.apache.commons.cli.Options; 39 import org.apache.commons.cli.ParseException; 40 import org.apache.commons.cli.PosixParser; 41 import org.jaxen.JaxenException; 42 import org.jaxen.dom.DOMXPath; 43 import org.w3c.dom.Document ; 44 import org.w3c.dom.Element ; 45 import org.w3c.dom.NamedNodeMap ; 46 import org.w3c.dom.Node ; 47 48 52 public class XmlConfUpdater { 53 private File sourceFile; 54 55 private File targetFile; 56 57 private Document sourceDoc; 58 59 private Document targetDoc; 60 61 private List xPaths; 62 63 private String LINE_FORMAT = "^((\\[(.*?):(.*?)\\])\\s)?(.*?)(\\s(<<[>!=]{2})\\s?(.*))?$"; 64 65 private boolean showDebug; 66 67 72 public static void main(String [] args) { 73 Options options = new Options(); 74 Option sourceFileOption = new Option("s", "source", true, "The source file that needs to be updated"); 75 Option targetFileOption = new Option("t", "target", true, "The target file that will serve as target"); 76 Option xPaths = new Option("x", "xpaths", true, "XPaths specifying which paths must be transfered from source to target"); 77 78 sourceFileOption.setRequired(true); 79 sourceFileOption.setArgName("source-file"); 80 targetFileOption.setRequired(true); 81 targetFileOption.setArgName("target-file"); 82 xPaths.setRequired(true); 83 xPaths.setArgName("xpaths-file"); 84 85 options.addOption(sourceFileOption); 86 options.addOption(targetFileOption); 87 options.addOption(xPaths); 88 options.addOption("d", "debug", false, "Print debugging messages"); 89 options.addOption("h", "help", false, "Show this message"); 90 91 CommandLineParser parser = new PosixParser(); 92 93 try { 94 CommandLine cmd = parser.parse(options, args); 95 try { 96 XmlConfUpdater updater = new XmlConfUpdater(cmd.getOptionValue("s"), cmd.getOptionValue("t"), cmd.getOptionValue("x"), cmd.hasOption("d")); 97 updater.update(); 98 System.out.println("Updated " + cmd.getOptionValue("t")); 99 } catch (Exception e) { 100 System.out.println("Could not update file " + cmd.getOptionValue("t")); 101 e.printStackTrace(); 102 System.exit(1); 103 } 104 } catch (ParseException e) { 105 HelpFormatter help = new HelpFormatter(); 106 help.printHelp("XConfUpdater", options, true); 107 } 108 } 109 110 123 public XmlConfUpdater(String sourceFileName, String targetFileName, String xpathFile, boolean showDebug) throws Exception { 124 this.showDebug = showDebug; 125 sourceFile = new File (sourceFileName); 126 targetFile = new File (targetFileName); 127 sourceDoc = InstallHelper.parseFile(sourceFile); 128 targetDoc = InstallHelper.parseFile(targetFile); 129 xPaths = getXPaths(xpathFile); 130 131 } 132 133 140 public void update() throws Exception { 141 Iterator actionIterator = xPaths.iterator(); 142 while (actionIterator.hasNext()) { 143 UpdateAction action = (UpdateAction) actionIterator.next(); 144 try { 145 int status = action.execute(); 146 if (showDebug) { 147 if ( status == UpdateAction.ACTION_SUCCEEDED) { 148 System.out.println("Xpath OK : " + action.getXPath().getRootExpr().getText()); 149 } else { 150 System.out.println("skipping xpath " + action.getXPath().getRootExpr().getText()); 151 } 152 } 153 } catch (Exception e) { 154 e.printStackTrace(); 155 System.err.println("Failed xpath" + action.getXPath().getRootExpr().getText()); 156 } 157 } 158 InstallHelper.saveDocument(targetFile, targetDoc); 159 } 160 161 private List getXPaths(String fileName) throws Exception { 162 List pathsInserts = new ArrayList (); 163 BufferedReader br; 164 if (fileName.equals("-")) 165 br = new BufferedReader (new InputStreamReader (System.in)); 166 else 167 br = new BufferedReader (new FileReader (fileName)); 168 169 try { 170 String line = null; 171 Pattern linePattern = Pattern.compile(LINE_FORMAT); 172 while ((line = br.readLine()) != null) { 173 Matcher lineMatcher = linePattern.matcher(line); 174 lineMatcher.find(); 175 String nsPrefix = lineMatcher.group(3); 176 String ns = lineMatcher.group(4); 177 DOMXPath xpath = new DOMXPath(lineMatcher.group(5)); 178 String commandString = lineMatcher.group(7); 179 String tag = lineMatcher.group(8); 180 181 if (ns != null && nsPrefix != null) 182 xpath.addNamespace(nsPrefix, ns); 183 184 UpdateAction xPathAction = UpdateAction.createAction(sourceDoc, targetDoc, xpath, tag, commandString); 185 186 pathsInserts.add(xPathAction); 187 } 188 189 } finally { 190 br.close(); 191 } 192 return pathsInserts; 193 } 194 195 private static abstract class UpdateAction { 196 197 private static final String INSERT_SEPARATOR = "<<=="; 198 199 private static final String REPLACE_SEPARATOR = "<<>>"; 200 201 private static final String REMOVE_SEPARATOR = "<<!!"; 202 203 private static final String XPATH_REFERENCE_REGEX = "(?<!\\$)\\{.*?\\}"; 204 205 public static final int ACTION_SUCCEEDED = 0; 206 207 public static final int ACTION_FAILED = 1; 208 209 protected Document tagDoc; 210 211 protected Document targetDoc; 212 213 protected Document sourceDoc; 214 215 protected DOMXPath xPath; 216 217 private boolean showDebug = false; 218 219 private UpdateAction(Document sourceDoc, Document targetDoc, DOMXPath xPath, String tag) throws Exception { 220 this.sourceDoc = sourceDoc; 221 this.targetDoc = targetDoc; 222 this.xPath = xPath; 223 if (tag != null) { 225 DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder(); 226 InputStream is = new ByteArrayInputStream (tag.getBytes()); 227 tagDoc = documentBuilder.parse(is); 228 translateXpathReferences(tagDoc.getDocumentElement(), targetDoc.getDocumentElement()); 230 } 231 } 232 233 public static UpdateAction createAction(Document sourceDoc, Document targetDoc, DOMXPath xpath, String tag, String command) throws Exception { 234 UpdateAction action = null; 235 if (command == null) 236 action = new CopyAction(sourceDoc, targetDoc, xpath); 237 else if (command.equals(INSERT_SEPARATOR)) 238 action = new InsertAction(sourceDoc, targetDoc, xpath, tag); 239 else if (command.equals(REPLACE_SEPARATOR)) 240 action = new ReplaceAction(sourceDoc, targetDoc, xpath, tag); 241 else if (command.equals(REMOVE_SEPARATOR)) 242 action = new RemoveAction(sourceDoc, targetDoc, xpath); 243 244 return action; 245 } 246 247 public abstract int execute() throws Exception ; 248 249 private void translateXpathReferences(Node newNode, Node rootNode) throws Exception { 250 if (newNode.getChildNodes().getLength() > 0) { 251 for (int i = 0; i < newNode.getChildNodes().getLength(); i++) 252 translateXpathReferences(newNode.getChildNodes().item(i), rootNode); 253 } 254 Pattern pattern = Pattern.compile(XPATH_REFERENCE_REGEX); 255 if ((newNode.getNodeType() == Node.TEXT_NODE || newNode.getNodeType() == Node.ATTRIBUTE_NODE) && newNode.getNodeValue() != null) { 256 257 String nodeValue = newNode.getNodeValue(); 258 Matcher matcher = pattern.matcher(nodeValue); 259 while (matcher.find()) { 260 String xpath = matcher.group(); 261 xpath = xpath.substring(1, xpath.length() - 1); 262 Node matchedNode = (Node ) new DOMXPath(xpath).selectSingleNode(rootNode); 263 if (matchedNode != null) { 264 if ( showDebug) 265 System.out.println("Found node to be replaced at : " + xpath + " value : " + matchedNode.getNodeValue()); 266 if (matchedNode.getNodeType() == Node.TEXT_NODE || matchedNode.getNodeType() == Node.ATTRIBUTE_NODE) { 268 nodeValue = matcher.replaceFirst(matchedNode.getNodeValue()); 269 } else if (matchedNode.getNodeType() == Node.ELEMENT_NODE) { 271 newNode.getParentNode().appendChild(newNode.getOwnerDocument().importNode(matchedNode, true)); 272 nodeValue = matcher.replaceFirst(""); 273 274 } else { 275 System.out.println("I don't know what to do with that type of node :" + matchedNode.getNodeType()); 276 nodeValue = matcher.replaceFirst(""); 277 } 278 279 } else { 280 throw new IOException ("This XPath could not be found " + xpath); 281 } 282 matcher = pattern.matcher(nodeValue); 283 } 284 newNode.setNodeValue(nodeValue); 285 286 } else if (newNode.getNodeType() == Node.ELEMENT_NODE) { 287 NamedNodeMap atts = newNode.getAttributes(); 288 for (int i = 0; i < atts.getLength(); i++) 289 translateXpathReferences(atts.item(i), rootNode); 290 } 291 } 292 293 public DOMXPath getXPath() { 294 return xPath; 295 } 296 297 public void setXPath(DOMXPath path) { 298 xPath = path; 299 } 300 301 public boolean isShowDebug() { 302 return showDebug; 303 } 304 305 public void setShowDebug(boolean showDebug) { 306 this.showDebug = showDebug; 307 } 308 } 309 310 private static class InsertAction extends UpdateAction { 311 public InsertAction(Document sourceDoc, Document targetDoc, DOMXPath xPath, String tag) throws Exception { 312 super(sourceDoc, targetDoc, xPath, tag); 313 } 314 315 public int execute() throws Exception { 316 int status = ACTION_SUCCEEDED; 317 318 Node targetNode = (Node ) xPath.selectSingleNode(targetDoc); 319 if (targetNode != null) 320 targetNode.appendChild(targetDoc.importNode(tagDoc.getDocumentElement(), true)); 321 else 322 status = ACTION_FAILED; 323 324 return status; 325 } 326 } 327 328 private static class ReplaceAction extends UpdateAction { 329 public ReplaceAction(Document sourceDoc, Document targetDoc, DOMXPath xPath, String tag) throws Exception { 330 super(sourceDoc, targetDoc, xPath, tag); 331 } 332 333 public int execute() throws Exception { 334 int status = ACTION_SUCCEEDED; 335 336 Node targetNode = (Node ) xPath.selectSingleNode(targetDoc); 337 Node newNode = targetDoc.importNode(tagDoc.getDocumentElement(), true); 338 if (targetNode != null) 339 targetNode.getParentNode().replaceChild(newNode, targetNode); 340 else 341 status = ACTION_FAILED; 342 343 return status; 344 } 345 } 346 347 private static class RemoveAction extends UpdateAction { 348 public RemoveAction(Document sourceDoc, Document targetDoc, DOMXPath xPath) throws Exception { 349 super(sourceDoc, targetDoc, xPath, null); 350 } 351 352 public int execute() throws Exception { 353 int status = ACTION_SUCCEEDED; 354 Node targetNode = (Node ) xPath.selectSingleNode(targetDoc); 355 if (targetNode != null) 356 targetNode.getParentNode().removeChild(targetNode); 357 else 358 status = ACTION_FAILED; 359 360 return status; 361 } 362 } 363 364 private static class CopyAction extends UpdateAction { 365 public CopyAction(Document sourceDoc, Document targetDoc, DOMXPath xPath) throws Exception { 366 super(sourceDoc, targetDoc, xPath, null); 367 } 368 369 public int execute() throws Exception { 370 int status = ACTION_SUCCEEDED; 371 Element sourceElement = (Element ) xPath.selectSingleNode(sourceDoc); 372 Element targetElement = (Element ) xPath.selectSingleNode(targetDoc); 373 if (sourceElement != null) { 374 if (targetElement != null) { 375 targetElement.getParentNode().replaceChild(targetDoc.importNode(sourceElement, true), targetElement); 377 } else { 378 do { 381 sourceElement = (Element ) xPath.selectSingleNode(sourceDoc); 382 xPath = getParentXpath(xPath); 383 targetElement = (Element ) xPath.selectSingleNode(targetDoc); 384 } while (targetElement == null); 385 386 targetElement.appendChild(targetDoc.importNode(sourceElement, true)); 387 } 388 } 389 return status; 390 } 391 392 private DOMXPath getParentXpath(DOMXPath path) throws JaxenException { 393 String rootText = path.getRootExpr().getText(); 394 return new DOMXPath(rootText.substring(0, rootText.lastIndexOf("/"))); 395 } 396 } 397 } 398 | Popular Tags |