View Javadoc

1   /*
2    * EL4J, the Extension Library for the J2EE, adds incremental enhancements to
3    * the spring framework, http://el4j.sf.net
4    * Copyright (C) 2006 by ELCA Informatique SA, Av. de la Harpe 22-24,
5    * 1000 Lausanne, Switzerland, http://www.elca.ch
6    *
7    * EL4J is published under the GNU Lesser General Public License (LGPL)
8    * Version 2.1. See http://www.gnu.org/licenses/
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13   * GNU Lesser General Public License for more details.
14   *
15   * For alternative licensing, please contact info@elca.ch
16   */
17  
18  // Checkstyle: MagicNumber off
19  
20  package ch.elca.el4j.services.xmlmerge.anttask;
21  
22  import java.io.File;
23  import java.io.FileInputStream;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.OutputStream;
28  import java.util.ArrayList;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.Properties;
32  
33  import org.apache.tools.ant.BuildException;
34  import org.apache.tools.ant.DirectoryScanner;
35  import org.apache.tools.ant.Task;
36  import org.apache.tools.ant.types.FileSet;
37  
38  import ch.elca.el4j.services.monitoring.notification.CoreNotificationHelper;
39  import ch.elca.el4j.services.xmlmerge.AbstractXmlMergeException;
40  import ch.elca.el4j.services.xmlmerge.ConfigurationException;
41  import ch.elca.el4j.services.xmlmerge.XmlMerge;
42  import ch.elca.el4j.services.xmlmerge.config.ConfigurableXmlMerge;
43  import ch.elca.el4j.services.xmlmerge.config.PropertyXPathConfigurer;
44  
45  /**
46   * Task for merging XML files in Ant.
47   *
48   * <p>Attributes:
49   * <ul>
50   * <li><b>dest</b> Output merged file. <i>Required</i>
51   * <li><b>conf</b> Configuration file. <i>Required</i>
52   * </ul>
53   *
54   * <p>Content:
55   * <ul><li><b>FileSet</b> Selects the files to merge.</li></ul>
56   *
57   * Usage example:
58   *
59   * <pre>
60   *   &lt;target name="test-task">
61   *       &lt;taskdef name="xmlmerge" classname="ch.elca.el4j.xmlmerge.anttask.XmlMergeTask"
62   *           classpath="module-xml_merge.jar;jdom.jar;jaxen.jar;saxpath.jar "/>
63   *
64   *       &lt;xmlmerge dest="out.xml" conf="test.properties">
65   *           &lt;fileset dir="test">
66   *             &lt;include name="source*.xml"/>
67   *          &lt;/fileset>
68   *       &lt;/xmlmerge>
69   *   &lt;/target>
70   * </pre>
71   *
72   * @svnLink $Revision: 3884 $;$Date: 2009-08-04 15:48:31 +0200 (Di, 04. Aug 2009) $;$Author: swismer $;$URL: https://el4j.svn.sourceforge.net/svnroot/el4j/branches/el4j_3_1/el4j/framework/modules/xml_merge/common/src/main/java/ch/elca/el4j/services/xmlmerge/anttask/XmlMergeTask.java $
73   *
74   * @author Laurent Bovet (LBO)
75   * @author Alex Mathey (AMA)
76   */
77  public class XmlMergeTask extends Task {
78  
79  	/**
80  	 * Configuration file name.
81  	 */
82  	String m_confFilename = null;
83  
84  	/**
85  	 * Output merged file name.
86  	 */
87  	String m_destFilename = null;
88  
89  	/**
90  	 * List of file sets.
91  	 */
92  	List m_filesets = new ArrayList();
93  
94  	/**
95  	 * Sets the configuration file name.
96  	 * @param confFilename The configuration file name to set.
97  	 */
98  	public void setConf(String confFilename) {
99  		m_confFilename = confFilename;
100 	}
101 
102 	/**
103 	 * Sets the destination file name.
104 	 * @param destFilename The destination file name to set.
105 	 */
106 	public void setDest(String destFilename) {
107 		m_destFilename = destFilename;
108 	}
109 
110 	/**
111 	 * Adds a file set.
112 	 * @param fileset The file set to add
113 	 */
114 	public void addFileSet(FileSet fileset) {
115 		m_filesets.add(fileset);
116 	}
117 
118 	/**
119 	 * Validates the configuration and destination files and the file sets.
120 	 */
121 	public void validate() {
122 		if (m_confFilename == null) {
123 			throw new BuildException("conf file not set");
124 		}
125 		if (m_destFilename == null) {
126 			throw new BuildException("dest file not set");
127 		}
128 		if (m_filesets.isEmpty()) {
129 			throw new BuildException("no source fileset specified");
130 		}
131 	}
132 
133 	/**
134 	 * {@inheritDoc}
135 	 */
136 	@Override
137 	public void execute() {
138 		validate();
139 
140 		// Get the files to merge
141 		List streamsToMerge = new ArrayList();
142 
143 		for (Iterator it = m_filesets.iterator(); it.hasNext();) {
144 			FileSet fs = (FileSet) it.next();
145 			DirectoryScanner ds = fs.getDirectoryScanner(getProject());
146 			String[] includedFiles = ds.getIncludedFiles();
147 			for (int i = 0; i < includedFiles.length; i++) {
148 				try {
149 					streamsToMerge.add(new FileInputStream(new File(ds
150 						.getBasedir(), includedFiles[i])));
151 				} catch (IOException e) {
152 					throw new BuildException(e);
153 				}
154 			}
155 		}
156 
157 		// Create the stream to write
158 		OutputStream out;
159 		File destFile = new File(m_destFilename);
160 
161 		if (!destFile.isAbsolute()) {
162 			destFile = new File(getProject().getBaseDir(), m_destFilename);
163 		}
164 
165 		try {
166 			out = new FileOutputStream(destFile);
167 		} catch (IOException e) {
168 			throw new BuildException(e);
169 		}
170 
171 		// Create conf properties
172 		Properties confProps = new Properties();
173 		File confFile = new File(m_confFilename);
174 
175 		if (!confFile.isAbsolute()) {
176 			confFile = new File(getProject().getBaseDir(), m_confFilename);
177 		}
178 
179 		InputStream configIn = null;
180 		try {
181 			configIn = new FileInputStream(confFile);
182 			confProps.load(configIn);
183 		} catch (IOException e) {
184 			throw new BuildException(e);
185 		} finally {
186 			if (configIn != null) {
187 				try {
188 					configIn.close();
189 				} catch (IOException e) {
190 					CoreNotificationHelper.notifyMisconfiguration(
191 						"The file '" + confFile
192 						+ "' could not be close.", e);
193 				}
194 			}
195 		}
196 
197 		// Create the XmlMerge instance and execute the merge
198 
199 		XmlMerge xmlMerge;
200 		try {
201 			xmlMerge = new ConfigurableXmlMerge(new PropertyXPathConfigurer(
202 				confProps));
203 		} catch (ConfigurationException e) {
204 			throw new BuildException(e);
205 		}
206 
207 		InputStream in;
208 
209 		try {
210 			in = xmlMerge.merge((InputStream[]) streamsToMerge
211 				.toArray(new InputStream[streamsToMerge.size()]));
212 		} catch (AbstractXmlMergeException e) {
213 			throw new BuildException(e);
214 		}
215 
216 		writeFromTo(in, out);
217 
218 		try {
219 			in.close();
220 		} catch (IOException e) {
221 			throw new BuildException(e);
222 		}
223 
224 		try {
225 			out.close();
226 		} catch (IOException e) {
227 			throw new BuildException(e);
228 		}
229 	}
230 
231 	/**
232 	 * Writes from an InputStream to an OutputStream.
233 	 * @param in The stream to read from
234 	 * @param out The stream to write to
235 	 * @throws BuildException If an error occurred during the write process
236 	 */
237 	private void writeFromTo(InputStream in, OutputStream out)
238 		throws BuildException {
239 		int len = 0;
240 		byte[] buffer = new byte[1024];
241 
242 		try {
243 			while ((len = in.read(buffer)) != -1) {
244 				out.write(buffer, 0, len);
245 			}
246 		} catch (IOException ioe) {
247 			throw new BuildException(ioe);
248 		}
249 	}
250 }
251 
252 //Checkstyle: MagicNumber on