001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.staticexport; 029 030import org.opencms.ade.detailpage.CmsDetailPageUtil; 031import org.opencms.db.CmsPublishedResource; 032import org.opencms.file.CmsObject; 033import org.opencms.file.CmsResource; 034import org.opencms.file.CmsResourceFilter; 035import org.opencms.file.CmsVfsResourceNotFoundException; 036import org.opencms.loader.I_CmsResourceLoader; 037import org.opencms.main.CmsException; 038import org.opencms.main.CmsLog; 039import org.opencms.main.OpenCms; 040import org.opencms.report.I_CmsReport; 041import org.opencms.util.CmsFileUtil; 042import org.opencms.util.CmsRequestUtil; 043import org.opencms.util.CmsStringUtil; 044import org.opencms.util.CmsUUID; 045import org.opencms.workplace.CmsWorkplace; 046 047import java.io.File; 048import java.io.IOException; 049import java.net.HttpURLConnection; 050import java.net.URL; 051import java.util.ArrayList; 052import java.util.Collection; 053import java.util.Collections; 054import java.util.HashMap; 055import java.util.HashSet; 056import java.util.Iterator; 057import java.util.List; 058import java.util.Map; 059import java.util.Set; 060 061import javax.servlet.ServletException; 062import javax.servlet.http.HttpServletResponse; 063 064import org.apache.commons.logging.Log; 065 066/** 067 * Implementation for the <code>{@link I_CmsStaticExportHandler}</code> interface.<p> 068 * 069 * This handler exports all changes immediately after something is published.<p> 070 * 071 * @since 6.0.0 072 * 073 * @see I_CmsStaticExportHandler 074 */ 075public class CmsAfterPublishStaticExportHandler extends A_CmsStaticExportHandler { 076 077 /** Header field set-cookie constant. */ 078 private static final String HEADER_FIELD_SET_COOKIE = "Set-Cookie"; 079 080 /** The log object for this class. */ 081 private static final Log LOG = CmsLog.getLog(CmsAfterPublishStaticExportHandler.class); 082 083 /** Request method get constant. */ 084 private static final String REQUEST_METHOD_GET = "GET"; 085 086 /** Request property cookie constant. */ 087 private static final String REQUEST_PROPERTY_COOKIE = "Cookie"; 088 089 /** 090 * Does the actual static export.<p> 091 * 092 * @param resources a list of CmsPublishedREsources to start the static export with 093 * @param report an <code>{@link I_CmsReport}</code> instance to print output message, or <code>null</code> to write messages to the log file 094 * 095 * @throws CmsException in case of errors accessing the VFS 096 * @throws IOException in case of errors writing to the export output stream 097 * @throws ServletException in case of errors accessing the servlet 098 */ 099 public void doExportAfterPublish(List<CmsPublishedResource> resources, I_CmsReport report) 100 throws CmsException, IOException, ServletException { 101 102 boolean templatesFound; 103 104 // export must be done in the context of the export user 105 // this will always use the root site 106 CmsObject cmsExportObject = OpenCms.initCmsObject(OpenCms.getDefaultUsers().getUserExport()); 107 108 List<CmsPublishedResource> resourcesToExport = getRelatedResources(cmsExportObject, resources); 109 // first export all non-template resources 110 templatesFound = exportNonTemplateResources(cmsExportObject, resourcesToExport, report); 111 LOG.warn("finished exporting non-template resources. "); 112 113 // export template resources (check "plainoptimization" setting) 114 if ((templatesFound) || (!OpenCms.getStaticExportManager().getQuickPlainExport())) { 115 CmsStaticExportManager manager = OpenCms.getStaticExportManager(); 116 117 // build resource filter set 118 Set<String> resourceFilter = new HashSet<String>(); 119 for (CmsPublishedResource pubResource : resourcesToExport) { 120 String rfsName = manager.getRfsName(cmsExportObject, pubResource.getRootPath()); 121 resourceFilter.add(rfsName.substring(manager.getRfsPrefixForRfsName(rfsName).length())); 122 } 123 124 long timestamp = 0; 125 List<String> publishedTemplateResources; 126 boolean newTemplateLinksFound; 127 int linkMode = CmsStaticExportManager.EXPORT_LINK_WITHOUT_PARAMETER; 128 do { 129 // get all template resources which are potential candidates for a static export 130 publishedTemplateResources = cmsExportObject.readStaticExportResources(linkMode, timestamp); 131 if (publishedTemplateResources == null) { 132 break; 133 } 134 newTemplateLinksFound = publishedTemplateResources.size() > 0; 135 if (newTemplateLinksFound) { 136 if (linkMode == CmsStaticExportManager.EXPORT_LINK_WITHOUT_PARAMETER) { 137 // first loop, switch mode to parameter links, leave the timestamp unchanged 138 linkMode = CmsStaticExportManager.EXPORT_LINK_WITH_PARAMETER; 139 // filter without parameter 140 publishedTemplateResources.retainAll(resourceFilter); 141 } else { 142 // second and subsequent loops, only look for links not already exported 143 // this can only be the case for a link with parameters 144 // that was present on a page also generated with parameters 145 timestamp = System.currentTimeMillis(); 146 // filter with parameter 147 Iterator<String> itPubTemplates = publishedTemplateResources.iterator(); 148 while (itPubTemplates.hasNext()) { 149 String rfsName = itPubTemplates.next(); 150 if (!resourceFilter.contains(rfsName.substring(0, rfsName.lastIndexOf('_')))) { 151 itPubTemplates.remove(); 152 } 153 } 154 } 155 // leave if no template left 156 if (publishedTemplateResources.isEmpty()) { 157 break; 158 } 159 // export 160 LOG.warn("exporting template resources. "); 161 exportTemplateResources(cmsExportObject, publishedTemplateResources, report); 162 } 163 // if no new template links where found we are finished 164 } while (newTemplateLinksFound); 165 } 166 } 167 168 /** 169 * Returns all resources within the current OpenCms site that are not marked as internal.<p> 170 * 171 * The result list contains objects of type {@link CmsPublishedResource}.<p> 172 * 173 * @param cms the cms context 174 * 175 * @return all resources within the current OpenCms site that are not marked as internal 176 * 177 * @throws CmsException if something goes wrong 178 */ 179 public List<CmsPublishedResource> getAllResources(CmsObject cms) throws CmsException { 180 181 if (LOG.isDebugEnabled()) { 182 LOG.debug(Messages.get().getBundle().key(Messages.LOG_GET_ALL_RESOURCES_0)); 183 } 184 // TODO: to improve performance, get here only the resources to render from the configuration 185 186 // read all from the root path, exclude resources flagged as internal 187 List<CmsResource> vfsResources = cms.readResources( 188 "/", 189 CmsResourceFilter.ALL.addExcludeFlags(CmsResource.FLAG_INTERNAL)); 190 191 CmsExportFolderMatcher matcher = OpenCms.getStaticExportManager().getExportFolderMatcher(); 192 // loop through the list and create the list of CmsPublishedResources 193 List<CmsPublishedResource> resources = new ArrayList<CmsPublishedResource>(vfsResources.size()); 194 Iterator<CmsResource> i = vfsResources.iterator(); 195 while (i.hasNext()) { 196 CmsResource resource = i.next(); 197 if (!matcher.match(resource.getRootPath())) { 198 // filter files that do not match the resources to render 199 continue; 200 } 201 CmsPublishedResource pubRes = new CmsPublishedResource(resource); 202 if (LOG.isDebugEnabled()) { 203 LOG.debug(Messages.get().getBundle().key(Messages.LOG_PROCESSING_1, resource.getRootPath())); 204 } 205 resources.add(pubRes); 206 } 207 208 if (LOG.isDebugEnabled()) { 209 LOG.debug(Messages.get().getBundle().key(Messages.LOG_NUM_RESOURCES_1, Integer.valueOf(resources.size()))); 210 } 211 return resources; 212 } 213 214 /** 215 * @see org.opencms.staticexport.I_CmsStaticExportHandler#performEventPublishProject(org.opencms.util.CmsUUID, org.opencms.report.I_CmsReport) 216 */ 217 @Override 218 public void performEventPublishProject(CmsUUID publishHistoryId, I_CmsReport report) { 219 220 try { 221 m_busy = true; 222 exportAfterPublish(publishHistoryId, report); 223 } catch (Throwable t) { 224 if (LOG.isErrorEnabled()) { 225 LOG.error(Messages.get().getBundle().key(Messages.LOG_STATIC_EXPORT_ERROR_0), t); 226 } 227 if (report != null) { 228 report.addError(t); 229 } 230 } finally { 231 m_busy = false; 232 } 233 } 234 235 /** 236 * Starts the static export on publish.<p> 237 * 238 * Exports all modified resources after a publish process into the real FS.<p> 239 * 240 * @param publishHistoryId the publichHistoryId of the published project 241 * @param report an <code>{@link I_CmsReport}</code> instance to print output message, or <code>null</code> to write messages to the log file 242 * 243 * @throws CmsException in case of errors accessing the VFS 244 * @throws IOException in case of errors writing to the export output stream 245 * @throws ServletException in case of errors accessing the servlet 246 */ 247 protected void exportAfterPublish(CmsUUID publishHistoryId, I_CmsReport report) 248 throws CmsException, IOException, ServletException { 249 250 // first check if the test resource was published already 251 // if not, we must do a complete export of all static resources 252 String rfsName = CmsFileUtil.normalizePath( 253 OpenCms.getStaticExportManager().getExportPath(OpenCms.getStaticExportManager().getTestResource()) 254 + OpenCms.getStaticExportManager().getTestResource()); 255 256 if (LOG.isDebugEnabled()) { 257 LOG.debug(Messages.get().getBundle().key(Messages.LOG_CHECKING_TEST_RESOURCE_1, rfsName)); 258 } 259 File file = new File(rfsName); 260 if (!file.exists()) { 261 if (LOG.isDebugEnabled()) { 262 LOG.debug(Messages.get().getBundle().key(Messages.LOG_TEST_RESOURCE_NOT_EXISTANT_0)); 263 } 264 // the file is not there, so export everything 265 OpenCms.getStaticExportManager().exportFullStaticRender(true, report); 266 } else { 267 if (LOG.isDebugEnabled()) { 268 LOG.debug(Messages.get().getBundle().key(Messages.LOG_TEST_RESOURCE_EXISTS_0)); 269 } 270 271 // delete all resources deleted during the publish process, and retrieve the list of resources to actually export 272 List<CmsPublishedResource> publishedResources = scrubExportFolders(publishHistoryId); 273 274 // do the export 275 doExportAfterPublish(publishedResources, report); 276 } 277 278 } 279 280 /** 281 * Exports all non template resources found in a list of published resources.<p> 282 * 283 * @param cms the current cms object 284 * @param publishedResources the list of published resources 285 * @param report an I_CmsReport instance to print output message, or null to write messages to the log file 286 * 287 * @return true if some template resources were found while looping the list of published resources 288 * 289 * @throws CmsException in case of errors accessing the VFS 290 * @throws IOException in case of errors writing to the export output stream 291 * @throws ServletException in case of errors accessing the servlet 292 */ 293 protected boolean exportNonTemplateResources( 294 CmsObject cms, 295 List<CmsPublishedResource> publishedResources, 296 I_CmsReport report) 297 throws CmsException, IOException, ServletException { 298 299 report.println( 300 Messages.get().container(Messages.RPT_STATICEXPORT_NONTEMPLATE_RESOURCES_BEGIN_0), 301 I_CmsReport.FORMAT_HEADLINE); 302 303 if (LOG.isDebugEnabled()) { 304 LOG.debug( 305 Messages.get().getBundle().key( 306 Messages.LOG_EXPORTING_NON_TEMPLATE_1, 307 Integer.valueOf(publishedResources.size()))); 308 } 309 310 CmsStaticExportManager manager = OpenCms.getStaticExportManager(); 311 List<CmsStaticExportData> resourcesToExport = new ArrayList<CmsStaticExportData>(); 312 boolean templatesFound = readNonTemplateResourcesToExport(cms, publishedResources, resourcesToExport); 313 314 int count = 1; 315 int size = resourcesToExport.size(); 316 if (LOG.isDebugEnabled()) { 317 LOG.debug(Messages.get().getBundle().key(Messages.LOG_NUM_EXPORT_1, Integer.valueOf(size))); 318 } 319 // now do the export 320 Iterator<CmsStaticExportData> i = resourcesToExport.iterator(); 321 while (i.hasNext()) { 322 CmsStaticExportData exportData = i.next(); 323 if (LOG.isDebugEnabled()) { 324 LOG.debug( 325 Messages.get().getBundle().key( 326 Messages.LOG_EXPORT_FILE_2, 327 exportData.getVfsName(), 328 exportData.getRfsName())); 329 } 330 331 report.print( 332 org.opencms.report.Messages.get().container( 333 org.opencms.report.Messages.RPT_SUCCESSION_2, 334 Integer.valueOf(count++), 335 Integer.valueOf(size)), 336 I_CmsReport.FORMAT_NOTE); 337 report.print(Messages.get().container(Messages.RPT_EXPORTING_0), I_CmsReport.FORMAT_NOTE); 338 report.print( 339 org.opencms.report.Messages.get().container( 340 org.opencms.report.Messages.RPT_ARGUMENT_1, 341 exportData.getVfsName())); 342 report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); 343 int status = -1; 344 try { 345 status = manager.export(null, null, cms, exportData); 346 if (status == HttpServletResponse.SC_OK) { 347 report.println( 348 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), 349 I_CmsReport.FORMAT_OK); 350 } else { 351 report.println( 352 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_IGNORED_0), 353 I_CmsReport.FORMAT_NOTE); 354 } 355 } catch (CmsStaticExportException e) { 356 LOG.warn(e.getLocalizedMessage(), e); 357 report.println( 358 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_IGNORED_0), 359 I_CmsReport.FORMAT_NOTE); 360 } 361 362 if (LOG.isInfoEnabled()) { 363 Object[] arguments = new Object[] { 364 exportData.getVfsName(), 365 exportData.getRfsName(), 366 Integer.valueOf(status)}; 367 LOG.info(Messages.get().getBundle().key(Messages.LOG_EXPORT_FILE_STATUS_3, arguments)); 368 } 369 //don't lock up the CPU exclusively - allow other Threads to run as well 370 Thread.yield(); 371 } 372 373 resourcesToExport = null; 374 375 report.println( 376 Messages.get().container(Messages.RPT_STATICEXPORT_NONTEMPLATE_RESOURCES_END_0), 377 I_CmsReport.FORMAT_HEADLINE); 378 379 return templatesFound; 380 } 381 382 /** 383 * Exports all sitemap resources found in a list of published resources.<p> 384 * 385 * @param entry the sitemap entry 386 * @param data the export data 387 * @param cookies cookies to keep the session 388 * 389 * @return the status of the http request used to perform the export 390 * 391 * @throws IOException if something goes wrong 392 */ 393 // protected int exportSitemapResource(CmsSitemapEntry entry, CmsStaticExportData data, StringBuffer cookies) 394 // throws IOException { 395 // 396 // String vfsName = data.getVfsName(); 397 // String rfsName = data.getRfsName(); 398 // CmsStaticExportManager manager = OpenCms.getStaticExportManager(); 399 // 400 // // check if the resource to export is a detail page 401 // // TODO: later when the property concept is finished this info is unnecessary 402 // String path = vfsName; 403 // boolean exportPropertyAlreadyReadFromVFS = false; 404 // if (path.endsWith("/")) { 405 // path = path.substring(0, path.length() - 1); 406 // String detailId = CmsResource.getName(path); 407 // if (CmsUUID.isValidUUID(detailId)) { 408 // exportPropertyAlreadyReadFromVFS = true; 409 // } 410 // } 411 // 412 // try { 413 // CmsObject exportCms = OpenCms.initCmsObject(OpenCms.getDefaultUsers().getUserExport()); 414 // Map<String, String> props = entry.getProperties(true); 415 // // if a container page was found in the vfs and 416 // if (((props.get("export") != null) && props.get("export").equals("true")) 417 // || exportPropertyAlreadyReadFromVFS) { 418 // // calculate rfs name 419 // rfsName = manager.getRfsName(exportCms, entry.getRootPath()); 420 // 421 // String exportUrlStr; 422 // if (rfsName.contains(manager.getRfsPrefix(vfsName))) { 423 // exportUrlStr = manager.getExportUrl() + rfsName; 424 // } else { 425 // exportUrlStr = manager.getExportUrl() + manager.getRfsPrefix(vfsName) + rfsName; 426 // } 427 // if (LOG.isDebugEnabled()) { 428 // LOG.debug(Messages.get().getBundle().key(Messages.LOG_SENDING_REQUEST_2, rfsName, exportUrlStr)); 429 // } 430 // // setup the connection and request the resource 431 // URL exportUrl = new URL(exportUrlStr); 432 // HttpURLConnection.setFollowRedirects(false); 433 // HttpURLConnection urlcon = (HttpURLConnection)exportUrl.openConnection(); 434 // // set request type to GET 435 // urlcon.setRequestMethod(REQUEST_METHOD_GET); 436 // // add special export header 437 // urlcon.setRequestProperty(CmsRequestUtil.HEADER_OPENCMS_EXPORT, CmsStringUtil.TRUE); 438 // // add additional headers if available 439 // if (manager.getAcceptLanguageHeader() != null) { 440 // urlcon.setRequestProperty(CmsRequestUtil.HEADER_ACCEPT_LANGUAGE, manager.getAcceptLanguageHeader()); 441 // } else { 442 // urlcon.setRequestProperty( 443 // CmsRequestUtil.HEADER_ACCEPT_LANGUAGE, 444 // manager.getDefaultAcceptLanguageHeader()); 445 // } 446 // if (manager.getAcceptCharsetHeader() != null) { 447 // urlcon.setRequestProperty(CmsRequestUtil.HEADER_ACCEPT_CHARSET, manager.getAcceptCharsetHeader()); 448 // } else { 449 // urlcon.setRequestProperty( 450 // CmsRequestUtil.HEADER_ACCEPT_CHARSET, 451 // manager.getDefaultAcceptCharsetHeader()); 452 // } 453 // 454 // // get the last modified date and add it to the request 455 // String exportFileName = CmsFileUtil.normalizePath(manager.getExportPath(vfsName) + rfsName); 456 // File exportFile = new File(exportFileName); 457 // long dateLastModified = exportFile.lastModified(); 458 // // system folder case 459 // if (vfsName.startsWith(CmsWorkplace.VFS_PATH_SYSTEM)) { 460 // // iterate over all rules 461 // for (CmsStaticExportRfsRule rule : manager.getRfsRules()) { 462 // if (rule.match(vfsName)) { 463 // exportFileName = CmsFileUtil.normalizePath(rule.getExportPath() + rfsName); 464 // exportFile = new File(exportFileName); 465 // if (dateLastModified > exportFile.lastModified()) { 466 // dateLastModified = exportFile.lastModified(); 467 // } 468 // } 469 // } 470 // } 471 // urlcon.setIfModifiedSince(dateLastModified); 472 // if (LOG.isDebugEnabled()) { 473 // LOG.debug(Messages.get().getBundle().key( 474 // Messages.LOG_IF_MODIFIED_SINCE_SET_2, 475 // exportFile.getName(), 476 // Long.valueOf((dateLastModified / 1000) * 1000))); 477 // } 478 // if (cookies.length() > 0) { 479 // // set the cookies, included the session id to keep the same session 480 // urlcon.setRequestProperty(REQUEST_PROPERTY_COOKIE, cookies.toString()); 481 // } 482 // 483 // // now perform the request 484 // urlcon.connect(); 485 // int status = urlcon.getResponseCode(); 486 // 487 // if (cookies.length() == 0) { 488 // //Now retrieve the cookies. The jsessionid is here 489 // cookies.append(urlcon.getHeaderField(HEADER_FIELD_SET_COOKIE)); 490 // if (LOG.isDebugEnabled()) { 491 // LOG.debug(Messages.get().getBundle().key(Messages.LOG_STATICEXPORT_COOKIES_1, cookies)); 492 // } 493 // } 494 // urlcon.disconnect(); 495 // if (LOG.isInfoEnabled()) { 496 // LOG.info(Messages.get().getBundle().key( 497 // Messages.LOG_REQUEST_RESULT_3, 498 // rfsName, 499 // exportUrlStr, 500 // Integer.valueOf(status))); 501 // } 502 // return status; 503 // } 504 // } catch (CmsException e) { 505 // LOG.error(e.getLocalizedMessage(), e); 506 // } 507 // return HttpServletResponse.SC_SEE_OTHER; 508 // } 509 510 /** 511 * Exports a single (template) resource specified by its export data.<p> 512 * 513 * @param data the export data 514 * @param cookies cookies to keep the session 515 * 516 * @return the status of the http request used to perform the export 517 * 518 * @throws IOException if the http request fails 519 */ 520 protected int exportTemplateResource(CmsStaticExportData data, StringBuffer cookies) throws IOException { 521 522 String vfsName = data.getVfsName(); 523 String rfsName = data.getRfsName(); 524 CmsStaticExportManager manager = OpenCms.getStaticExportManager(); 525 526 String exportUrlStr; 527 if (rfsName.contains(manager.getRfsPrefix(vfsName))) { 528 LOG.info("rfsName " + rfsName + " contains rfsPrefix " + manager.getRfsPrefix(vfsName)); 529 exportUrlStr = manager.getExportUrl() + rfsName; 530 } else { 531 exportUrlStr = manager.getExportUrl() + manager.getRfsPrefix(vfsName) + rfsName; 532 } 533 if (LOG.isDebugEnabled()) { 534 LOG.debug(Messages.get().getBundle().key(Messages.LOG_SENDING_REQUEST_2, rfsName, exportUrlStr)); 535 } 536 // setup the connection and request the resource 537 URL exportUrl = new URL(exportUrlStr); 538 HttpURLConnection.setFollowRedirects(false); 539 HttpURLConnection urlcon = (HttpURLConnection)exportUrl.openConnection(); 540 // set request type to GET 541 urlcon.setRequestMethod(REQUEST_METHOD_GET); 542 // add special export header 543 urlcon.setRequestProperty(CmsRequestUtil.HEADER_OPENCMS_EXPORT, CmsStringUtil.TRUE); 544 // add additional headers if available 545 if (manager.getAcceptLanguageHeader() != null) { 546 urlcon.setRequestProperty(CmsRequestUtil.HEADER_ACCEPT_LANGUAGE, manager.getAcceptLanguageHeader()); 547 } else { 548 urlcon.setRequestProperty(CmsRequestUtil.HEADER_ACCEPT_LANGUAGE, manager.getDefaultAcceptLanguageHeader()); 549 } 550 if (manager.getAcceptCharsetHeader() != null) { 551 urlcon.setRequestProperty(CmsRequestUtil.HEADER_ACCEPT_CHARSET, manager.getAcceptCharsetHeader()); 552 } else { 553 urlcon.setRequestProperty(CmsRequestUtil.HEADER_ACCEPT_CHARSET, manager.getDefaultAcceptCharsetHeader()); 554 } 555 556 // get the last modified date and add it to the request 557 String exportFileName = CmsFileUtil.normalizePath(manager.getExportPath(vfsName) + rfsName); 558 File exportFile = new File(exportFileName); 559 long dateLastModified = exportFile.lastModified(); 560 // system folder case 561 if (vfsName.startsWith(CmsWorkplace.VFS_PATH_SYSTEM) || OpenCms.getSiteManager().startsWithShared(vfsName)) { 562 // iterate over all rules 563 Iterator<CmsStaticExportRfsRule> it = manager.getRfsRules().iterator(); 564 while (it.hasNext()) { 565 CmsStaticExportRfsRule rule = it.next(); 566 if (rule.match(vfsName)) { 567 exportFileName = CmsFileUtil.normalizePath(rule.getExportPath() + rfsName); 568 exportFile = new File(exportFileName); 569 if (dateLastModified > exportFile.lastModified()) { 570 dateLastModified = exportFile.lastModified(); 571 } 572 } 573 } 574 } 575 urlcon.setIfModifiedSince(dateLastModified); 576 if (LOG.isDebugEnabled()) { 577 LOG.debug( 578 Messages.get().getBundle().key( 579 Messages.LOG_IF_MODIFIED_SINCE_SET_2, 580 exportFile.getName(), 581 Long.valueOf((dateLastModified / 1000) * 1000))); 582 } 583 if (cookies.length() > 0) { 584 // set the cookies, included the session id to keep the same session 585 urlcon.setRequestProperty(REQUEST_PROPERTY_COOKIE, cookies.toString()); 586 } 587 588 // now perform the request 589 urlcon.connect(); 590 int status = urlcon.getResponseCode(); 591 592 if (cookies.length() == 0) { 593 //Now retrieve the cookies. The jsessionid is here 594 cookies.append(urlcon.getHeaderField(HEADER_FIELD_SET_COOKIE)); 595 if (LOG.isDebugEnabled()) { 596 LOG.debug(Messages.get().getBundle().key(Messages.LOG_STATICEXPORT_COOKIES_1, cookies)); 597 } 598 } 599 urlcon.disconnect(); 600 if (LOG.isInfoEnabled()) { 601 LOG.info( 602 Messages.get().getBundle().key( 603 Messages.LOG_REQUEST_RESULT_3, 604 rfsName, 605 exportUrlStr, 606 Integer.valueOf(status))); 607 } 608 return status; 609 } 610 611 /** 612 * Exports all template resources found in a list of published resources.<p> 613 * 614 * @param cms the cms context, in the root site as Export user 615 * @param publishedTemplateResources list of potential candidates to export 616 * @param report an I_CmsReport instance to print output message, or null to write messages to the log file 617 */ 618 protected void exportTemplateResources(CmsObject cms, List<String> publishedTemplateResources, I_CmsReport report) { 619 620 CmsStaticExportManager manager = OpenCms.getStaticExportManager(); 621 int size = publishedTemplateResources.size(); 622 int count = 1; 623 624 if (LOG.isDebugEnabled()) { 625 LOG.debug(Messages.get().getBundle().key(Messages.LOG_EXPORT_TEMPLATES_1, Integer.valueOf(size))); 626 } 627 report.println( 628 Messages.get().container(Messages.RPT_STATICEXPORT_TEMPLATE_RESOURCES_BEGIN_0), 629 I_CmsReport.FORMAT_HEADLINE); 630 631 StringBuffer cookies = new StringBuffer(); 632 // now loop through all of them and request them from the server 633 Iterator<String> i = publishedTemplateResources.iterator(); 634 while (i.hasNext()) { 635 String rfsName = i.next(); 636 CmsStaticExportData data = null; 637 try { 638 data = manager.getVfsNameInternal(cms, rfsName); 639 } catch (CmsVfsResourceNotFoundException e) { 640 String rfsBaseName = rfsName; 641 int pos = rfsName.lastIndexOf('_'); 642 if (pos >= 0) { 643 rfsBaseName = rfsName.substring(0, pos); 644 } 645 try { 646 data = manager.getVfsNameInternal(cms, rfsBaseName); 647 } catch (CmsVfsResourceNotFoundException e2) { 648 if (LOG.isInfoEnabled()) { 649 LOG.info( 650 Messages.get().getBundle().key( 651 Messages.LOG_NO_INTERNAL_VFS_RESOURCE_FOUND_1, 652 new String[] {rfsName})); 653 } 654 } 655 } 656 if (data != null) { 657 data.setRfsName(rfsName); 658 report.print( 659 org.opencms.report.Messages.get().container( 660 org.opencms.report.Messages.RPT_SUCCESSION_2, 661 Integer.valueOf(count++), 662 Integer.valueOf(size)), 663 I_CmsReport.FORMAT_NOTE); 664 report.print(Messages.get().container(Messages.RPT_EXPORTING_0), I_CmsReport.FORMAT_NOTE); 665 report.print( 666 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_ARGUMENT_1, rfsName)); 667 report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); 668 } else { 669 // no valid resource found for rfs name (already deleted), skip it 670 continue; 671 } 672 673 try { 674 CmsResource resource = data.getResource(); 675 try { 676 Collection<String> detailPages = CmsDetailPageUtil.getAllDetailPagesWithUrlName(cms, resource); 677 for (String detailPageUri : detailPages) { 678 String altRfsName = manager.getRfsName(cms, detailPageUri); 679 CmsStaticExportData detailData = new CmsStaticExportData( 680 data.getVfsName(), 681 altRfsName, 682 data.getResource(), 683 data.getParameters()); 684 exportTemplateResource(detailData, cookies); 685 } 686 } catch (CmsException e) { 687 LOG.error(e.getLocalizedMessage(), e); 688 } 689 690 int status = exportTemplateResource(data, cookies); 691 692 // write the report 693 if (status == HttpServletResponse.SC_OK) { 694 report.println( 695 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), 696 I_CmsReport.FORMAT_OK); 697 } else if (status == HttpServletResponse.SC_NOT_MODIFIED) { 698 report.println( 699 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_SKIPPED_0), 700 I_CmsReport.FORMAT_NOTE); 701 } else if (status == HttpServletResponse.SC_SEE_OTHER) { 702 report.println( 703 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_IGNORED_0), 704 I_CmsReport.FORMAT_NOTE); 705 } else { 706 report.println( 707 org.opencms.report.Messages.get().container( 708 org.opencms.report.Messages.RPT_ARGUMENT_1, 709 Integer.valueOf(status)), 710 I_CmsReport.FORMAT_OK); 711 } 712 } catch (IOException e) { 713 report.println(e); 714 } 715 //don't lock up the CPU exclusively - allow other Threads to run as well 716 Thread.yield(); 717 } 718 report.println( 719 Messages.get().container(Messages.RPT_STATICEXPORT_TEMPLATE_RESOURCES_END_0), 720 I_CmsReport.FORMAT_HEADLINE); 721 } 722 723 /** 724 * @see org.opencms.staticexport.A_CmsStaticExportHandler#getRelatedFilesToPurge(java.lang.String, java.lang.String) 725 */ 726 @Override 727 protected List<File> getRelatedFilesToPurge(String exportFileName, String vfsName) { 728 729 return Collections.emptyList(); 730 } 731 732 /** 733 * Creates a list of <code>{@link org.opencms.db.CmsPublishedResource}</code> objects containing all related resources of the VFS tree.<p> 734 * 735 * If the static export has been triggered by the OpenCms workplace, publishedResources is null and all resources in the VFS tree are returned.<p> 736 * If really an after publish static export is triggered, then only the related resources are returned.<p> 737 * 738 * @param cms the current cms object 739 * @param publishedResources the list of published resources 740 * 741 * @return list of CmsPulishedResource objects containing all resources of the VFS tree 742 * 743 * @throws CmsException in case of errors accessing the VFS 744 */ 745 protected List<CmsPublishedResource> getRelatedResources( 746 CmsObject cms, 747 List<CmsPublishedResource> publishedResources) 748 throws CmsException { 749 750 String storedSiteRoot = cms.getRequestContext().getSiteRoot(); 751 try { 752 // switch to root site 753 cms.getRequestContext().setSiteRoot("/"); 754 if (publishedResources == null) { 755 // full static export 756 return getAllResources(cms); 757 } else { 758 // after publish export 759 Map<String, CmsPublishedResource> resourceMap = new HashMap<String, CmsPublishedResource>(); 760 Iterator<CmsPublishedResource> itPubRes = publishedResources.iterator(); 761 while (itPubRes.hasNext()) { 762 CmsPublishedResource pubResource = itPubRes.next(); 763 // check the internal flag if the resource does still exist 764 // we cannot export with an internal flag 765 if (cms.existsResource(pubResource.getRootPath())) { 766 CmsResource vfsResource = cms.readResource(pubResource.getRootPath()); 767 if (!vfsResource.isInternal()) { 768 // add only if not internal 769 // additionally, add all siblings of the resource 770 Iterator<CmsPublishedResource> itSiblings = getSiblings(cms, pubResource).iterator(); 771 while (itSiblings.hasNext()) { 772 CmsPublishedResource sibling = itSiblings.next(); 773 resourceMap.put(sibling.getRootPath(), sibling); 774 } 775 } 776 } else { 777 // the resource does not exist, so add them for deletion in the static export 778 resourceMap.put(pubResource.getRootPath(), pubResource); 779 } 780 781 boolean match = false; 782 Iterator<CmsStaticExportExportRule> itExportRules = OpenCms.getStaticExportManager().getExportRules().iterator(); 783 while (itExportRules.hasNext()) { 784 CmsStaticExportExportRule rule = itExportRules.next(); 785 Set<CmsPublishedResource> relatedResources = rule.getRelatedResources(cms, pubResource); 786 if (relatedResources != null) { 787 Iterator<CmsPublishedResource> itRelatedRes = relatedResources.iterator(); 788 while (itRelatedRes.hasNext()) { 789 CmsPublishedResource relatedRes = itRelatedRes.next(); 790 resourceMap.put(relatedRes.getRootPath(), relatedRes); 791 } 792 match = true; 793 } 794 } 795 // if one res does not match any rule, then export all files 796 if (!match) { 797 return getAllResources(cms); 798 } 799 } 800 return new ArrayList<CmsPublishedResource>(resourceMap.values()); 801 } 802 } finally { 803 cms.getRequestContext().setSiteRoot(storedSiteRoot); 804 } 805 } 806 807 /** 808 * Returns all siblings of the published resource as list of <code>CmsPublishedResource</code>.<p> 809 * 810 * @param cms the cms object 811 * @param pubResource the published resource 812 * 813 * @return all siblings of the published resource 814 * 815 * @throws CmsException if something goes wrong 816 */ 817 protected Set<CmsPublishedResource> getSiblings(CmsObject cms, CmsPublishedResource pubResource) 818 throws CmsException { 819 820 Set<CmsPublishedResource> siblings = new HashSet<CmsPublishedResource>(); 821 for (Iterator<String> i = getSiblingsList(cms, pubResource.getRootPath()).iterator(); i.hasNext();) { 822 String sibling = i.next(); 823 siblings.add(new CmsPublishedResource(cms.readResource(sibling))); 824 } 825 return siblings; 826 } 827 828 /** 829 * Returns all non template resources found in a list of published resources.<p> 830 * 831 * @param cms the current cms object 832 * @param publishedResources the list of published resources 833 * @param resourcesToExport the list of non-template resources 834 * 835 * @return <code>true</code> if some template resources were found while looping the list of published resources 836 * 837 * @throws CmsException in case of errors accessing the VFS 838 */ 839 protected boolean readNonTemplateResourcesToExport( 840 CmsObject cms, 841 List<CmsPublishedResource> publishedResources, 842 List<CmsStaticExportData> resourcesToExport) 843 throws CmsException { 844 845 CmsStaticExportManager manager = OpenCms.getStaticExportManager(); 846 boolean templatesFound = false; 847 // loop through all resources 848 Iterator<CmsPublishedResource> i = publishedResources.iterator(); 849 while (i.hasNext()) { 850 CmsPublishedResource pubRes = i.next(); 851 String vfsName = pubRes.getRootPath(); 852 // only process this resource, if it is within the tree of allowed folders for static export 853 if (manager.getExportFolderMatcher().match(vfsName)) { 854 // get the export data object, if null is returned, this resource cannot be exported 855 CmsStaticExportData exportData = manager.getVfsExportData(cms, vfsName); 856 if (exportData != null) { 857 CmsResource resource = null; 858 if (pubRes.isFile()) { 859 resource = exportData.getResource(); 860 } else { 861 // the resource is a folder, check if PROPERTY_DEFAULT_FILE is set on folder 862 try { 863 resource = cms.readDefaultFile(vfsName); 864 // String defaultFileName = cms.readPropertyObject( 865 // vfsName, 866 // CmsPropertyDefinition.PROPERTY_DEFAULT_FILE, 867 // false).getValue(); 868 // if (defaultFileName != null) { 869 // resource = cms.readResource(vfsName + defaultFileName); 870 // } 871 } catch (CmsException e) { 872 // resource is (still) a folder, check default files specified in configuration 873 for (int j = 0; j < OpenCms.getDefaultFiles().size(); j++) { 874 String tmpResourceName = vfsName + OpenCms.getDefaultFiles().get(j); 875 try { 876 resource = cms.readResource(tmpResourceName); 877 break; 878 } catch (CmsException e1) { 879 // ignore all other exceptions and continue the lookup process 880 } 881 } 882 } 883 } 884 if ((resource != null) && resource.isFile()) { 885 // check loader for current resource if it must be processed before exported 886 I_CmsResourceLoader loader = OpenCms.getResourceManager().getLoader(resource); 887 if (!loader.isStaticExportProcessable()) { 888 // this resource must not be processed, so export it (if it's not marked as deleted) 889 if (!pubRes.getState().isDeleted()) { 890 // mark the resource for export to the real file system 891 resourcesToExport.add(exportData); 892 } 893 } else { 894 // the resource is a template resource or a folder, so store the name of it in the DB for further use 895 templatesFound = true; 896 cms.writeStaticExportPublishedResource( 897 exportData.getRfsName(), 898 CmsStaticExportManager.EXPORT_LINK_WITHOUT_PARAMETER, 899 "", 900 System.currentTimeMillis()); 901 } 902 } 903 } 904 } 905 } 906 907 return templatesFound; 908 } 909}