KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > info > magnolia > cms > core > ie > DataTransporter


1 package info.magnolia.cms.core.ie;
2
3 import info.magnolia.cms.beans.runtime.Document;
4 import info.magnolia.cms.core.Content;
5 import info.magnolia.cms.core.HierarchyManager;
6 import info.magnolia.cms.core.ItemType;
7 import info.magnolia.cms.core.ie.filters.ImportXmlRootFilter;
8 import info.magnolia.cms.core.ie.filters.MagnoliaV2Filter;
9 import info.magnolia.cms.core.ie.filters.VersionFilter;
10 import info.magnolia.cms.util.ContentUtil;
11 import info.magnolia.cms.util.NodeDataUtil;
12 import info.magnolia.context.MgnlContext;
13
14 import java.io.File JavaDoc;
15 import java.io.FileInputStream JavaDoc;
16 import java.io.FileNotFoundException JavaDoc;
17 import java.io.FileOutputStream JavaDoc;
18 import java.io.IOException JavaDoc;
19 import java.io.InputStream JavaDoc;
20 import java.io.OutputStream JavaDoc;
21 import java.text.MessageFormat JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.Properties JavaDoc;
24 import java.util.zip.DeflaterOutputStream JavaDoc;
25 import java.util.zip.GZIPInputStream JavaDoc;
26 import java.util.zip.GZIPOutputStream JavaDoc;
27 import java.util.zip.ZipInputStream JavaDoc;
28 import java.util.zip.ZipOutputStream JavaDoc;
29
30 import javax.jcr.ImportUUIDBehavior;
31 import javax.jcr.Node;
32 import javax.jcr.PathNotFoundException;
33 import javax.jcr.RepositoryException;
34 import javax.jcr.Session;
35 import javax.jcr.Workspace;
36 import javax.xml.transform.Source JavaDoc;
37 import javax.xml.transform.sax.SAXTransformerFactory JavaDoc;
38 import javax.xml.transform.stream.StreamSource JavaDoc;
39
40 import org.apache.commons.io.IOUtils;
41 import org.apache.commons.lang.StringUtils;
42 import org.apache.commons.lang.exception.NestableRuntimeException;
43 import org.apache.xml.serialize.OutputFormat;
44 import org.apache.xml.serialize.XMLSerializer;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47 import org.xml.sax.ContentHandler JavaDoc;
48 import org.xml.sax.InputSource JavaDoc;
49 import org.xml.sax.SAXException JavaDoc;
50 import org.xml.sax.XMLReader JavaDoc;
51 import org.xml.sax.XMLFilter JavaDoc;
52 import org.xml.sax.helpers.XMLReaderFactory JavaDoc;
53
54
55 /**
56  * imports and exports XML data
57  * @author <a HREF="mailto:niko@macnica.com">Nicolas Modrzyk</a>
58  * @author Oliver Lietz
59  */

