KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > outerj > daisy > install > XmlConfUpdater


1 /*
2  * Copyright 2004 Outerthought bvba and Schaubroeck nv
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */

16 package org.outerj.daisy.install;
17
18 import java.io.BufferedReader JavaDoc;
19 import java.io.ByteArrayInputStream JavaDoc;
20 import java.io.File JavaDoc;
21 import java.io.FileReader JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24 import java.io.InputStreamReader JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.regex.Matcher JavaDoc;
29 import java.util.regex.Pattern JavaDoc;
30
31 import javax.xml.parsers.DocumentBuilder JavaDoc;
32 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
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 JavaDoc;
44 import org.w3c.dom.Element JavaDoc;
45 import org.w3c.dom.NamedNodeMap JavaDoc;
46 import org.w3c.dom.Node JavaDoc;
47
48 /**
49  * @author paul
50  *
51  */

52 public class XmlConfUpdater {
53     private File JavaDoc sourceFile;
54
55     private File JavaDoc targetFile;
56
57     private Document JavaDoc sourceDoc;
58
59     private Document JavaDoc targetDoc;
60
61     private List JavaDoc xPaths;
62
63     private String JavaDoc LINE_FORMAT = "^((\\[(.*?):(.*?)\\])\\s)?(.*?)(\\s(<<[>!=]{2})\\s?(.*))?$";
64
65     private boolean showDebug;
66
67     /**
68      * @param args
69      * Accepted command line arguments '-t' '--target' '-s'
70      * '--source' '-x' '--xpaths' -h' '--help'
71      */

72     public static void main(String JavaDoc[] 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 JavaDoc 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     /**
111      * Constucts an Updater object
112      *
113      * @param sourceFileName
114      * Source xml file from which items will be copied to the target
115      * xml file
116      * @param targetFileName
117      * Target xml file receiving items from the source file
118      * @param xpathFile
119      * File specifying XPaths that will be copied from source to
120      * target. Each entry is newline delimited.
121      * @throws Exception
122      */

123     public XmlConfUpdater(String JavaDoc sourceFileName, String JavaDoc targetFileName, String JavaDoc xpathFile, boolean showDebug) throws Exception JavaDoc {
124         this.showDebug = showDebug;
125         sourceFile = new File JavaDoc(sourceFileName);
126         targetFile = new File JavaDoc(targetFileName);
127         sourceDoc = InstallHelper.parseFile(sourceFile);
128         targetDoc = InstallHelper.parseFile(targetFile);
129         xPaths = getXPaths(xpathFile);
130
131     }
132
133     /**
134      * Updates the target xml file with the source xml file. The items specified
135      * in the xPathFile will be copied from source to target. Existing tags in
136      * the target xml file will be overwritten.
137      *
138      * @throws Exception
139      */

140     public void update() throws Exception JavaDoc {
141         Iterator JavaDoc 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 JavaDoc 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 JavaDoc getXPaths(String JavaDoc fileName) throws Exception JavaDoc {
162         List JavaDoc pathsInserts = new ArrayList JavaDoc();
163         BufferedReader JavaDoc br;
164         if (fileName.equals("-"))
165             br = new BufferedReader JavaDoc(new InputStreamReader JavaDoc(System.in));
166         else
167             br = new BufferedReader JavaDoc(new FileReader JavaDoc(fileName));
168
169         try {
170             String JavaDoc line = null;
171             Pattern JavaDoc linePattern = Pattern.compile(LINE_FORMAT);
172             while ((line = br.readLine()) != null) {
173                 Matcher JavaDoc lineMatcher = linePattern.matcher(line);
174                 lineMatcher.find();
175                 String JavaDoc nsPrefix = lineMatcher.group(3);
176                 String JavaDoc ns = lineMatcher.group(4);
177                 DOMXPath xpath = new DOMXPath(lineMatcher.group(5));
178                 String JavaDoc commandString = lineMatcher.group(7);
179                 String JavaDoc 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 JavaDoc INSERT_SEPARATOR = "<<==";
198
199         private static final String JavaDoc REPLACE_SEPARATOR = "<<>>";
200
201         private static final String JavaDoc REMOVE_SEPARATOR = "<<!!";
202
203         private static final String JavaDoc 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 JavaDoc tagDoc;
210
211         protected Document JavaDoc targetDoc;
212
213         protected Document JavaDoc sourceDoc;
214
215         protected DOMXPath xPath;
216         
217         private boolean showDebug = false;
218
219         private UpdateAction(Document JavaDoc sourceDoc, Document JavaDoc targetDoc, DOMXPath xPath, String JavaDoc tag) throws Exception JavaDoc {
220             this.sourceDoc = sourceDoc;
221             this.targetDoc = targetDoc;
222             this.xPath = xPath;
223             // Change the tag into a dom node
224
if (tag != null) {
225                 DocumentBuilder JavaDoc documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
226                 InputStream JavaDoc is = new ByteArrayInputStream JavaDoc(tag.getBytes());
227                 tagDoc = documentBuilder.parse(is);
228                 // replace { } thingies
229
translateXpathReferences(tagDoc.getDocumentElement(), targetDoc.getDocumentElement());
230             }
231         }
232
233         public static UpdateAction createAction(Document JavaDoc sourceDoc, Document JavaDoc targetDoc, DOMXPath xpath, String JavaDoc tag, String JavaDoc command) throws Exception JavaDoc {
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 JavaDoc;
248
249         private void translateXpathReferences(Node JavaDoc newNode, Node JavaDoc rootNode) throws Exception JavaDoc {
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 JavaDoc pattern = Pattern.compile(XPATH_REFERENCE_REGEX);
255             if ((newNode.getNodeType() == Node.TEXT_NODE || newNode.getNodeType() == Node.ATTRIBUTE_NODE) && newNode.getNodeValue() != null) {
256
257                 String JavaDoc nodeValue = newNode.getNodeValue();
258                 Matcher JavaDoc matcher = pattern.matcher(nodeValue);
259                 while (matcher.find()) {
260                     String JavaDoc xpath = matcher.group();
261                     xpath = xpath.substring(1, xpath.length() - 1);
262                     Node JavaDoc matchedNode = (Node JavaDoc) 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                         // substitute element or attribute text
267
if (matchedNode.getNodeType() == Node.TEXT_NODE || matchedNode.getNodeType() == Node.ATTRIBUTE_NODE) {
268                             nodeValue = matcher.replaceFirst(matchedNode.getNodeValue());
269                             // append element
270
} 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 JavaDoc("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 JavaDoc 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 JavaDoc sourceDoc, Document JavaDoc targetDoc, DOMXPath xPath, String JavaDoc tag) throws Exception JavaDoc {
312             super(sourceDoc, targetDoc, xPath, tag);
313         }
314
315         public int execute() throws Exception JavaDoc {
316             int status = ACTION_SUCCEEDED;
317
318             Node JavaDoc targetNode = (Node JavaDoc) 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 JavaDoc sourceDoc, Document JavaDoc targetDoc, DOMXPath xPath, String JavaDoc tag) throws Exception JavaDoc {
330             super(sourceDoc, targetDoc, xPath, tag);
331         }
332
333         public int execute() throws Exception JavaDoc {
334             int status = ACTION_SUCCEEDED;
335
336             Node JavaDoc targetNode = (Node JavaDoc) xPath.selectSingleNode(targetDoc);
337             Node JavaDoc 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 JavaDoc sourceDoc, Document JavaDoc targetDoc, DOMXPath xPath) throws Exception JavaDoc {
349             super(sourceDoc, targetDoc, xPath, null);
350         }
351
352         public int execute() throws Exception JavaDoc {
353             int status = ACTION_SUCCEEDED;
354             Node JavaDoc targetNode = (Node JavaDoc) 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 JavaDoc sourceDoc, Document JavaDoc targetDoc, DOMXPath xPath) throws Exception JavaDoc {
366             super(sourceDoc, targetDoc, xPath, null);
367         }
368
369         public int execute() throws Exception JavaDoc {
370             int status = ACTION_SUCCEEDED;
371             Element JavaDoc sourceElement = (Element JavaDoc) xPath.selectSingleNode(sourceDoc);
372             Element JavaDoc targetElement = (Element JavaDoc) xPath.selectSingleNode(targetDoc);
373             if (sourceElement != null) {
374                 if (targetElement != null) {
375                     // target element exists and will be replaced
376
targetElement.getParentNode().replaceChild(targetDoc.importNode(sourceElement, true), targetElement);
377                 } else {
378                     // target element does not exist so we'll climb the parental
379
// ladder to find the first existing item
380
do {
381                         sourceElement = (Element JavaDoc) xPath.selectSingleNode(sourceDoc);
382                         xPath = getParentXpath(xPath);
383                         targetElement = (Element JavaDoc) 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 JavaDoc rootText = path.getRootExpr().getText();
394             return new DOMXPath(rootText.substring(0, rootText.lastIndexOf("/")));
395         }
396     }
397 }
398
Popular Tags