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 ; 16 import java.io.FileInputStream ; 17 import java.io.FileOutputStream ; 18 import java.io.IOException ; 19 import java.io.InputStream ; 20 import java.io.OutputStream ; 21 import java.io.PrintWriter ; 22 import java.text.MessageFormat ; 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 ; 29 import javax.servlet.http.HttpServlet ; 30 import javax.servlet.http.HttpServletRequest ; 31 import javax.servlet.http.HttpServletResponse ; 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 ; 41 import org.xml.sax.XMLReader ; 42 import org.xml.sax.helpers.XMLReaderFactory ; 43 44 45 50 public class ImportExportServlet extends HttpServlet { 51 52 55 private static final long serialVersionUID = 222L; 56 57 60 private static final String PARAM_REPOSITORY = "mgnlRepository"; 62 65 private static final String PARAM_PATH = "mgnlPath"; 67 70 private static final String PARAM_KEEPVERSIONS = "mgnlKeepVersions"; 72 75 private static final String PARAM_FORMAT = "mgnlFormat"; 77 80 private static final String PARAM_FILE = "mgnlFileImport"; 82 85 private static final String PARAM_UUID_BEHAVIOR = "mgnlUuidBehavior"; 87 90 private static final String PARAM_REDIRECT = "mgnlRedirect"; 92 95 private static final String PARAM_EXPORT_ACTION = "exportxml"; 97 100 private static final int INDENT_VALUE = 2; 102 105 private static Logger log = Logger.getLogger(ImportExportServlet.class); 106 107 110 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException , ServletException { 111 112 try { 113 request.setCharacterEncoding("UTF-8"); } 115 catch (IllegalStateException e) { 116 } 118 119 String repository = request.getParameter(PARAM_REPOSITORY); 120 if (StringUtils.isEmpty(repository)) { 121 repository = ContentRepository.WEBSITE; 122 } 123 String basepath = request.getParameter(PARAM_PATH); 124 if (StringUtils.isEmpty(basepath)) { 125 basepath = "/"; } 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 (new AccessDeniedException( 139 "Write permission needed for export. User not allowed to WRITE path [" + basepath + "]")); } 142 143 if (StringUtils.contains(request.getRequestURI(), "import")) { displayImportForm(request, response.getWriter(), repository, basepath); 145 } 146 else { 147 displayExportForm(request, response.getWriter(), repository, basepath); 148 } 149 } 150 151 157 private void displayExportForm(HttpServletRequest request, PrintWriter out, String repository, String basepath) { 158 159 out.println("<html><head><title>Magnolia</title>"); out.println(new Sources(request.getContextPath()).getHtmlCss()); 161 out.println("</head><body class=\"mgnlBgLight mgnlImportExport\">"); 163 out.println("<h2>"); out.println(MessagesManager.get(request, "importexport.export")); out.println("</h2>"); out.println("<form method=\"get\" action=\"\">"); 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=\"" + PARAM_EXPORT_ACTION + "\" value=\"" + MessagesManager.get(request, "importexport.export") + "\" />"); 178 out.println("</form></body></html>"); } 180 181 187 private void displayImportForm(HttpServletRequest request, PrintWriter out, String repository, String basepath) { 188 189 out.println("<html><head><title>Magnolia</title>"); out.println(new Sources(request.getContextPath()).getHtmlCss()); 191 out.println("</head><body class=\"mgnlBgLight mgnlImportExport\">"); 193 out.println("<h2>"); out.println(MessagesManager.get(request, "importexport.import")); out.println("</h2>"); out.println("<form method=\"post\" action=\"\" enctype=\"multipart/form-data\">"); 198 writeRepositoryField(request, out, repository); 199 writeBasePathField(request, out, basepath); 200 writeKeepVersionField(request, out); 201 out.println(MessagesManager.get(request, "importexport.file") + " <input type=\"file\" name=\"" + PARAM_FILE + "\" /><br/>"); 204 out.println("<input type=\"radio\" name=\"" + PARAM_UUID_BEHAVIOR + "\" value=\"" + ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW + "\">"); out.println(MessagesManager.get(request, "importexport.createnew")); out.println("<br/>"); 210 out.println("<input type=\"radio\" name=\"" + PARAM_UUID_BEHAVIOR + "\" value=\"" + ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING + "\">"); out.println(MessagesManager.get(request, "importexport.removeexisting")); out.println("<br/>"); 216 out.println("<input type=\"radio\" name=\"" + PARAM_UUID_BEHAVIOR + "\" value=\"" + ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING + "\">"); out.println(MessagesManager.get(request, "importexport.replaceexisting")); out.println("<br/>"); 222 out.println("<input type=\"submit\" name=\"" + PARAM_EXPORT_ACTION + "\" value=\"" + MessagesManager.get(request, "importexport.import") + "\" />"); 227 out.println("</form></body></html>"); } 229 230 234 private void writeBasePathField(HttpServletRequest request, PrintWriter out, String basepath) { 235 out.println(MessagesManager.get(request, "importexport.basepath") + " <input name=\"" + PARAM_PATH + "\" value=\"" + basepath + "\" /><br/>"); } 240 241 244 private void writeKeepVersionField(HttpServletRequest request, PrintWriter out) { 245 out.println(MessagesManager.get(request, "importexport.keepversions") + " <input name=\"" + PARAM_KEEPVERSIONS + "\" value=\"true\" type=\"checkbox\"/><br/>"); } 249 250 253 private void writeFormatField(HttpServletRequest request, PrintWriter out) { 254 out.println(MessagesManager.get(request, "importexport.format") + " <input name=\"" + PARAM_FORMAT + "\" value=\"true\" type=\"checkbox\"/><br/>"); } 258 259 263 private void writeRepositoryField(HttpServletRequest request, PrintWriter out, String repository) { 264 out.println(MessagesManager.get(request, "importexport.repository") + " <select name=\"" + PARAM_REPOSITORY + "\">"); 268 String [] repositories = ContentRepository.getAllRepositoryNames(); 269 for (int j = 0; j < repositories.length; j++) { 270 out.print("<option"); if (repository.equals(repositories[j])) { 272 out.print(" selected=\"selected\""); } 274 out.print(">"); out.print(repositories[j]); 276 out.print("</option>"); } 278 out.println("</select>"); out.println("<br/>"); } 281 282 286 public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException , ServletException { 287 288 log.debug("Import request received."); 290 MultipartForm form = Resource.getPostedForm(request); 291 if (form == null) { 292 log.error("Missing form."); return; 294 } 295 296 String basepath = form.getParameter(PARAM_PATH); 297 if (StringUtils.isEmpty(basepath)) { 298 basepath = "/"; } 300 301 boolean keepVersionHistory = BooleanUtils.toBoolean(form.getParameter(PARAM_KEEPVERSIONS)); 302 303 String repository = form.getParameter(PARAM_REPOSITORY); 304 Document xmlFile = form.getDocument(PARAM_FILE); 305 if (StringUtils.isEmpty(repository) || xmlFile == null) { 306 throw new RuntimeException ("Wrong parameters"); } 308 309 String 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 (new AccessDeniedException( 321 "Write permission needed for import. User not allowed to WRITE path [" + basepath + "]")); } 324 325 String redirectPage = form.getParameter(PARAM_REDIRECT); 326 if (StringUtils.isNotBlank(redirectPage)) { 327 if (log.isInfoEnabled()) { 328 log.info(MessageFormat.format("Redirecting to [{0}]", new Object []{redirectPage})); 330 } 331 response.sendRedirect(redirectPage); 332 } 333 else { 334 doGet(request, response); 335 } 336 } 337 338 347 private void executeExport(HttpServletResponse response, String repository, String basepath, boolean format, 348 boolean keepVersionHistory) throws IOException { 349 HierarchyManager hr = ContentRepository.getHierarchyManager(repository); 350 Workspace ws = hr.getWorkspace(); 351 OutputStream stream = response.getOutputStream(); 352 response.setContentType("text/xml"); response.setCharacterEncoding("UTF-8"); String pathName = StringUtils.replace(basepath, "/", "."); if (".".equals(pathName)) { pathName = StringUtils.EMPTY; 358 } 359 response.setHeader("content-disposition", "attachment; filename=" + repository + pathName + ".xml"); 361 Session session = ws.getSession(); 362 363 try { 364 if (keepVersionHistory) { 365 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 XMLReader 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 e) { 382 throw new NestableRuntimeException(e); 383 } 384 385 stream.flush(); 386 stream.close(); 387 } 388 389 400 private void parseAndFormat(OutputStream stream, XMLReader reader, String repository, String basepath, 401 boolean format, Session session) throws Exception { 402 403 if (reader == null) { 404 reader = XMLReaderFactory.createXMLReader(org.apache.xerces.parsers.SAXParser.class.getName()); 405 } 406 407 File tempFile = File.createTempFile("export-" + repository + session.getUserID(), "xml"); tempFile.deleteOnExit(); 410 OutputStream fileStream = new FileOutputStream (tempFile); 411 412 try { 413 session.exportSystemView(basepath, fileStream, false, false); 414 } 415 finally { 416 try { 417 fileStream.close(); 418 } 419 catch (IOException e) { 420 } 422 } 423 424 InputStream fileInputStream = new FileInputStream (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 (fileInputStream)); 434 435 try { 436 fileInputStream.close(); 437 } 438 catch (IOException e) { 439 } 441 442 if (!tempFile.delete()) { 443 log.error("Could not delete temporary export file..." + tempFile.getAbsolutePath()); } 445 } 446 447 456 private void executeImport(String basepath, String 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 []{repository})); } 464 465 InputStream 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 File strippedFile = File.createTempFile("import", "xml"); strippedFile.deleteOnExit(); 477 478 FileOutputStream outstream = new FileOutputStream (strippedFile); 479 480 XMLReader 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 (stream)); 487 } 488 finally { 489 stream.close(); 490 } 491 492 InputStream filteredStream = new FileInputStream (strippedFile); 494 try { 495 session.importXML(basepath, filteredStream, importMode); 496 } 497 finally { 498 try { 499 filteredStream.close(); 500 } 501 catch (Exception e) { 502 } 504 } 505 } 506 } 507 catch (Exception e) { 508 throw new NestableRuntimeException(e); 509 } 510 try { 511 stream.close(); 512 } 513 catch (IOException e) { 514 } 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}.", new Object []{repository, e.getClass().getName(), e.getMessage()}), e); 524 } 525 526 log.info("Import done"); } 528 529 534 protected boolean checkPermissions(HttpServletRequest request, String repository, String 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 |