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, new Integer(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 new Integer(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, new Integer(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 new Integer(count++), 335 new Integer(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 = manager.export(null, null, cms, exportData); 344 if (status == HttpServletResponse.SC_OK) { 345 report.println( 346 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), 347 I_CmsReport.FORMAT_OK); 348 } else { 349 report.println( 350 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_IGNORED_0), 351 I_CmsReport.FORMAT_NOTE); 352 } 353 354 if (LOG.isInfoEnabled()) { 355 Object[] arguments = new Object[] { 356 exportData.getVfsName(), 357 exportData.getRfsName(), 358 new Integer(status)}; 359 LOG.info(Messages.get().getBundle().key(Messages.LOG_EXPORT_FILE_STATUS_3, arguments)); 360 } 361 //don't lock up the CPU exclusively - allow other Threads to run as well 362 Thread.yield(); 363 } 364 365 resourcesToExport = null; 366 367 report.println( 368 Messages.get().container(Messages.RPT_STATICEXPORT_NONTEMPLATE_RESOURCES_END_0), 369 I_CmsReport.FORMAT_HEADLINE); 370 371 return templatesFound; 372 } 373 374 /** 375 * Exports all sitemap resources found in a list of published resources.<p> 376 * 377 * @param entry the sitemap entry 378 * @param data the export data 379 * @param cookies cookies to keep the session 380 * 381 * @return the status of the http request used to perform the export 382 * 383 * @throws IOException if something goes wrong 384 */ 385 // protected int exportSitemapResource(CmsSitemapEntry entry, CmsStaticExportData data, StringBuffer cookies) 386 // throws IOException { 387 // 388 // String vfsName = data.getVfsName(); 389 // String rfsName = data.getRfsName(); 390 // CmsStaticExportManager manager = OpenCms.getStaticExportManager(); 391 // 392 // // check if the resource to export is a detail page 393 // // TODO: later when the property concept is finished this info is unnecessary 394 // String path = vfsName; 395 // boolean exportPropertyAlreadyReadFromVFS = false; 396 // if (path.endsWith("/")) { 397 // path = path.substring(0, path.length() - 1); 398 // String detailId = CmsResource.getName(path); 399 // if (CmsUUID.isValidUUID(detailId)) { 400 // exportPropertyAlreadyReadFromVFS = true; 401 // } 402 // } 403 // 404 // try { 405 // CmsObject exportCms = OpenCms.initCmsObject(OpenCms.getDefaultUsers().getUserExport()); 406 // Map<String, String> props = entry.getProperties(true); 407 // // if a container page was found in the vfs and 408 // if (((props.get("export") != null) && props.get("export").equals("true")) 409 // || exportPropertyAlreadyReadFromVFS) { 410 // // calculate rfs name 411 // rfsName = manager.getRfsName(exportCms, entry.getRootPath()); 412 // 413 // String exportUrlStr; 414 // if (rfsName.contains(manager.getRfsPrefix(vfsName))) { 415 // exportUrlStr = manager.getExportUrl() + rfsName; 416 // } else { 417 // exportUrlStr = manager.getExportUrl() + manager.getRfsPrefix(vfsName) + rfsName; 418 // } 419 // if (LOG.isDebugEnabled()) { 420 // LOG.debug(Messages.get().getBundle().key(Messages.LOG_SENDING_REQUEST_2, rfsName, exportUrlStr)); 421 // } 422 // // setup the connection and request the resource 423 // URL exportUrl = new URL(exportUrlStr); 424 // HttpURLConnection.setFollowRedirects(false); 425 // HttpURLConnection urlcon = (HttpURLConnection)exportUrl.openConnection(); 426 // // set request type to GET 427 // urlcon.setRequestMethod(REQUEST_METHOD_GET); 428 // // add special export header 429 // urlcon.setRequestProperty(CmsRequestUtil.HEADER_OPENCMS_EXPORT, CmsStringUtil.TRUE); 430 // // add additional headers if available 431 // if (manager.getAcceptLanguageHeader() != null) { 432 // urlcon.setRequestProperty(CmsRequestUtil.HEADER_ACCEPT_LANGUAGE, manager.getAcceptLanguageHeader()); 433 // } else { 434 // urlcon.setRequestProperty( 435 // CmsRequestUtil.HEADER_ACCEPT_LANGUAGE, 436 // manager.getDefaultAcceptLanguageHeader()); 437 // } 438 // if (manager.getAcceptCharsetHeader() != null) { 439 // urlcon.setRequestProperty(CmsRequestUtil.HEADER_ACCEPT_CHARSET, manager.getAcceptCharsetHeader()); 440 // } else { 441 // urlcon.setRequestProperty( 442 // CmsRequestUtil.HEADER_ACCEPT_CHARSET, 443 // manager.getDefaultAcceptCharsetHeader()); 444 // } 445 // 446 // // get the last modified date and add it to the request 447 // String exportFileName = CmsFileUtil.normalizePath(manager.getExportPath(vfsName) + rfsName); 448 // File exportFile = new File(exportFileName); 449 // long dateLastModified = exportFile.lastModified(); 450 // // system folder case 451 // if (vfsName.startsWith(CmsWorkplace.VFS_PATH_SYSTEM)) { 452 // // iterate over all rules 453 // for (CmsStaticExportRfsRule rule : manager.getRfsRules()) { 454 // if (rule.match(vfsName)) { 455 // exportFileName = CmsFileUtil.normalizePath(rule.getExportPath() + rfsName); 456 // exportFile = new File(exportFileName); 457 // if (dateLastModified > exportFile.lastModified()) { 458 // dateLastModified = exportFile.lastModified(); 459 // } 460 // } 461 // } 462 // } 463 // urlcon.setIfModifiedSince(dateLastModified); 464 // if (LOG.isDebugEnabled()) { 465 // LOG.debug(Messages.get().getBundle().key( 466 // Messages.LOG_IF_MODIFIED_SINCE_SET_2, 467 // exportFile.getName(), 468 // new Long((dateLastModified / 1000) * 1000))); 469 // } 470 // if (cookies.length() > 0) { 471 // // set the cookies, included the session id to keep the same session 472 // urlcon.setRequestProperty(REQUEST_PROPERTY_COOKIE, cookies.toString()); 473 // } 474 // 475 // // now perform the request 476 // urlcon.connect(); 477 // int status = urlcon.getResponseCode(); 478 // 479 // if (cookies.length() == 0) { 480 // //Now retrieve the cookies. The jsessionid is here 481 // cookies.append(urlcon.getHeaderField(HEADER_FIELD_SET_COOKIE)); 482 // if (LOG.isDebugEnabled()) { 483 // LOG.debug(Messages.get().getBundle().key(Messages.LOG_STATICEXPORT_COOKIES_1, cookies)); 484 // } 485 // } 486 // urlcon.disconnect(); 487 // if (LOG.isInfoEnabled()) { 488 // LOG.info(Messages.get().getBundle().key( 489 // Messages.LOG_REQUEST_RESULT_3, 490 // rfsName, 491 // exportUrlStr, 492 // new Integer(status))); 493 // } 494 // return status; 495 // } 496 // } catch (CmsException e) { 497 // LOG.error(e.getLocalizedMessage(), e); 498 // } 499 // return HttpServletResponse.SC_SEE_OTHER; 500 // } 501 502 /** 503 * Exports a single (template) resource specified by its export data.<p> 504 * 505 * @param data the export data 506 * @param cookies cookies to keep the session 507 * 508 * @return the status of the http request used to perform the export 509 * 510 * @throws IOException if the http request fails 511 */ 512 protected int exportTemplateResource(CmsStaticExportData data, StringBuffer cookies) throws IOException { 513 514 String vfsName = data.getVfsName(); 515 String rfsName = data.getRfsName(); 516 CmsStaticExportManager manager = OpenCms.getStaticExportManager(); 517 518 String exportUrlStr; 519 if (rfsName.contains(manager.getRfsPrefix(vfsName))) { 520 LOG.info("rfsName " + rfsName + " contains rfsPrefix " + manager.getRfsPrefix(vfsName)); 521 exportUrlStr = manager.getExportUrl() + rfsName; 522 } else { 523 exportUrlStr = manager.getExportUrl() + manager.getRfsPrefix(vfsName) + rfsName; 524 } 525 if (LOG.isDebugEnabled()) { 526 LOG.debug(Messages.get().getBundle().key(Messages.LOG_SENDING_REQUEST_2, rfsName, exportUrlStr)); 527 } 528 // setup the connection and request the resource 529 URL exportUrl = new URL(exportUrlStr); 530 HttpURLConnection.setFollowRedirects(false); 531 HttpURLConnection urlcon = (HttpURLConnection)exportUrl.openConnection(); 532 // set request type to GET 533 urlcon.setRequestMethod(REQUEST_METHOD_GET); 534 // add special export header 535 urlcon.setRequestProperty(CmsRequestUtil.HEADER_OPENCMS_EXPORT, CmsStringUtil.TRUE); 536 // add additional headers if available 537 if (manager.getAcceptLanguageHeader() != null) { 538 urlcon.setRequestProperty(CmsRequestUtil.HEADER_ACCEPT_LANGUAGE, manager.getAcceptLanguageHeader()); 539 } else { 540 urlcon.setRequestProperty(CmsRequestUtil.HEADER_ACCEPT_LANGUAGE, manager.getDefaultAcceptLanguageHeader()); 541 } 542 if (manager.getAcceptCharsetHeader() != null) { 543 urlcon.setRequestProperty(CmsRequestUtil.HEADER_ACCEPT_CHARSET, manager.getAcceptCharsetHeader()); 544 } else { 545 urlcon.setRequestProperty(CmsRequestUtil.HEADER_ACCEPT_CHARSET, manager.getDefaultAcceptCharsetHeader()); 546 } 547 548 // get the last modified date and add it to the request 549 String exportFileName = CmsFileUtil.normalizePath(manager.getExportPath(vfsName) + rfsName); 550 File exportFile = new File(exportFileName); 551 long dateLastModified = exportFile.lastModified(); 552 // system folder case 553 if (vfsName.startsWith(CmsWorkplace.VFS_PATH_SYSTEM) || OpenCms.getSiteManager().startsWithShared(vfsName)) { 554 // iterate over all rules 555 Iterator<CmsStaticExportRfsRule> it = manager.getRfsRules().iterator(); 556 while (it.hasNext()) { 557 CmsStaticExportRfsRule rule = it.next(); 558 if (rule.match(vfsName)) { 559 exportFileName = CmsFileUtil.normalizePath(rule.getExportPath() + rfsName); 560 exportFile = new File(exportFileName); 561 if (dateLastModified > exportFile.lastModified()) { 562 dateLastModified = exportFile.lastModified(); 563 } 564 } 565 } 566 } 567 urlcon.setIfModifiedSince(dateLastModified); 568 if (LOG.isDebugEnabled()) { 569 LOG.debug( 570 Messages.get().getBundle().key( 571 Messages.LOG_IF_MODIFIED_SINCE_SET_2, 572 exportFile.getName(), 573 new Long((dateLastModified / 1000) * 1000))); 574 } 575 if (cookies.length() > 0) { 576 // set the cookies, included the session id to keep the same session 577 urlcon.setRequestProperty(REQUEST_PROPERTY_COOKIE, cookies.toString()); 578 } 579 580 // now perform the request 581 urlcon.connect(); 582 int status = urlcon.getResponseCode(); 583 584 if (cookies.length() == 0) { 585 //Now retrieve the cookies. The jsessionid is here 586 cookies.append(urlcon.getHeaderField(HEADER_FIELD_SET_COOKIE)); 587 if (LOG.isDebugEnabled()) { 588 LOG.debug(Messages.get().getBundle().key(Messages.LOG_STATICEXPORT_COOKIES_1, cookies)); 589 } 590 } 591 urlcon.disconnect(); 592 if (LOG.isInfoEnabled()) { 593 LOG.info( 594 Messages.get().getBundle().key( 595 Messages.LOG_REQUEST_RESULT_3, 596 rfsName, 597 exportUrlStr, 598 new Integer(status))); 599 } 600 return status; 601 } 602 603 /** 604 * Exports all template resources found in a list of published resources.<p> 605 * 606 * @param cms the cms context, in the root site as Export user 607 * @param publishedTemplateResources list of potential candidates to export 608 * @param report an I_CmsReport instance to print output message, or null to write messages to the log file 609 */ 610 protected void exportTemplateResources(CmsObject cms, List<String> publishedTemplateResources, I_CmsReport report) { 611 612 CmsStaticExportManager manager = OpenCms.getStaticExportManager(); 613 int size = publishedTemplateResources.size(); 614 int count = 1; 615 616 if (LOG.isDebugEnabled()) { 617 LOG.debug(Messages.get().getBundle().key(Messages.LOG_EXPORT_TEMPLATES_1, new Integer(size))); 618 } 619 report.println( 620 Messages.get().container(Messages.RPT_STATICEXPORT_TEMPLATE_RESOURCES_BEGIN_0), 621 I_CmsReport.FORMAT_HEADLINE); 622 623 StringBuffer cookies = new StringBuffer(); 624 // now loop through all of them and request them from the server 625 Iterator<String> i = publishedTemplateResources.iterator(); 626 while (i.hasNext()) { 627 String rfsName = i.next(); 628 CmsStaticExportData data = null; 629 try { 630 data = manager.getVfsNameInternal(cms, rfsName); 631 } catch (CmsVfsResourceNotFoundException e) { 632 String rfsBaseName = rfsName; 633 int pos = rfsName.lastIndexOf('_'); 634 if (pos >= 0) { 635 rfsBaseName = rfsName.substring(0, pos); 636 } 637 try { 638 data = manager.getVfsNameInternal(cms, rfsBaseName); 639 } catch (CmsVfsResourceNotFoundException e2) { 640 if (LOG.isInfoEnabled()) { 641 LOG.info( 642 Messages.get().getBundle().key( 643 Messages.LOG_NO_INTERNAL_VFS_RESOURCE_FOUND_1, 644 new String[] {rfsName})); 645 } 646 } 647 } 648 if (data != null) { 649 data.setRfsName(rfsName); 650 report.print( 651 org.opencms.report.Messages.get().container( 652 org.opencms.report.Messages.RPT_SUCCESSION_2, 653 new Integer(count++), 654 new Integer(size)), 655 I_CmsReport.FORMAT_NOTE); 656 report.print(Messages.get().container(Messages.RPT_EXPORTING_0), I_CmsReport.FORMAT_NOTE); 657 report.print( 658 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_ARGUMENT_1, rfsName)); 659 report.print(org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0)); 660 } else { 661 // no valid resource found for rfs name (already deleted), skip it 662 continue; 663 } 664 665 try { 666 CmsResource resource = data.getResource(); 667 try { 668 Collection<String> detailPages = CmsDetailPageUtil.getAllDetailPagesWithUrlName(cms, resource); 669 for (String detailPageUri : detailPages) { 670 String altRfsName = manager.getRfsName(cms, detailPageUri); 671 CmsStaticExportData detailData = new CmsStaticExportData( 672 data.getVfsName(), 673 altRfsName, 674 data.getResource(), 675 data.getParameters()); 676 exportTemplateResource(detailData, cookies); 677 } 678 } catch (CmsException e) { 679 LOG.error(e.getLocalizedMessage(), e); 680 } 681 682 int status = exportTemplateResource(data, cookies); 683 684 // write the report 685 if (status == HttpServletResponse.SC_OK) { 686 report.println( 687 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), 688 I_CmsReport.FORMAT_OK); 689 } else if (status == HttpServletResponse.SC_NOT_MODIFIED) { 690 report.println( 691 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_SKIPPED_0), 692 I_CmsReport.FORMAT_NOTE); 693 } else if (status == HttpServletResponse.SC_SEE_OTHER) { 694 report.println( 695 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_IGNORED_0), 696 I_CmsReport.FORMAT_NOTE); 697 } else { 698 report.println( 699 org.opencms.report.Messages.get().container( 700 org.opencms.report.Messages.RPT_ARGUMENT_1, 701 new Integer(status)), 702 I_CmsReport.FORMAT_OK); 703 } 704 } catch (IOException e) { 705 report.println(e); 706 } 707 //don't lock up the CPU exclusively - allow other Threads to run as well 708 Thread.yield(); 709 } 710 report.println( 711 Messages.get().container(Messages.RPT_STATICEXPORT_TEMPLATE_RESOURCES_END_0), 712 I_CmsReport.FORMAT_HEADLINE); 713 } 714 715 /** 716 * @see org.opencms.staticexport.A_CmsStaticExportHandler#getRelatedFilesToPurge(java.lang.String, java.lang.String) 717 */ 718 @Override 719 protected List<File> getRelatedFilesToPurge(String exportFileName, String vfsName) { 720 721 return Collections.emptyList(); 722 } 723 724 /** 725 * Creates a list of <code>{@link org.opencms.db.CmsPublishedResource}</code> objects containing all related resources of the VFS tree.<p> 726 * 727 * If the static export has been triggered by the OpenCms workplace, publishedResources is null and all resources in the VFS tree are returned.<p> 728 * If really an after publish static export is triggered, then only the related resources are returned.<p> 729 * 730 * @param cms the current cms object 731 * @param publishedResources the list of published resources 732 * 733 * @return list of CmsPulishedResource objects containing all resources of the VFS tree 734 * 735 * @throws CmsException in case of errors accessing the VFS 736 */ 737 protected List<CmsPublishedResource> getRelatedResources( 738 CmsObject cms, 739 List<CmsPublishedResource> publishedResources) 740 throws CmsException { 741 742 String storedSiteRoot = cms.getRequestContext().getSiteRoot(); 743 try { 744 // switch to root site 745 cms.getRequestContext().setSiteRoot("/"); 746 if (publishedResources == null) { 747 // full static export 748 return getAllResources(cms); 749 } else { 750 // after publish export 751 Map<String, CmsPublishedResource> resourceMap = new HashMap<String, CmsPublishedResource>(); 752 Iterator<CmsPublishedResource> itPubRes = publishedResources.iterator(); 753 while (itPubRes.hasNext()) { 754 CmsPublishedResource pubResource = itPubRes.next(); 755 // check the internal flag if the resource does still exist 756 // we cannot export with an internal flag 757 if (cms.existsResource(pubResource.getRootPath())) { 758 CmsResource vfsResource = cms.readResource(pubResource.getRootPath()); 759 if (!vfsResource.isInternal()) { 760 // add only if not internal 761 // additionally, add all siblings of the resource 762 Iterator<CmsPublishedResource> itSiblings = getSiblings(cms, pubResource).iterator(); 763 while (itSiblings.hasNext()) { 764 CmsPublishedResource sibling = itSiblings.next(); 765 resourceMap.put(sibling.getRootPath(), sibling); 766 } 767 } 768 } else { 769 // the resource does not exist, so add them for deletion in the static export 770 resourceMap.put(pubResource.getRootPath(), pubResource); 771 } 772 773 boolean match = false; 774 Iterator<CmsStaticExportExportRule> itExportRules = OpenCms.getStaticExportManager().getExportRules().iterator(); 775 while (itExportRules.hasNext()) { 776 CmsStaticExportExportRule rule = itExportRules.next(); 777 Set<CmsPublishedResource> relatedResources = rule.getRelatedResources(cms, pubResource); 778 if (relatedResources != null) { 779 Iterator<CmsPublishedResource> itRelatedRes = relatedResources.iterator(); 780 while (itRelatedRes.hasNext()) { 781 CmsPublishedResource relatedRes = itRelatedRes.next(); 782 resourceMap.put(relatedRes.getRootPath(), relatedRes); 783 } 784 match = true; 785 } 786 } 787 // if one res does not match any rule, then export all files 788 if (!match) { 789 return getAllResources(cms); 790 } 791 } 792 return new ArrayList<CmsPublishedResource>(resourceMap.values()); 793 } 794 } finally { 795 cms.getRequestContext().setSiteRoot(storedSiteRoot); 796 } 797 } 798 799 /** 800 * Returns all siblings of the published resource as list of <code>CmsPublishedResource</code>.<p> 801 * 802 * @param cms the cms object 803 * @param pubResource the published resource 804 * 805 * @return all siblings of the published resource 806 * 807 * @throws CmsException if something goes wrong 808 */ 809 protected Set<CmsPublishedResource> getSiblings(CmsObject cms, CmsPublishedResource pubResource) 810 throws CmsException { 811 812 Set<CmsPublishedResource> siblings = new HashSet<CmsPublishedResource>(); 813 for (Iterator<String> i = getSiblingsList(cms, pubResource.getRootPath()).iterator(); i.hasNext();) { 814 String sibling = i.next(); 815 siblings.add(new CmsPublishedResource(cms.readResource(sibling))); 816 } 817 return siblings; 818 } 819 820 /** 821 * Returns all non template resources found in a list of published resources.<p> 822 * 823 * @param cms the current cms object 824 * @param publishedResources the list of published resources 825 * @param resourcesToExport the list of non-template resources 826 * 827 * @return <code>true</code> if some template resources were found while looping the list of published resources 828 * 829 * @throws CmsException in case of errors accessing the VFS 830 */ 831 protected boolean readNonTemplateResourcesToExport( 832 CmsObject cms, 833 List<CmsPublishedResource> publishedResources, 834 List<CmsStaticExportData> resourcesToExport) 835 throws CmsException { 836 837 CmsStaticExportManager manager = OpenCms.getStaticExportManager(); 838 boolean templatesFound = false; 839 // loop through all resources 840 Iterator<CmsPublishedResource> i = publishedResources.iterator(); 841 while (i.hasNext()) { 842 CmsPublishedResource pubRes = i.next(); 843 String vfsName = pubRes.getRootPath(); 844 // only process this resource, if it is within the tree of allowed folders for static export 845 if (manager.getExportFolderMatcher().match(vfsName)) { 846 // get the export data object, if null is returned, this resource cannot be exported 847 CmsStaticExportData exportData = manager.getVfsExportData(cms, vfsName); 848 if (exportData != null) { 849 CmsResource resource = null; 850 if (pubRes.isFile()) { 851 resource = exportData.getResource(); 852 } else { 853 // the resource is a folder, check if PROPERTY_DEFAULT_FILE is set on folder 854 try { 855 resource = cms.readDefaultFile(vfsName); 856 // String defaultFileName = cms.readPropertyObject( 857 // vfsName, 858 // CmsPropertyDefinition.PROPERTY_DEFAULT_FILE, 859 // false).getValue(); 860 // if (defaultFileName != null) { 861 // resource = cms.readResource(vfsName + defaultFileName); 862 // } 863 } catch (CmsException e) { 864 // resource is (still) a folder, check default files specified in configuration 865 for (int j = 0; j < OpenCms.getDefaultFiles().size(); j++) { 866 String tmpResourceName = vfsName + OpenCms.getDefaultFiles().get(j); 867 try { 868 resource = cms.readResource(tmpResourceName); 869 break; 870 } catch (CmsException e1) { 871 // ignore all other exceptions and continue the lookup process 872 } 873 } 874 } 875 } 876 if ((resource != null) && resource.isFile()) { 877 // check loader for current resource if it must be processed before exported 878 I_CmsResourceLoader loader = OpenCms.getResourceManager().getLoader(resource); 879 if (!loader.isStaticExportProcessable()) { 880 // this resource must not be processed, so export it (if it's not marked as deleted) 881 if (!pubRes.getState().isDeleted()) { 882 // mark the resource for export to the real file system 883 resourcesToExport.add(exportData); 884 } 885 } else { 886 // the resource is a template resource or a folder, so store the name of it in the DB for further use 887 templatesFound = true; 888 cms.writeStaticExportPublishedResource( 889 exportData.getRfsName(), 890 CmsStaticExportManager.EXPORT_LINK_WITHOUT_PARAMETER, 891 "", 892 System.currentTimeMillis()); 893 } 894 } 895 } 896 } 897 } 898 899 return templatesFound; 900 } 901}