1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    * The contents of this file are subject to the terms of the Liferay Enterprise
5    * Subscription License ("License"). You may not use this file except in
6    * compliance with the License. You can obtain a copy of the License by
7    * contacting Liferay, Inc. See the License for the specific language governing
8    * permissions and limitations under the License, including but not limited to
9    * distribution rights of the Software.
10   *
11   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.util.xml;
21  
22  import com.liferay.portal.kernel.util.ByteArrayMaker;
23  import com.liferay.portal.kernel.util.FileUtil;
24  import com.liferay.portal.kernel.util.StringUtil;
25  import com.liferay.portal.kernel.util.Validator;
26  import com.liferay.util.xml.descriptor.XMLDescriptor;
27  
28  import java.io.File;
29  import java.io.IOException;
30  import java.io.StringReader;
31  
32  import org.dom4j.Document;
33  import org.dom4j.DocumentException;
34  import org.dom4j.io.OutputFormat;
35  import org.dom4j.io.SAXReader;
36  import org.dom4j.io.XMLWriter;
37  
38  /**
39   * <a href="XMLMergerRunner.java.html"><b><i>View Source</i></b></a>
40   *
41   * @author Jorge Ferrer
42   *
43   */
44  public class XMLMergerRunner {
45  
46      public static void main(String[] args)
47          throws ClassNotFoundException, DocumentException,
48                 IllegalAccessException, InstantiationException, IOException {
49  
50          if ((args != null) && (args.length == 4)) {
51              XMLMergerRunner runner = new XMLMergerRunner(args[3]);
52  
53              runner.mergeAndSave(args[0], args[1], args[2]);
54          }
55          else {
56              throw new IllegalArgumentException();
57          }
58      }
59  
60      public XMLMergerRunner(String descriptorClassName) {
61          if (Validator.isNotNull(descriptorClassName)) {
62              _descriptorClassName = descriptorClassName;
63          }
64      }
65  
66      public void mergeAndSave(
67              String masterFile, String slaveFile, String mergedFile)
68          throws ClassNotFoundException, DocumentException,
69                 IllegalAccessException, InstantiationException, IOException {
70  
71          mergeAndSave(
72              new File(masterFile), new File(slaveFile), new File(mergedFile));
73      }
74  
75      public void mergeAndSave(File masterFile, File slaveFile, File mergedFile)
76          throws ClassNotFoundException, DocumentException,
77                 IllegalAccessException, InstantiationException, IOException {
78  
79          String xml1 = FileUtil.read(masterFile);
80          String xml2 = FileUtil.read(slaveFile);
81  
82          String mergedXml = _merge(xml1, xml2);
83  
84          FileUtil.write(mergedFile, mergedXml);
85      }
86  
87      private String _documentToString(Document doc, String docType)
88          throws IOException {
89  
90          ByteArrayMaker bam = new ByteArrayMaker();
91  
92          OutputFormat format = OutputFormat.createPrettyPrint();
93  
94          format.setIndent("\t");
95          format.setLineSeparator("\n");
96  
97          XMLWriter writer = new XMLWriter(bam, format);
98  
99          writer.write(doc);
100 
101         String xml = bam.toString();
102 
103         int pos = xml.indexOf("<?");
104 
105         String header = xml.substring(pos, xml.indexOf("?>", pos) + 2);
106 
107         xml = StringUtil.replace(xml, header, "");
108         xml = header + "\n" + docType + "\n" + xml;
109 
110         return xml;
111     }
112 
113     private String _merge(String masterXml, String slaveXml)
114         throws ClassNotFoundException, DocumentException,
115                IllegalAccessException, InstantiationException, IOException {
116 
117         int pos = masterXml.indexOf("<!DOCTYPE");
118 
119         String masterDoctype = "";
120 
121         if (pos >= 0) {
122             masterDoctype = masterXml.substring(
123                 pos, masterXml.indexOf(">", pos) + 1);
124             masterXml = StringUtil.replace(masterXml, masterDoctype, "");
125         }
126 
127         pos = slaveXml.indexOf("<!DOCTYPE");
128 
129         String slaveDoctype = "";
130 
131         if (pos >= 0) {
132             slaveDoctype = slaveXml.substring(
133                 pos, slaveXml.indexOf(">", pos) + 1);
134             slaveXml = StringUtil.replace(slaveXml, slaveDoctype, "");
135         }
136 
137         String doctype = null;
138 
139         if (Validator.isNotNull(masterDoctype)) {
140             doctype = masterDoctype;
141         }
142         else {
143             doctype = slaveDoctype;
144         }
145 
146         SAXReader reader = new SAXReader();
147 
148         Document masterDoc = reader.read(new StringReader(masterXml));
149         Document slaveDoc = reader.read(new StringReader(slaveXml));
150 
151         XMLDescriptor descriptor = null;
152 
153         if (_descriptorClassName.equals(_AUTO_DESCRIPTOR)) {
154             descriptor = XMLTypeDetector.determineType(doctype, masterDoc);
155         }
156         else {
157             descriptor = (XMLDescriptor)Class.forName(
158                 _descriptorClassName).newInstance();
159         }
160 
161         XMLMerger merger = new XMLMerger(descriptor);
162 
163         Document mergedDoc = merger.merge(masterDoc, slaveDoc);
164 
165         return _documentToString(mergedDoc, doctype);
166     }
167 
168     private static final String _AUTO_DESCRIPTOR = "auto";
169 
170     private String _descriptorClassName = _AUTO_DESCRIPTOR;
171 
172 }