KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > info > magnolia > cms > servlets > ImportExportServlet


1 package info.magnolia.cms.servlets;
2
3 import info.magnolia.cms.beans.config.ContentRepository;
4 import info.magnolia.cms.beans.config.Bootstrapper.VersionFilter;
5 import info.magnolia.cms.beans.runtime.Document;
6 import info.magnolia.cms.beans.runtime.MultipartForm;
7 import info.magnolia.cms.core.HierarchyManager;
8 import info.magnolia.cms.gui.misc.Sources;
9 import info.magnolia.cms.i18n.MessagesManager;
10 import info.magnolia.cms.security.AccessDeniedException;
11 import info.magnolia.cms.security.Permission;
12 import info.magnolia.cms.security.SessionAccessControl;
13 import info.magnolia.cms.util.Resource;
14
15 import java.io.File JavaDoc;
16 import java.io.FileInputStream 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.io.PrintWriter JavaDoc;
22 import java.text.MessageFormat JavaDoc;
23
24 import javax.jcr.ImportUUIDBehavior;
25 import javax.jcr.RepositoryException;
26 import javax.jcr.Session;
27 import javax.jcr.Workspace;
28 import javax.servlet.ServletException JavaDoc;
29 import javax.servlet.http.HttpServlet JavaDoc;
30 import javax.servlet.http.HttpServletRequest JavaDoc;
31 import javax.servlet.http.HttpServletResponse JavaDoc;
32
33 import org.apache.commons.lang.BooleanUtils;
34 import org.apache.commons.lang.StringUtils;
35 import org.apache.commons.lang.exception.NestableRuntimeException;
36 import org.apache.commons.lang.math.NumberUtils;
37 import org.apache.log4j.Logger;
38 import org.apache.xml.serialize.OutputFormat;
39 import org.apache.xml.serialize.XMLSerializer;
40 import org.xml.sax.InputSource JavaDoc;
41 import org.xml.sax.XMLReader JavaDoc;
42 import org.xml.sax.helpers.XMLReaderFactory JavaDoc;
43
44
45 /**
46  * Simple servlet used to import/export data from jcr using the standard jcr import/export features.
47  * @author Fabrizio Giustina
48  * @version $Id: $
49  */