60 public class DataTransporter {
61
62     private static final int INDENT_VALUE = 2;
63
64     private static Logger log = LoggerFactory.getLogger(DataTransporter.class.getName());
65
66     final static int bootstrapImportMode = ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING;
67
68     public static final String JavaDoc ZIP = ".zip";
69
70     public static final String JavaDoc GZ = ".gz";
71
72     public static final String JavaDoc XML = ".xml";
73
74     public static final String JavaDoc PROPERTIES = ".properties";
75     
76     public static final String JavaDoc DOT = ".";
77
78     public static final String JavaDoc SLASH = "/";
79
80     public static final String JavaDoc JCR_ROOT = "jcr:root";
81
82     /**
83      * Document -> File
84      * @param xmlDocument uploaded file
85      * @param repositoryName selected repository
86      * @param basepath base path in repository
87      * @param keepVersionHistory if <code>false</code> version info will be stripped before importing the document
88      * @param importMode a valid value for ImportUUIDBehavior
89      * @param saveAfterImport
90      * @param createBasepathIfNotExist
91      * @throws IOException
92      * @see ImportUUIDBehavior
93      */

94     public static synchronized void importDocument(Document xmlDocument, String JavaDoc repositoryName, String JavaDoc basepath,
95                                                    boolean keepVersionHistory, int importMode, boolean saveAfterImport,
96                                                    boolean createBasepathIfNotExist)
97             throws IOException JavaDoc {
98         File JavaDoc xmlFile = xmlDocument.getFile();
99         importFile(xmlFile, repositoryName, basepath, keepVersionHistory, importMode, saveAfterImport,
100                 createBasepathIfNotExist);
101     }
102
103     /**
104      * File -> InputStream
105      * @param xmlFile (zipped/gzipped) XML file to import
106      * @param repositoryName selected repository
107      * @param basepath base path in repository
108      * @param keepVersionHistory if <code>false</code> version info will be stripped before importing the document
109      * @param importMode a valid value for ImportUUIDBehavior
110      * @param saveAfterImport
111      * @param createBasepathIfNotExist
112      * @throws IOException
113      * @see ImportUUIDBehavior
114      */

115     public static synchronized void importFile(File JavaDoc xmlFile, String JavaDoc repositoryName, String JavaDoc basepath,
116                                                boolean keepVersionHistory, int importMode, boolean saveAfterImport,
117                                                boolean createBasepathIfNotExist)
118             throws IOException JavaDoc {
119         String JavaDoc name = xmlFile.getAbsolutePath();
120
121         InputStream JavaDoc xmlStream = getInputStreamForFile(xmlFile);
122         importXmlStream(xmlStream, repositoryName, basepath, name, keepVersionHistory, importMode, saveAfterImport,
123                 createBasepathIfNotExist);
124     }
125
126     /**
127      * @param xmlFile
128      * @param repositoryName
129      * @throws IOException
130      */

131     public static void executeBootstrapImport(File JavaDoc xmlFile, String JavaDoc repositoryName) throws IOException JavaDoc {
132         String JavaDoc filenameWithoutExt = StringUtils.substringBeforeLast(xmlFile.getName(), DOT);
133         if (filenameWithoutExt.endsWith(XML)) {
134             // if file ends in .xml.gz or .xml.zip
135
// need to keep the .xml to be able to view it after decompression
136
filenameWithoutExt = StringUtils.substringBeforeLast(xmlFile.getName(), DOT);
137         }
138         String JavaDoc pathName = StringUtils.substringAfter(StringUtils.substringBeforeLast(filenameWithoutExt, DOT), DOT);
139         String JavaDoc basepath = SLASH + StringUtils.replace(pathName, DOT, SLASH);
140
141         if(xmlFile.getName().endsWith(PROPERTIES)){
142             Properties JavaDoc properties = new Properties JavaDoc();
143             properties.load(new FileInputStream JavaDoc(xmlFile));
144             importProperties(properties , repositoryName);
145         }
146         else{
147             DataTransporter.importFile(xmlFile, repositoryName, basepath, false, bootstrapImportMode, true, true);
148         }
149     }
150
151     /**
152      * Overwrite or set single values
153      * @param properties
154      * @param repositoryName
155      */

156     public static void importProperties(Properties JavaDoc properties, String JavaDoc repositoryName) {
157         for (Iterator JavaDoc iter = properties.keySet().iterator(); iter.hasNext();) {
158             String JavaDoc key = (String JavaDoc) iter.next();
159             String JavaDoc value = (String JavaDoc) properties.get(key);
160
161             String JavaDoc name = StringUtils.substringAfterLast(key, "."); //$NON-NLS-1$
162
String JavaDoc path = StringUtils.substringBeforeLast(key, ".").replace('.', '/'); //$NON-NLS-1$
163
Content node = ContentUtil.getContent(repositoryName, path);
164             if(node != null){
165                 try {
166                     NodeDataUtil.getOrCreate(node, name).setValue(value);
167                     node.save();
168                 }
169                 catch (RepositoryException e) {
170                     log.error("can't set property " + key , e);
171                 }
172             }
173         }
174         
175     }
176
177     /**
178      * imports XML stream into repository<p/>
179      * XML is filtered by <code>MagnoliaV2Filter</code>, <code>VersionFilter</code> and <code>ImportXmlRootFilter</code>
180      * if <code>keepVersionHistory</code> is set to <code>false</code>
181      * @param xmlStream XML stream to import
182      * @param repositoryName selected repository
183      * @param basepath base path in repository
184      * @param name (absolute path of <code>File</code>)
185      * @param keepVersionHistory if <code>false</code> version info will be stripped before importing the document
186      * @param importMode a valid value for ImportUUIDBehavior
187      * @param saveAfterImport
188      * @param createBasepathIfNotExist
189      * @throws IOException
190      * @see ImportUUIDBehavior
191      * @see ImportXmlRootFilter
192      * @see VersionFilter
193      * @see MagnoliaV2Filter
194      */

195     public static synchronized void importXmlStream(InputStream JavaDoc xmlStream, String JavaDoc repositoryName, String JavaDoc basepath,
196                                                     String JavaDoc name, boolean keepVersionHistory, int importMode,
197                                                     boolean saveAfterImport, boolean createBasepathIfNotExist)
198             throws IOException JavaDoc {
199
200         HierarchyManager hm = MgnlContext.getHierarchyManager(repositoryName);
201         Workspace ws = hm.getWorkspace();
202
203         if (log.isDebugEnabled()) {
204             log.debug("Importing content into repository: [{}] from: [{}] into path: [{}]", //$NON-NLS-1$
205
new Object JavaDoc[]{repositoryName, name, basepath});
206         }
207
208         if (!hm.isExist(basepath) && createBasepathIfNotExist) {
209             try {
210                 ContentUtil.createPath(hm, basepath, ItemType.CONTENT);
211             }
212             catch (RepositoryException e) {
213                 log.error("can't create path [{}]", basepath); //$NON-NLS-1$
214
}
215         }
216
217         Session session = ws.getSession();
218
219         try {
220             if (keepVersionHistory) {
221                 // do not manipulate
222
session.importXML(basepath, xmlStream, importMode);
223             }
224             else {
225                 // create readers/filters and chain
226
XMLReader JavaDoc initialReader = XMLReaderFactory.createXMLReader(org.apache.xerces.parsers.SAXParser.class.getName());
227
228                 XMLFilter JavaDoc magnoliaV2Filter = null;
229
230                 // if stream is from regular file, test for belonging XSL file to apply XSL transformation to XML
231
if (new File JavaDoc(name).isFile()) {
232                     InputStream JavaDoc xslStream = getXslStreamForXmlFile(new File JavaDoc(name));
233                     if (xslStream != null) {
234                         Source JavaDoc xslSource = new StreamSource JavaDoc(xslStream);
235                         SAXTransformerFactory JavaDoc saxTransformerFactory = (SAXTransformerFactory JavaDoc) SAXTransformerFactory.newInstance();
236                         XMLFilter JavaDoc xslFilter = saxTransformerFactory.newXMLFilter(xslSource);
237                         magnoliaV2Filter = new MagnoliaV2Filter(xslFilter);
238                     }
239                 }
240
241                 if (magnoliaV2Filter == null) {
242                     magnoliaV2Filter = new MagnoliaV2Filter(initialReader);
243                 }
244
245                 XMLFilter JavaDoc versionFilter = new VersionFilter(magnoliaV2Filter);
246                 XMLReader JavaDoc finalReader = new ImportXmlRootFilter(versionFilter);
247
248                 ContentHandler JavaDoc handler = session.getImportContentHandler(basepath, importMode);
249                 finalReader.setContentHandler(handler);
250
251                 // parse XML, import is done by handler from session
252
try {
253                     finalReader.parse(new InputSource JavaDoc(xmlStream));
254                 }
255                 finally {
256                     IOUtils.closeQuietly(xmlStream);
257                 }
258
259                 if (((ImportXmlRootFilter) finalReader).rootNodeFound) {
260                     String JavaDoc path = basepath;
261                     if (!path.endsWith(SLASH)) {
262                         path += SLASH;
263                     }
264
265                     Node dummyRoot = (Node) session.getItem(path + JCR_ROOT);
266                     for (Iterator JavaDoc iter = dummyRoot.getNodes(); iter.hasNext();) {
267                         Node child = (Node) iter.next();
268                         // move childs to real root
269

270                         if (session.itemExists(path + child.getName())) {
271                             session.getItem(path + child.getName()).remove();
272                         }
273
274                         session.move(child.getPath(), path + child.getName());
275                     }
276                     // delete the dummy node
277
dummyRoot.remove();
278                 }
279             }
280         }
281         catch (Exception JavaDoc e) {
282             throw new NestableRuntimeException(e);
283         }
284         finally {
285             IOUtils.closeQuietly(xmlStream);
286         }
287
288         try {
289             if (saveAfterImport) {
290                 session.save();
291             }
292         }
293         catch (RepositoryException e) {
294             log.error(MessageFormat.format(
295                     "Unable to save changes to the [{0}] repository due to a {1} Exception: {2}.", //$NON-NLS-1$
296
new Object JavaDoc[]{repositoryName, e.getClass().getName(), e.getMessage()}), e);
297             throw new IOException JavaDoc(e.getMessage());
298         }
299     }
300
301     /**
302      * @param file
303      * @return XSL stream for Xml file or <code>null</code>
304      */

305     protected static InputStream JavaDoc getXslStreamForXmlFile(File JavaDoc file) {
306         InputStream JavaDoc xslStream = null;
307         String JavaDoc xlsFilename = StringUtils.substringBeforeLast(file.getAbsolutePath(), ".") + ".xsl"; //$NON-NLS-1$
308
File JavaDoc xslFile = new File JavaDoc(xlsFilename);
309         if (xslFile.exists()) {
310             try {
311                 xslStream = new FileInputStream JavaDoc(xslFile);
312                 log.info("XSL file for [" + file.getName() + "] found (" + xslFile.getName() + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
313
} catch (FileNotFoundException JavaDoc e) { // should never happen (xslFile.exists())
314
e.printStackTrace();
315             }
316         }
317         return xslStream;
318     }
319
320     /**
321      * creates a stream from the (zipped/gzipped) XML file
322      * @param xmlFile
323      * @return stream of the file
324      * @throws IOException
325      */

326     private static InputStream JavaDoc getInputStreamForFile(File JavaDoc xmlFile) throws IOException JavaDoc {
327         InputStream JavaDoc xmlStream;
328         // looks like the zip one is buggy. It throws exception when trying to use it
329
if (xmlFile.getName().endsWith(ZIP)) {
330             xmlStream = new ZipInputStream JavaDoc((new FileInputStream JavaDoc(xmlFile)));
331         }
332         else if (xmlFile.getName().endsWith(GZ)) {
333             xmlStream = new GZIPInputStream JavaDoc((new FileInputStream JavaDoc(xmlFile)));
334         }
335         else { // if(fileName.endsWith(XML))
336
xmlStream = new FileInputStream JavaDoc(xmlFile);
337         }
338         return xmlStream;
339     }
340
341
342     public static void executeExport(OutputStream JavaDoc baseOutputStream, boolean keepVersionHistory, boolean format,
343                                      Session session, String JavaDoc basepath, String JavaDoc repository, String JavaDoc ext) throws IOException JavaDoc {
344         OutputStream JavaDoc outputStream = baseOutputStream;
345         if (ext.endsWith(ZIP)) {
346             outputStream = new ZipOutputStream JavaDoc(baseOutputStream);
347         }
348         else if (ext.endsWith(GZ)) {
349             outputStream = new GZIPOutputStream JavaDoc(baseOutputStream);
350         }
351
352         try {
353             if (keepVersionHistory) {
354                 // use exportSystemView in order to preserve property types
355
// http://issues.apache.org/jira/browse/JCR-115
356
if (!format) {
357                     session.exportSystemView(basepath, outputStream, false, false);
358                 }
359                 else {
360                     parseAndFormat(outputStream, null, repository, basepath, session, false);
361                 }
362             }
363             else {
364                 // use XMLSerializer and a SAXFilter in order to rewrite the
365
// file
366
XMLReader JavaDoc reader = new VersionFilter(XMLReaderFactory
367                         .createXMLReader(org.apache.xerces.parsers.SAXParser.class.getName()));
368                 parseAndFormat(outputStream, reader, repository, basepath, session, false);
369             }
370         }
371         catch (IOException JavaDoc e) {
372             throw new NestableRuntimeException(e);
373         }
374         catch (SAXException JavaDoc e) {
375             throw new NestableRuntimeException(e);
376         }
377         catch (RepositoryException e) {
378             throw new NestableRuntimeException(e);
379         }
380
381         // finish the stream properly if zip stream
382
// this is not done by the IOUtils
383
if (outputStream instanceof DeflaterOutputStream JavaDoc) {
384             ((DeflaterOutputStream JavaDoc) outputStream).finish();
385         }
386
387         baseOutputStream.flush();
388         IOUtils.closeQuietly(baseOutputStream);
389     }
390
391     /**
392      * This export the content of the repository, and format it if necessary
393      * @param stream the stream to write the content to
394      * @param reader the reader to use to parse the xml content (so that we can perform filtering), if null instanciate
395      * a default one
396      * @param repository the repository to export
397      * @param basepath the basepath in the repository
398      * @param session the session to use to export the data from the repository
399      * @param noRecurse
400      * @throws IOException
401      * @throws SAXException
402      * @throws RepositoryException
403      * @throws PathNotFoundException
404      */

405     public static void parseAndFormat(OutputStream JavaDoc stream, XMLReader JavaDoc reader, String JavaDoc repository, String JavaDoc basepath,
406                                       Session session, boolean noRecurse)
407             throws IOException JavaDoc, SAXException JavaDoc, PathNotFoundException, RepositoryException {
408
409         if (reader == null) {
410             reader = XMLReaderFactory.createXMLReader(org.apache.xerces.parsers.SAXParser.class.getName());
411         }
412
413         // write to a temp file and then re-read it to remove version history
414
File JavaDoc tempFile = File.createTempFile("export-" + repository + session.getUserID(), "xml"); //$NON-NLS-1$ //$NON-NLS-2$
415
OutputStream JavaDoc fileStream = new FileOutputStream JavaDoc(tempFile);
416
417         try {
418             session.exportSystemView(basepath, fileStream, false, noRecurse);
419         }
420         finally {
421             IOUtils.closeQuietly(fileStream);
422         }
423
424         readFormatted(reader, tempFile, stream);
425
426         if (!tempFile.delete()) {
427             log.warn("Could not delete temporary export file {}", tempFile.getAbsolutePath()); //$NON-NLS-1$
428
}
429     }
430
431     /**
432      * @param reader
433      * @param inputFile
434      * @param outputStream
435      * @throws FileNotFoundException
436      * @throws IOException
437      * @throws SAXException
438      */

439     protected static void readFormatted(XMLReader JavaDoc reader, File JavaDoc inputFile, OutputStream JavaDoc outputStream)
440             throws FileNotFoundException JavaDoc, IOException JavaDoc, SAXException JavaDoc {
441         InputStream JavaDoc fileInputStream = new FileInputStream JavaDoc(inputFile);
442         readFormatted(reader, fileInputStream, outputStream);
443         IOUtils.closeQuietly(fileInputStream);
444     }
445
446     /**
447      * @param reader
448      * @param inputStream
449      * @param outputStream
450      * @throws FileNotFoundException
451      * @throws IOException
452      * @throws SAXException
453      */

454     protected static void readFormatted(XMLReader JavaDoc reader, InputStream JavaDoc inputStream, OutputStream JavaDoc outputStream)
455             throws FileNotFoundException JavaDoc, IOException JavaDoc, SAXException JavaDoc {
456
457         OutputFormat outputFormat = new OutputFormat();
458
459         outputFormat.setPreserveSpace(false); // this is ok, doesn't affect text nodes??
460
outputFormat.setIndenting(true);
461         outputFormat.setIndent(INDENT_VALUE);
462         outputFormat.setLineWidth(120); // need to be set after setIndenting()!
463

464         reader.setContentHandler(new XMLSerializer(outputStream, outputFormat));
465         reader.parse(new InputSource JavaDoc(inputStream));
466
467         IOUtils.closeQuietly(inputStream);
468     }
469
470 }
471
Popular Tags