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.workplace.tools.searchindex.sourcesearch; 029 030import org.opencms.file.CmsFile; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsProject; 033import org.opencms.file.CmsResource; 034import org.opencms.file.CmsResourceFilter; 035import org.opencms.file.types.CmsResourceTypeXmlContent; 036import org.opencms.file.types.I_CmsResourceType; 037import org.opencms.i18n.CmsLocaleManager; 038import org.opencms.loader.CmsLoaderException; 039import org.opencms.lock.CmsLock; 040import org.opencms.main.CmsException; 041import org.opencms.main.CmsLog; 042import org.opencms.main.OpenCms; 043import org.opencms.report.A_CmsReportThread; 044import org.opencms.report.I_CmsReport; 045import org.opencms.search.CmsSearchException; 046import org.opencms.search.solr.CmsSolrIndex; 047import org.opencms.search.solr.CmsSolrQuery; 048import org.opencms.util.CmsRequestUtil; 049import org.opencms.util.CmsStringUtil; 050import org.opencms.xml.CmsXmlUtils; 051import org.opencms.xml.content.CmsXmlContent; 052import org.opencms.xml.content.CmsXmlContentFactory; 053import org.opencms.xml.types.I_CmsXmlContentValue; 054 055import java.util.ArrayList; 056import java.util.HashSet; 057import java.util.Iterator; 058import java.util.List; 059import java.util.Locale; 060import java.util.Set; 061import java.util.regex.Matcher; 062import java.util.regex.Pattern; 063 064import javax.servlet.http.HttpSession; 065 066import org.apache.commons.logging.Log; 067 068/** 069 * Searches in sources. 070 * <p> 071 * 072 * @since 7.5.3 073 */ 074public class CmsSearchReplaceThread extends A_CmsReportThread { 075 076 /** The log object for this class. */ 077 private static final Log LOG = CmsLog.getLog(CmsSearchReplaceThread.class); 078 079 /** The number of Solr search results to be processed at maximum. */ 080 private static final int MAX_PROCESSED_SOLR_RESULTS = 10000; 081 082 /** Number of errors while searching. */ 083 private int m_errorSearch; 084 085 /** Number of errors while updating. */ 086 private int m_errorUpdate; 087 088 /** Number of locked files during updating. */ 089 private int m_lockedFiles; 090 091 /** The found resources. */ 092 private Set<CmsResource> m_matchedResources = new HashSet<CmsResource>(); 093 094 /** The current session. */ 095 private HttpSession m_session; 096 097 /** Settings. */ 098 private CmsSearchReplaceSettings m_settings; 099 100 /** 101 * Creates a replace html tag Thread.<p> 102 * 103 * @param session the current session 104 * @param cms the current cms object 105 * @param settings the settings needed to perform the operation. 106 */ 107 public CmsSearchReplaceThread(HttpSession session, CmsObject cms, CmsSearchReplaceSettings settings) { 108 109 super(cms, "searchAndReplace"); 110 initHtmlReport(cms.getRequestContext().getLocale()); 111 m_session = session; 112 m_settings = settings; 113 } 114 115 /** 116 * @see org.opencms.report.A_CmsReportThread#getReportUpdate() 117 */ 118 @Override 119 public String getReportUpdate() { 120 121 return getReport().getReportUpdate(); 122 } 123 124 /** 125 * @see java.lang.Runnable#run() 126 */ 127 @Override 128 public void run() { 129 130 // get the report 131 I_CmsReport report = getReport(); 132 boolean isError = false; 133 report.println( 134 Messages.get().container(Messages.RPT_SOURCESEARCH_BEGIN_SEARCH_THREAD_0), 135 I_CmsReport.FORMAT_HEADLINE); 136 // write parameters to report 137 report.println(Messages.get().container(Messages.RPT_SOURCESEARCH_PARAMETERS_0), I_CmsReport.FORMAT_HEADLINE); 138 // the paths 139 if (!m_settings.getPaths().isEmpty()) { 140 // iterate over the paths 141 Iterator<String> iter = m_settings.getPaths().iterator(); 142 while (iter.hasNext()) { 143 String path = iter.next(); 144 report.println( 145 Messages.get().container(Messages.RPT_SOURCESEARCH_PARAMETERS_RESOURCE_PATH_1, path), 146 I_CmsReport.FORMAT_NOTE); 147 } 148 } else { 149 // no paths selected 150 isError = true; 151 report.println( 152 Messages.get().container(Messages.RPT_SOURCESEARCH_PARAMETERS_EMPTY_RESOURCE_PATHS_0), 153 I_CmsReport.FORMAT_ERROR); 154 } 155 // the search pattern 156 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(m_settings.getSearchpattern())) { 157 // there is a search pattern 158 report.println( 159 Messages.get().container( 160 Messages.RPT_SOURCESEARCH_PARAMETERS_SEARCHPATTERN_1, 161 CmsStringUtil.escapeHtml(m_settings.getSearchpattern())), 162 I_CmsReport.FORMAT_NOTE); 163 } else { 164 // empty search pattern 165 isError = true; 166 report.println( 167 Messages.get().container(Messages.RPT_SOURCESEARCH_PARAMETERS_EMPTY_SEARCHPATTERN_0), 168 I_CmsReport.FORMAT_ERROR); 169 } 170 // the replace pattern 171 report.println( 172 Messages.get().container( 173 Messages.RPT_SOURCESEARCH_PARAMETERS_REPLACEPATTERN_1, 174 CmsStringUtil.escapeHtml(m_settings.getReplacepattern())), 175 I_CmsReport.FORMAT_NOTE); 176 // the project 177 report.println( 178 Messages.get().container(Messages.RPT_SOURCESEARCH_PARAMETERS_PROJECT_1, m_settings.getProject()), 179 I_CmsReport.FORMAT_NOTE); 180 // remarks for search/replace dependent od the replace pattern and the selected project 181 // in the online project search is possible only 182 // in other projects there is replaced, if the replace pattern is not empty 183 boolean replace = false; 184 if (CmsStringUtil.isEmpty(m_settings.getReplacepattern()) && !m_settings.isForceReplace()) { 185 // empty replace pattern, search only 186 report.println( 187 Messages.get().container(Messages.RPT_SOURCESEARCH_PARAMETERS_EMPTY_REPLACEPATTERN_0), 188 I_CmsReport.FORMAT_NOTE); 189 } else { 190 // not empty replace pattern, search and replace 191 replace = true; 192 report.println( 193 Messages.get().container(Messages.RPT_SOURCESEARCH_PARAMETERS_NOTEMPTY_REPLACEPATTERN_0), 194 I_CmsReport.FORMAT_NOTE); 195 } 196 197 // make an OpenCms object copy if replace is active 198 CmsObject cmsObject = getCms(); 199 if (replace && !m_settings.getProject().equals(cmsObject.getRequestContext().getCurrentProject().getName())) { 200 try { 201 cmsObject = OpenCms.initCmsObject(getCms()); 202 CmsProject cmsProject = getCms().readProject(m_settings.getProject()); 203 cmsObject.getRequestContext().setCurrentProject(cmsProject); 204 } catch (CmsException e) { 205 report.println( 206 Messages.get().container(Messages.RPT_SOURCESEARCH_INIT_CMS_OBJECT_FAILED_0), 207 I_CmsReport.FORMAT_NOTE); 208 replace = false; 209 } 210 } 211 212 // search the resources and replace the patterns 213 if (!isError) { 214 List<CmsResource> resources = searchResources(report, cmsObject); 215 216 if (resources.isEmpty()) { 217 // no resources found, so search is not possible 218 report.println( 219 Messages.get().container(Messages.RPT_SOURCESEARCH_NO_FILES_TO_SEARCH_IN_0), 220 I_CmsReport.FORMAT_NOTE); 221 } else { 222 223 report.println( 224 Messages.get().container( 225 Messages.RPT_SOURCESEARCH_NR_OF_FILES_TO_SEARCH_IN_1, 226 Integer.valueOf(resources.size())), 227 I_CmsReport.FORMAT_NOTE); 228 if (replace) { 229 // start searching and replacing 230 report.println( 231 Messages.get().container(Messages.RPT_SOURCESEARCH_START_SEARCHING_REPLACING_0), 232 I_CmsReport.FORMAT_HEADLINE); 233 } else { 234 // start searching 235 report.println( 236 Messages.get().container(Messages.RPT_SOURCESEARCH_START_SEARCHING_0), 237 I_CmsReport.FORMAT_HEADLINE); 238 } 239 240 searchAndReplace(cmsObject, resources, replace, report); 241 } 242 243 // show the resources 244 // save the matched file list in the session 245 m_session.setAttribute( 246 CmsSearchReplaceSettings.ATTRIBUTE_NAME_SOURCESEARCH_RESULT_LIST, 247 m_matchedResources); 248 } else { 249 // do not show the resources, because there were errors while searching 250 } 251 252 report.println( 253 Messages.get().container(Messages.RPT_SOURCESEARCH_END_SEARCH_THREAD_0), 254 I_CmsReport.FORMAT_HEADLINE); 255 } 256 257 /** 258 * Search the resources.<p> 259 * 260 * @param cmsObject the CmsObject using to write files 261 * @param resources the relevant resources 262 * @param replace true, if search and replace. False is search only. 263 * @param report the report. 264 */ 265 protected void searchAndReplace( 266 CmsObject cmsObject, 267 List<CmsResource> resources, 268 boolean replace, 269 I_CmsReport report) { 270 271 // the file counter 272 int counter = 0; 273 int resCount = resources.size(); 274 275 // iterate over the files in the selected path 276 for (CmsResource resource : resources) { 277 278 try { 279 280 // get the content 281 CmsFile file = getCms().readFile(resource); 282 byte[] contents = file.getContents(); 283 284 // report the current resource 285 ++counter; 286 report(report, counter, resCount, resource); 287 288 // search and replace 289 byte[] result = null; 290 boolean xpath = false; 291 if ((CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_settings.getXpath()) 292 || m_settings.isOnlyContentValues()) && CmsResourceTypeXmlContent.isXmlContent(resource)) { 293 xpath = true; 294 } 295 if (!xpath) { 296 result = replaceInContent(cmsObject, report, file, contents, replace); 297 } else { 298 result = replaceInXml(cmsObject, file, replace, report); 299 } 300 301 if ((result != null) && (contents != null) && !contents.equals(result)) { 302 // rewrite the content 303 writeContent(cmsObject, report, file, result); 304 } 305 306 } catch (Exception e) { 307 report.print( 308 org.opencms.report.Messages.get().container(Messages.RPT_SOURCESEARCH_COULD_NOT_READ_FILE_0), 309 I_CmsReport.FORMAT_ERROR); 310 report.addError(e); 311 report.println( 312 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_FAILED_0), 313 I_CmsReport.FORMAT_ERROR); 314 m_errorSearch += 1; 315 LOG.error( 316 org.opencms.report.Messages.get().container(Messages.RPT_SOURCESEARCH_COULD_NOT_READ_FILE_0), 317 e); 318 continue; 319 } 320 } 321 322 // report results 323 reportResults(replace, report, resources.size()); 324 } 325 326 /** 327 * Locks the current resource.<p> 328 * 329 * @param cms the current CmsObject 330 * @param cmsResource the resource to lock 331 * @param report the report 332 * 333 * @return <code>true</code> if the given resource was locked was successfully 334 * 335 * @throws CmsException if some goes wrong 336 */ 337 private boolean lockResource(CmsObject cms, CmsResource cmsResource, I_CmsReport report) throws CmsException { 338 339 CmsLock lock = cms.getLock(cms.getSitePath(cmsResource)); 340 // check the lock 341 if ((lock != null) 342 && lock.isOwnedBy(cms.getRequestContext().getCurrentUser()) 343 && lock.isOwnedInProjectBy( 344 cms.getRequestContext().getCurrentUser(), 345 cms.getRequestContext().getCurrentProject())) { 346 // prove is current lock from current user in current project 347 return true; 348 } else if ((lock != null) && !lock.isUnlocked() && !lock.isOwnedBy(cms.getRequestContext().getCurrentUser())) { 349 // the resource is not locked by the current user, so can not lock it 350 m_lockedFiles += 1; 351 return false; 352 } else if ((lock != null) 353 && !lock.isUnlocked() 354 && lock.isOwnedBy(cms.getRequestContext().getCurrentUser()) 355 && !lock.isOwnedInProjectBy( 356 cms.getRequestContext().getCurrentUser(), 357 cms.getRequestContext().getCurrentProject())) { 358 // prove is current lock from current user but not in current project 359 // file is locked by current user but not in current project 360 // change the lock 361 cms.changeLock(cms.getSitePath(cmsResource)); 362 } else if ((lock != null) && lock.isUnlocked()) { 363 // lock resource from current user in current project 364 cms.lockResource(cms.getSitePath(cmsResource)); 365 } 366 lock = cms.getLock(cms.getSitePath(cmsResource)); 367 if ((lock != null) 368 && lock.isOwnedBy(cms.getRequestContext().getCurrentUser()) 369 && !lock.isOwnedInProjectBy( 370 cms.getRequestContext().getCurrentUser(), 371 cms.getRequestContext().getCurrentProject())) { 372 // resource could not be locked 373 m_lockedFiles += 1; 374 375 return false; 376 } 377 // resource is locked successfully 378 return true; 379 } 380 381 /** 382 * Performs the replacement in content.<p> 383 * 384 * @param cmsObject the cms context 385 * @param report the report to print messages to 386 * @param file the file object 387 * @param contents the byte content 388 * @param replace signals whether to execute a replacement or not 389 * 390 * @return the new content if a replacement has been performed 391 * 392 * @throws Exception if something goes wrong 393 */ 394 private byte[] replaceInContent( 395 CmsObject cmsObject, 396 I_CmsReport report, 397 CmsFile file, 398 byte[] contents, 399 boolean replace) 400 throws Exception { 401 402 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(m_settings.getLocale())) { 403 Locale contentLocale = CmsLocaleManager.getMainLocale(cmsObject, file); 404 if (!contentLocale.toString().equalsIgnoreCase(m_settings.getLocale())) { 405 // content does not match the requested locale, skip it 406 report.println( 407 Messages.get().container(Messages.RPT_SOURCESEARCH_NOT_MATCHED_0), 408 I_CmsReport.FORMAT_NOTE); 409 return null; 410 } 411 } 412 413 String encoding = CmsLocaleManager.getResourceEncoding(cmsObject, file); 414 String content = new String(contents, encoding); 415 416 Matcher matcher; 417 matcher = Pattern.compile(m_settings.getSearchpattern()).matcher(content); 418 if (matcher.find()) { 419 // search pattern did match here, so take this file in the list with matches resources 420 m_matchedResources.add(file); 421 report.println(Messages.get().container(Messages.RPT_SOURCESEARCH_MATCHED_0), I_CmsReport.FORMAT_OK); 422 if (replace) { 423 return matcher.replaceAll(m_settings.getReplacepattern()).getBytes(encoding); 424 } 425 } else { 426 // search pattern did not match 427 report.println(Messages.get().container(Messages.RPT_SOURCESEARCH_NOT_MATCHED_0), I_CmsReport.FORMAT_NOTE); 428 } 429 return null; 430 } 431 432 /** 433 * Performs a replacement for XML contents.<p> 434 * 435 * @param cmsObject the cms object to perform the actio with 436 * @param cmsFile the file to operate on 437 * @param replace <code>true</code> if a replacement should be performed 438 * @param report the report to print messages to 439 * 440 * @return the marshaled content 441 * @throws Exception if something goes wrong 442 */ 443 private byte[] replaceInXml(CmsObject cmsObject, CmsFile cmsFile, boolean replace, I_CmsReport report) 444 throws Exception { 445 446 Exception e = null; 447 CmsXmlContent xmlContent = CmsXmlContentFactory.unmarshal(cmsObject, cmsFile); 448 Pattern pattern = Pattern.compile(m_settings.getSearchpattern()); 449 // loop over the locales of the content 450 boolean modified = false; 451 boolean matched = false; 452 String requestedLocale = m_settings.getLocale(); 453 for (Locale locale : xmlContent.getLocales()) { 454 if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(requestedLocale) 455 && !locale.toString().equalsIgnoreCase(requestedLocale)) { 456 // does not match the requested locale, skip it 457 continue; 458 } 459 // loop over the available element paths of the current content locale 460 List<String> paths = xmlContent.getNames(locale); 461 for (String xpath : paths) { 462 // try to get the value extraction for the current element path 463 I_CmsXmlContentValue value = xmlContent.getValue(xpath, locale); 464 if (value.isSimpleType()) { 465 try { 466 String currPath = value.getPath(); 467 if (CmsStringUtil.isEmptyOrWhitespaceOnly(m_settings.getXpath()) 468 || currPath.equals(m_settings.getXpath()) 469 || (CmsXmlUtils.removeXpath(currPath).equals(m_settings.getXpath()))) { 470 // xpath match 471 String oldVal = value.getStringValue(cmsObject); 472 Matcher matcher = pattern.matcher(oldVal); 473 matcher = Pattern.compile(m_settings.getSearchpattern()).matcher(oldVal); 474 if (matcher.find()) { 475 matched = true; 476 m_matchedResources.add(cmsFile); 477 if (replace) { 478 String newVal = matcher.replaceAll(m_settings.getReplacepattern()); 479 if (!oldVal.equals(newVal)) { 480 value.setStringValue(cmsObject, newVal); 481 modified = true; 482 } 483 } 484 } 485 } 486 } catch (Exception ex) { 487 // log and go on 488 LOG.error(ex.getMessage(), ex); 489 e = ex; 490 } 491 } 492 } 493 } 494 if (e != null) { 495 throw e; 496 } 497 if (matched) { 498 report.println(Messages.get().container(Messages.RPT_SOURCESEARCH_MATCHED_0), I_CmsReport.FORMAT_OK); 499 } else { 500 report.println(Messages.get().container(Messages.RPT_SOURCESEARCH_NOT_MATCHED_0), I_CmsReport.FORMAT_NOTE); 501 } 502 if (modified) { 503 return xmlContent.marshal(); 504 } 505 return null; 506 } 507 508 /** 509 * Reads the content as byte array of the given resource and prints a message to the report.<p> 510 * 511 * @param report the report 512 * @param counter the counter 513 * @param resCount the total resource count 514 * @param resource the file to get the content for 515 */ 516 private void report(I_CmsReport report, int counter, int resCount, CmsResource resource) { 517 518 // report entries 519 report.print( 520 org.opencms.report.Messages.get().container( 521 org.opencms.report.Messages.RPT_SUCCESSION_2, 522 String.valueOf(counter), 523 String.valueOf(resCount)), 524 I_CmsReport.FORMAT_NOTE); 525 report.print( 526 org.opencms.report.Messages.get().container( 527 org.opencms.report.Messages.RPT_ARGUMENT_1, 528 report.removeSiteRoot(resource.getRootPath()))); 529 report.print( 530 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0), 531 I_CmsReport.FORMAT_DEFAULT); 532 } 533 534 /** 535 * Prints the result messages into the report.<p> 536 * 537 * @param replace if replacement has to be executed 538 * @param report the report to use 539 * @param nrOfFiles the total number of files 540 */ 541 private void reportResults(boolean replace, I_CmsReport report, int nrOfFiles) { 542 543 // report entries 544 if (replace) { 545 // finish searching and replacing 546 report.println( 547 Messages.get().container(Messages.RPT_SOURCESEARCH_END_SEARCHING_REPLACING_0), 548 I_CmsReport.FORMAT_HEADLINE); 549 } else { 550 // finish searching 551 report.println( 552 Messages.get().container(Messages.RPT_SOURCESEARCH_END_SEARCHING_0), 553 I_CmsReport.FORMAT_HEADLINE); 554 } 555 // the results are written in the report 556 report.println(Messages.get().container(Messages.RPT_SOURCESEARCH_RESULT_0), I_CmsReport.FORMAT_HEADLINE); 557 report.println( 558 Messages.get().container( 559 Messages.RPT_SOURCESEARCH_NR_OF_FILES_TO_SEARCH_IN_1, 560 Integer.valueOf(nrOfFiles).toString()), 561 I_CmsReport.FORMAT_NOTE); 562 report.println( 563 Messages.get().container( 564 Messages.RPT_SOURCESEARCH_NR_OF_FILES_MATCHED_1, 565 Integer.valueOf(m_matchedResources.size()).toString()), 566 I_CmsReport.FORMAT_NOTE); 567 report.println( 568 Messages.get().container( 569 Messages.RPT_SOURCESEARCH_SEARCH_ERROR_COUNT_1, 570 Integer.valueOf(m_errorSearch).toString()), 571 I_CmsReport.FORMAT_NOTE); 572 if (replace) { 573 // replace report entries 574 report.println( 575 Messages.get().container( 576 Messages.RPT_SOURCESEARCH_REPLACE_ERROR_COUNT_1, 577 Integer.valueOf(m_errorUpdate).toString()), 578 I_CmsReport.FORMAT_NOTE); 579 report.println( 580 Messages.get().container( 581 Messages.RPT_SOURCESEARCH_LOCKED_FILES_1, 582 Integer.valueOf(m_lockedFiles).toString()), 583 I_CmsReport.FORMAT_NOTE); 584 if (m_matchedResources.size() == 0) { 585 report.println( 586 Messages.get().container(Messages.RPT_SOURCESEARCH_NO_FILES_FOUND_0), 587 I_CmsReport.FORMAT_OK); 588 } else { 589 report.println( 590 Messages.get().container(Messages.RPT_SOURCESEARCH_CLICK_OK_TO_GET_LIST_0), 591 I_CmsReport.FORMAT_OK); 592 } 593 if (m_lockedFiles > 0) { 594 report.println( 595 Messages.get().container(Messages.RPT_SOURCESEARCH_REPLACE_FAILED_0), 596 I_CmsReport.FORMAT_ERROR); 597 } else { 598 report.println( 599 Messages.get().container(Messages.RPT_SOURCESEARCH_REPLACE_SUCCESS_0), 600 I_CmsReport.FORMAT_OK); 601 } 602 } else { 603 // search report entries 604 if (m_matchedResources.size() == 0) { 605 report.println( 606 Messages.get().container(Messages.RPT_SOURCESEARCH_NO_FILES_FOUND_0), 607 I_CmsReport.FORMAT_OK); 608 } else { 609 report.println( 610 Messages.get().container(Messages.RPT_SOURCESEARCH_CLICK_OK_TO_GET_LIST_0), 611 I_CmsReport.FORMAT_OK); 612 } 613 if (m_errorSearch > 0) { 614 // only searching failed 615 report.println( 616 Messages.get().container(Messages.RPT_SOURCESEARCH_SEARCH_FAILED_0), 617 I_CmsReport.FORMAT_ERROR); 618 } else { 619 // only searching was successful 620 report.println( 621 Messages.get().container(Messages.RPT_SOURCESEARCH_SEARCH_SUCCESS_0), 622 I_CmsReport.FORMAT_OK); 623 } 624 } 625 } 626 627 /** 628 * Searches/reads all resources that are relevant.<p> 629 * 630 * @param report the report 631 * @param cmsObject the cms Object to use 632 * 633 * @return the relevant resources 634 */ 635 private List<CmsResource> searchResources(I_CmsReport report, CmsObject cmsObject) { 636 637 report.println( 638 Messages.get().container(Messages.RPT_SOURCESEARCH_START_COLLECTING_FILES_TO_SEARCH_IN_0), 639 I_CmsReport.FORMAT_HEADLINE); 640 641 List<CmsResource> resources = new ArrayList<CmsResource>(); 642 if (m_settings.isSolrSearch()) { 643 CmsSolrIndex index = OpenCms.getSearchManager().getIndexSolr(m_settings.getSource()); 644 if (index != null) { 645 CmsSolrQuery query = new CmsSolrQuery( 646 null, 647 CmsRequestUtil.createParameterMap(m_settings.getQuery() + "&fl=path,type")); 648 query.setSearchRoots(m_settings.getPaths()); 649 if ((m_settings.getTypesArray() != null) && (m_settings.getTypesArray().length > 0)) { 650 query.setResourceTypes(m_settings.getTypesArray()); 651 } 652 query.setRows(Integer.valueOf(MAX_PROCESSED_SOLR_RESULTS)); 653 query.ensureParameters(); 654 try { 655 resources.addAll( 656 index.search(cmsObject, query, true, null, false, null, MAX_PROCESSED_SOLR_RESULTS)); 657 } catch (CmsSearchException e) { 658 LOG.error(e.getMessage(), e); 659 } 660 } 661 } else { 662 CmsResourceFilter filter = CmsResourceFilter.ALL.addRequireFile().addExcludeState( 663 CmsResource.STATE_DELETED).addRequireTimerange().addRequireVisible(); 664 if ((m_settings.getTypesArray() != null) && (m_settings.getTypesArray().length > 0)) { 665 for (String resTypeName : m_settings.getTypesArray()) { 666 try { 667 I_CmsResourceType type = OpenCms.getResourceManager().getResourceType(resTypeName); 668 filter = filter.addRequireType(type); 669 } catch (CmsLoaderException e) { 670 // noop 671 } catch (NullPointerException e) { 672 // noop 673 } 674 } 675 } 676 677 // iterate over all selected paths 678 Iterator<String> iterPaths = m_settings.getPaths().iterator(); 679 while (iterPaths.hasNext()) { 680 String path = iterPaths.next(); 681 try { 682 // only read resources which are files and not deleted, which are in the current time range window and where the current 683 // user has the sufficient permissions to read them 684 List<CmsResource> tmpResources = getCms().readResources(path, filter); 685 if ((tmpResources != null) && !tmpResources.isEmpty()) { 686 resources.addAll(tmpResources); 687 } 688 } catch (CmsException e) { 689 // an error occured 690 LOG.error(Messages.get().container(Messages.RPT_SOURCESEARCH_ERROR_READING_RESOURCES_1, path), e); 691 report.println( 692 Messages.get().container(Messages.RPT_SOURCESEARCH_ERROR_READING_RESOURCES_1, path), 693 I_CmsReport.FORMAT_ERROR); 694 } 695 } 696 } 697 return resources; 698 } 699 700 /** 701 * Writes the file contents.<p> 702 * 703 * @param cmsObject the cms context 704 * @param report the report 705 * @param file the file to write 706 * @param content the file content 707 * 708 * @return success flag 709 */ 710 private boolean writeContent(CmsObject cmsObject, I_CmsReport report, CmsFile file, byte[] content) { 711 712 boolean success = true; 713 714 // get current lock from file 715 try { 716 // try to lock the resource 717 if (!lockResource(cmsObject, file, report)) { 718 report.println( 719 Messages.get().container(Messages.RPT_SOURCESEARCH_LOCKED_FILE_0, cmsObject.getSitePath(file)), 720 I_CmsReport.FORMAT_ERROR); 721 success = false; 722 } 723 } catch (CmsException e) { 724 report.println( 725 Messages.get().container(Messages.RPT_SOURCESEARCH_LOCKED_FILE_0, cmsObject.getSitePath(file)), 726 I_CmsReport.FORMAT_ERROR); 727 if (LOG.isErrorEnabled()) { 728 LOG.error(e.getMessageContainer(), e); 729 } 730 success = false; 731 } 732 733 // write the file content 734 try { 735 file.setContents(content); 736 cmsObject.writeFile(file); 737 } catch (Exception e) { 738 m_errorUpdate += 1; 739 report.println( 740 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_FAILED_0), 741 I_CmsReport.FORMAT_ERROR); 742 if (LOG.isErrorEnabled()) { 743 LOG.error(e.toString()); 744 } 745 success = false; 746 } 747 748 // unlock the resource 749 try { 750 cmsObject.unlockResource(cmsObject.getSitePath(file)); 751 } catch (CmsException e) { 752 m_errorUpdate += 1; 753 report.println( 754 Messages.get().container(Messages.RPT_SOURCESEARCH_UNLOCK_FILE_0), 755 I_CmsReport.FORMAT_WARNING); 756 if (LOG.isErrorEnabled()) { 757 LOG.error(e.getMessageContainer(), e); 758 } 759 success = false; 760 } 761 762 if (success) { 763 // successfully updated 764 report.println( 765 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), 766 I_CmsReport.FORMAT_OK); 767 } 768 769 return success; 770 } 771}