50 public class ImportExportServlet extends HttpServlet JavaDoc {
51
52     /**
53      * Stable serialVersionUID.
54      */

55     private static final long serialVersionUID = 222L;
56
57     /**
58      * request parameter: repository name.
59      */

60     private static final String JavaDoc PARAM_REPOSITORY = "mgnlRepository"; //$NON-NLS-1$
61

62     /**
63      * request parameter: path.
64      */

65     private static final String JavaDoc PARAM_PATH = "mgnlPath"; //$NON-NLS-1$
66

67     /**
68      * request parameter: keep versions.
69      */

70     private static final String JavaDoc PARAM_KEEPVERSIONS = "mgnlKeepVersions"; //$NON-NLS-1$
71

72     /**
73      * request parameter: format
74      */

75     private static final String JavaDoc PARAM_FORMAT = "mgnlFormat"; //$NON-NLS-1$
76

77     /**
78      * request parameter: imported file.
79      */

80     private static final String JavaDoc PARAM_FILE = "mgnlFileImport"; //$NON-NLS-1$
81

82     /**
83      * request parameter: UUID behavior for import.
84      */

85     private static final String JavaDoc PARAM_UUID_BEHAVIOR = "mgnlUuidBehavior"; //$NON-NLS-1$
86

87     /**
88      * request parameter: redirect page after import.
89      */

90     private static final String JavaDoc PARAM_REDIRECT = "mgnlRedirect"; //$NON-NLS-1$
91

92     /**
93      * request parameter: export requested.
94      */

95     private static final String JavaDoc PARAM_EXPORT_ACTION = "exportxml"; //$NON-NLS-1$
96

97     /**
98      * Number of space for indentation
99      */

100     private static final int INDENT_VALUE = 2; //$NON-NLS-1$
101

102     /**
103      * Logger.
104      */

105     private static Logger log = Logger.getLogger(ImportExportServlet.class);
106
107     /**
108      * @see javax.servlet.http.HttpServlet#doGet(HttpServletRequest, HttpServletResponse)
109      */

110     public void doGet(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) throws IOException JavaDoc, ServletException JavaDoc {
111
112         try {
113             request.setCharacterEncoding("UTF-8"); //$NON-NLS-1$
114
}
115         catch (IllegalStateException JavaDoc e) {
116             // ignore
117
}
118
119         String JavaDoc repository = request.getParameter(PARAM_REPOSITORY);
120         if (StringUtils.isEmpty(repository)) {
121             repository = ContentRepository.WEBSITE;
122         }
123         String JavaDoc basepath = request.getParameter(PARAM_PATH);
124         if (StringUtils.isEmpty(basepath)) {
125             basepath = "/"; //$NON-NLS-1$
126
}
127
128         boolean keepVersionHistory = BooleanUtils.toBoolean(request.getParameter(PARAM_KEEPVERSIONS));
129         boolean format = BooleanUtils.toBoolean(request.getParameter(PARAM_FORMAT));
130
131         if (request.getParameter(PARAM_EXPORT_ACTION) != null) {
132
133             if (checkPermissions(request, repository, basepath, Permission.WRITE)) {
134                 executeExport(response, repository, basepath, format, keepVersionHistory);
135                 return;
136             }
137
138             throw new ServletException JavaDoc(new AccessDeniedException(
139                 "Write permission needed for export. User not allowed to WRITE path [" //$NON-NLS-1$
140
+ basepath + "]")); //$NON-NLS-1$
141
}
142
143         if (StringUtils.contains(request.getRequestURI(), "import")) { //$NON-NLS-1$
144
displayImportForm(request, response.getWriter(), repository, basepath);
145         }
146         else {
147             displayExportForm(request, response.getWriter(), repository, basepath);
148         }
149     }
150
151     /**
152      * Display a simple form for importing/exporting data.
153      * @param response HttpServletResponse
154      * @param repository selected repository
155      * @param basepath base path in repository (extracted from request parameter or default)
156      */

157     private void displayExportForm(HttpServletRequest JavaDoc request, PrintWriter JavaDoc out, String JavaDoc repository, String JavaDoc basepath) {
158
159         out.println("<html><head><title>Magnolia</title>"); //$NON-NLS-1$
160
out.println(new Sources(request.getContextPath()).getHtmlCss());
161         out.println("</head><body class=\"mgnlBgLight mgnlImportExport\">"); //$NON-NLS-1$
162

163         out.println("<h2>"); //$NON-NLS-1$
164
out.println(MessagesManager.get(request, "importexport.export")); //$NON-NLS-1$
165
out.println("</h2>"); //$NON-NLS-1$
166
out.println("<form method=\"get\" action=\"\">"); //$NON-NLS-1$
167

168         writeRepositoryField(request, out, repository);
169         writeBasePathField(request, out, basepath);
170         writeKeepVersionField(request, out);
171         writeFormatField(request, out);
172
173         out.println("<input type=\"submit\" name=\"" //$NON-NLS-1$
174
+ PARAM_EXPORT_ACTION + "\" value=\"" //$NON-NLS-1$
175
+ MessagesManager.get(request, "importexport.export") //$NON-NLS-1$
176
+ "\" />"); //$NON-NLS-1$
177

178         out.println("</form></body></html>"); //$NON-NLS-1$
179
}
180
181     /**
182      * Display a simple form for importing/exporting data.
183      * @param response HttpServletResponse
184      * @param repository selected repository
185      * @param basepath base path in repository (extracted from request parameter or default)
186      */

187     private void displayImportForm(HttpServletRequest JavaDoc request, PrintWriter JavaDoc out, String JavaDoc repository, String JavaDoc basepath) {
188
189         out.println("<html><head><title>Magnolia</title>"); //$NON-NLS-1$
190
out.println(new Sources(request.getContextPath()).getHtmlCss());
191         out.println("</head><body class=\"mgnlBgLight mgnlImportExport\">"); //$NON-NLS-1$
192

193         out.println("<h2>"); //$NON-NLS-1$
194
out.println(MessagesManager.get(request, "importexport.import")); //$NON-NLS-1$
195
out.println("</h2>"); //$NON-NLS-1$
196
out.println("<form method=\"post\" action=\"\" enctype=\"multipart/form-data\">"); //$NON-NLS-1$
197

198         writeRepositoryField(request, out, repository);
199         writeBasePathField(request, out, basepath);
200         writeKeepVersionField(request, out);
201         out.println(MessagesManager.get(request, "importexport.file") //$NON-NLS-1$
202
+ " <input type=\"file\" name=\"" + PARAM_FILE + "\" /><br/>"); //$NON-NLS-1$//$NON-NLS-2$
203

204         out.println("<input type=\"radio\" name=\"" //$NON-NLS-1$
205
+ PARAM_UUID_BEHAVIOR + "\" value=\"" //$NON-NLS-1$
206
+ ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW + "\">"); //$NON-NLS-1$
207
out.println(MessagesManager.get(request, "importexport.createnew")); //$NON-NLS-1$
208
out.println("<br/>"); //$NON-NLS-1$
209

210         out.println("<input type=\"radio\" name=\"" //$NON-NLS-1$
211
+ PARAM_UUID_BEHAVIOR + "\" value=\"" //$NON-NLS-1$
212
+ ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING + "\">"); //$NON-NLS-1$
213
out.println(MessagesManager.get(request, "importexport.removeexisting")); //$NON-NLS-1$
214
out.println("<br/>"); //$NON-NLS-1$
215

216         out.println("<input type=\"radio\" name=\"" //$NON-NLS-1$
217
+ PARAM_UUID_BEHAVIOR + "\" value=\"" //$NON-NLS-1$
218
+ ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING + "\">"); //$NON-NLS-1$
219
out.println(MessagesManager.get(request, "importexport.replaceexisting")); //$NON-NLS-1$
220
out.println("<br/>"); //$NON-NLS-1$
221

222         out.println("<input type=\"submit\" name=\"" //$NON-NLS-1$
223
+ PARAM_EXPORT_ACTION + "\" value=\"" //$NON-NLS-1$
224
+ MessagesManager.get(request, "importexport.import") //$NON-NLS-1$
225
+ "\" />"); //$NON-NLS-1$
226

227         out.println("</form></body></html>"); //$NON-NLS-1$
228
}
229
230     /**
231      * @param out
232      * @param basepath
233      */

234     private void writeBasePathField(HttpServletRequest JavaDoc request, PrintWriter JavaDoc out, String JavaDoc basepath) {
235         out.println(MessagesManager.get(request, "importexport.basepath") //$NON-NLS-1$
236
+ " <input name=\"" //$NON-NLS-1$
237
+ PARAM_PATH + "\" value=\"" //$NON-NLS-1$
238
+ basepath + "\" /><br/>"); //$NON-NLS-1$
239
}
240
241     /**
242      * @param out
243      */

244     private void writeKeepVersionField(HttpServletRequest JavaDoc request, PrintWriter JavaDoc out) {
245         out.println(MessagesManager.get(request, "importexport.keepversions") //$NON-NLS-1$
246
+ " <input name=\"" //$NON-NLS-1$
247
+ PARAM_KEEPVERSIONS + "\" value=\"true\" type=\"checkbox\"/><br/>"); //$NON-NLS-1$
248
}
249
250     /**
251      * @param out
252      */

253     private void writeFormatField(HttpServletRequest JavaDoc request, PrintWriter JavaDoc out) {
254         out.println(MessagesManager.get(request, "importexport.format") //$NON-NLS-1$
255
+ " <input name=\"" //$NON-NLS-1$
256
+ PARAM_FORMAT + "\" value=\"true\" type=\"checkbox\"/><br/>"); //$NON-NLS-1$
257
}
258
259     /**
260      * @param out
261      * @param repository
262      */

263     private void writeRepositoryField(HttpServletRequest JavaDoc request, PrintWriter JavaDoc out, String JavaDoc repository) {
264         out.println(MessagesManager.get(request, "importexport.repository") //$NON-NLS-1$
265
+ " <select name=\"" //$NON-NLS-1$
266
+ PARAM_REPOSITORY + "\">"); //$NON-NLS-1$
267

268         String JavaDoc[] repositories = ContentRepository.getAllRepositoryNames();
269         for (int j = 0; j < repositories.length; j++) {
270             out.print("<option"); //$NON-NLS-1$
271
if (repository.equals(repositories[j])) {
272                 out.print(" selected=\"selected\""); //$NON-NLS-1$
273
}
274             out.print(">"); //$NON-NLS-1$
275
out.print(repositories[j]);
276             out.print("</option>"); //$NON-NLS-1$
277
}
278         out.println("</select>"); //$NON-NLS-1$
279
out.println("<br/>"); //$NON-NLS-1$
280
}
281
282     /**
283      * A post request is usually an import request.
284      * @see javax.servlet.http.HttpServlet#doPost(HttpServletRequest, HttpServletResponse)
285      */

286     public void doPost(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response) throws IOException JavaDoc, ServletException JavaDoc {
287
288         log.debug("Import request received."); //$NON-NLS-1$
289

290         MultipartForm form = Resource.getPostedForm(request);
291         if (form == null) {
292             log.error("Missing form."); //$NON-NLS-1$
293
return;
294         }
295
296         String JavaDoc basepath = form.getParameter(PARAM_PATH);
297         if (StringUtils.isEmpty(basepath)) {
298             basepath = "/"; //$NON-NLS-1$
299
}
300
301         boolean keepVersionHistory = BooleanUtils.toBoolean(form.getParameter(PARAM_KEEPVERSIONS));
302
303         String JavaDoc repository = form.getParameter(PARAM_REPOSITORY);
304         Document xmlFile = form.getDocument(PARAM_FILE);
305         if (StringUtils.isEmpty(repository) || xmlFile == null) {
306             throw new RuntimeException JavaDoc("Wrong parameters"); //$NON-NLS-1$
307
}
308
309         String JavaDoc uuidBehaviorString = form.getParameter(PARAM_UUID_BEHAVIOR);
310
311         int uuidBehavior = ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW;
312         if (NumberUtils.isNumber(uuidBehaviorString)) {
313             uuidBehavior = Integer.parseInt(uuidBehaviorString);
314         }
315
316         if (checkPermissions(request, repository, basepath, Permission.WRITE)) {
317             executeImport(basepath, repository, xmlFile, keepVersionHistory, uuidBehavior);
318         }
319         else {
320             throw new ServletException JavaDoc(new AccessDeniedException(
321                 "Write permission needed for import. User not allowed to WRITE path [" //$NON-NLS-1$
322
+ basepath + "]")); //$NON-NLS-1$
323
}
324
325         String JavaDoc redirectPage = form.getParameter(PARAM_REDIRECT);
326         if (StringUtils.isNotBlank(redirectPage)) {
327             if (log.isInfoEnabled()) {
328                 log.info(MessageFormat.format("Redirecting to [{0}]", //$NON-NLS-1$
329
new Object JavaDoc[]{redirectPage}));
330             }
331             response.sendRedirect(redirectPage);
332         }
333         else {
334             doGet(request, response);
335         }
336     }
337
338     /**
339      * Actually perform export. The generated file is sent to the client.
340      * @param response HttpServletResponse
341      * @param repository selected repository
342      * @param basepath base path in repository
343      * @param format should we format the resulting xml
344      * @param keepVersionHistory if <code>false</code> version info will be stripped from the exported document
345      * @throws IOException for errors while accessing the servlet output stream
346      */

347     private void executeExport(HttpServletResponse JavaDoc response, String JavaDoc repository, String JavaDoc basepath, boolean format,
348         boolean keepVersionHistory) throws IOException JavaDoc {
349         HierarchyManager hr = ContentRepository.getHierarchyManager(repository);
350         Workspace ws = hr.getWorkspace();
351         OutputStream JavaDoc stream = response.getOutputStream();
352         response.setContentType("text/xml"); //$NON-NLS-1$
353
response.setCharacterEncoding("UTF-8"); //$NON-NLS-1$
354
String JavaDoc pathName = StringUtils.replace(basepath, "/", "."); //$NON-NLS-1$ //$NON-NLS-2$
355
if (".".equals(pathName)) { //$NON-NLS-1$
356
// root node
357
pathName = StringUtils.EMPTY;
358         }
359         response.setHeader("content-disposition", "attachment; filename=" + repository + pathName + ".xml"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
360

361         Session session = ws.getSession();
362
363         try {
364             if (keepVersionHistory) {
365                 // use exportSystemView in order to preserve property types
366
// http://issues.apache.org/jira/browse/JCR-115
367
if (!format) {
368                     session.exportSystemView(basepath, stream, false, false);
369                 }
370                 else {
371                     parseAndFormat(stream, null, repository, basepath, format, session);
372                 }
373             }
374             else {
375                 // use XMLSerializer and a SAXFilter in order to rewrite the file
376
XMLReader JavaDoc reader = new VersionFilter(XMLReaderFactory
377                     .createXMLReader(org.apache.xerces.parsers.SAXParser.class.getName()));
378                 parseAndFormat(stream, reader, repository, basepath, format, session);
379             }
380         }
381         catch (Exception JavaDoc e) {
382             throw new NestableRuntimeException(e);
383         }
384
385         stream.flush();
386         stream.close();
387     }
388
389     /**
390      * This export the content of the repository, and format it if necessary
391      * @param stream the stream to write the content to
392      * @param reader the reader to use to parse the xml content (so that we can perform filtering), if null instanciate
393      * a default one
394      * @param repository the repository to export
395      * @param basepath the basepath in the repository
396      * @param format should we format the xml
397      * @param session the session to use to export the data from the repository
398      * @throws Exception if anything goes wrong ...
399      */

400     private void parseAndFormat(OutputStream JavaDoc stream, XMLReader JavaDoc reader, String JavaDoc repository, String JavaDoc basepath,
401         boolean format, Session session) throws Exception JavaDoc {
402
403         if (reader == null) {
404             reader = XMLReaderFactory.createXMLReader(org.apache.xerces.parsers.SAXParser.class.getName());
405         }
406
407         // write to a temp file and then re-read it to remove version history
408
File JavaDoc tempFile = File.createTempFile("export-" + repository + session.getUserID(), "xml"); //$NON-NLS-1$ //$NON-NLS-2$
409
tempFile.deleteOnExit();
410         OutputStream JavaDoc fileStream = new FileOutputStream JavaDoc(tempFile);
411
412         try {
413             session.exportSystemView(basepath, fileStream, false, false);
414         }
415         finally {
416             try {
417                 fileStream.close();
418             }
419             catch (IOException JavaDoc e) {
420                 // ignore
421
}
422         }
423
424         InputStream JavaDoc fileInputStream = new FileInputStream JavaDoc(tempFile);
425
426         OutputFormat forma = new OutputFormat();
427         if (format) {
428             forma.setIndenting(true);
429             forma.setIndent(INDENT_VALUE);
430         }
431         reader.setContentHandler(new XMLSerializer(stream, forma));
432
433         reader.parse(new InputSource JavaDoc(fileInputStream));
434
435         try {
436             fileInputStream.close();
437         }
438         catch (IOException JavaDoc e) {
439             // ignore
440
}
441
442         if (!tempFile.delete()) {
443             log.error("Could not delete temporary export file..." + tempFile.getAbsolutePath()); //$NON-NLS-1$
444
}
445     }
446
447     /**
448      * Perform import.
449      * @param repository selected repository
450      * @param basepath base path in repository
451      * @param xmlFile uploaded file
452      * @param keepVersionHistory if <code>false</code> version info will be stripped before importing the document
453      * @param importMode a valid value for ImportUUIDBehavior
454      * @see ImportUUIDBehavior
455      */

456     private void executeImport(String JavaDoc basepath, String JavaDoc repository, Document xmlFile, boolean keepVersionHistory,
457         int importMode) {
458         HierarchyManager hr = ContentRepository.getHierarchyManager(repository);
459         Workspace ws = hr.getWorkspace();
460
461         if (log.isInfoEnabled()) {
462             log.info(MessageFormat.format("About to import file into the [{0}] repository", new Object JavaDoc[]{repository})); //$NON-NLS-1$
463
}
464
465         InputStream JavaDoc stream = xmlFile.getStream();
466         Session session = ws.getSession();
467
468         try {
469             if (keepVersionHistory) {
470                 session.importXML(basepath, stream, importMode);
471             }
472             else {
473
474                 // create a temporary file and save the trimmed xml
475
File JavaDoc strippedFile = File.createTempFile("import", "xml"); //$NON-NLS-1$ //$NON-NLS-2$
476
strippedFile.deleteOnExit();
477
478                 FileOutputStream JavaDoc outstream = new FileOutputStream JavaDoc(strippedFile);
479
480                 // use XMLSerializer and a SAXFilter in order to rewrite the file
481
XMLReader JavaDoc reader = new VersionFilter(XMLReaderFactory
482                     .createXMLReader(org.apache.xerces.parsers.SAXParser.class.getName()));
483                 reader.setContentHandler(new XMLSerializer(outstream, new OutputFormat()));
484
485                 try {
486                     reader.parse(new InputSource JavaDoc(stream));
487                 }
488                 finally {
489                     stream.close();
490                 }
491
492                 // return the filtered file as an input stream
493
InputStream JavaDoc filteredStream = new FileInputStream JavaDoc(strippedFile);
494                 try {
495                     session.importXML(basepath, filteredStream, importMode);
496                 }
497                 finally {
498                     try {
499                         filteredStream.close();
500                     }
501                     catch (Exception JavaDoc e) {
502                         // ignore
503
}
504                 }
505             }
506         }
507         catch (Exception JavaDoc e) {
508             throw new NestableRuntimeException(e);
509         }
510         try {
511             stream.close();
512         }
513         catch (IOException JavaDoc e) {
514             // ignore
515
}
516
517         try {
518             session.save();
519         }
520         catch (RepositoryException e) {
521             log.error(MessageFormat.format(
522                 "Unable to save changes to the [{0}] repository due to a {1} Exception: {2}.", //$NON-NLS-1$
523
new Object JavaDoc[]{repository, e.getClass().getName(), e.getMessage()}), e);
524         }
525
526         log.info("Import done"); //$NON-NLS-1$
527
}
528
529     /**
530      * Uses access manager to authorise this request.
531      * @param request HttpServletRequest as received by the service method
532      * @return boolean true if read access is granted
533      */

534     protected boolean checkPermissions(HttpServletRequest JavaDoc request, String JavaDoc repository, String JavaDoc basePath,
535         long permissionType) {
536         if (SessionAccessControl.getAccessManager(request, repository) != null) {
537             if (!SessionAccessControl.getAccessManager(request).isGranted(basePath, permissionType)) {
538                 return false;
539             }
540         }
541         return true;
542     }
543
544 }
Popular Tags