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.content.check; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsResource; 032import org.opencms.file.CmsResourceFilter; 033import org.opencms.main.CmsException; 034import org.opencms.main.CmsLog; 035import org.opencms.report.I_CmsReport; 036import org.opencms.util.CmsFileUtil; 037import org.opencms.workplace.CmsWorkplace; 038import org.opencms.workplace.tools.CmsToolManager; 039 040import java.util.ArrayList; 041import java.util.Iterator; 042import java.util.List; 043import java.util.SortedMap; 044import java.util.TreeMap; 045 046import org.apache.commons.logging.Log; 047 048/** 049 * Main implementation of the content check. It maintains all configured content check 050 * plugins and handles the check process.<p> 051 * 052 * 053 * @since 6.1.2 054 */ 055public class CmsContentCheck { 056 057 /** Path to the plugin folder. */ 058 public static final String VFS_PATH_PLUGIN_FOLDER = CmsWorkplace.VFS_PATH_WORKPLACE 059 + "admin/contenttools/check/plugin/"; 060 061 /** The log object for this class. */ 062 private static final Log LOG = CmsLog.getLog(CmsContentCheck.class); 063 064 /** The CmsObject. */ 065 private CmsObject m_cms; 066 067 /** The list of paths to be processed. */ 068 private List m_paths; 069 070 /** The list of all instantiated plugins. */ 071 private List m_plugins; 072 073 /** The report for the output. */ 074 private I_CmsReport m_report; 075 076 /** The map of resources to check. */ 077 private SortedMap m_resources; 078 079 /** The content check result. */ 080 private CmsContentCheckResult m_result; 081 082 /** 083 * Constructor, creates a new CmsContentCheck. <p> 084 * 085 * @param cms the CmsObject 086 */ 087 public CmsContentCheck(CmsObject cms) { 088 089 m_cms = cms; 090 m_plugins = new ArrayList(); 091 m_paths = new ArrayList(); 092 m_result = new CmsContentCheckResult(); 093 094 try { 095 init(); 096 } catch (CmsException e) { 097 // TODO: do some errorhandling 098 } 099 } 100 101 /** 102 * Gets a list of all paths to be processed by the content check plugins.<p> 103 * 104 * @return list of vfs paths 105 */ 106 public List getPaths() { 107 108 return m_paths; 109 } 110 111 /** 112 * Gets a list of instances of all available content check plugins.<p> 113 * 114 * @return list of plugin instances. 115 */ 116 public List getPlugins() { 117 118 return m_plugins; 119 } 120 121 /** 122 * Gets the number of installed plugins.<p> 123 * 124 * @return number of installed plugins 125 */ 126 public int getPluginsCount() { 127 128 return m_plugins.size(); 129 } 130 131 /** 132 * Gets the results of the content check.<p> 133 * 134 * @return CmsContentCheckResult object containing all resources that collected an error or warning 135 */ 136 public CmsContentCheckResult getResults() { 137 138 return m_result; 139 } 140 141 /** 142 * Sets the list of all paths to be processed by the content check plugins.<p> 143 * @param paths list of vfs paths 144 */ 145 public void setPaths(List paths) { 146 147 m_paths = paths; 148 } 149 150 /** 151 * Starts the content check.<p> 152 * 153 * @param cms the CmsObject 154 * @param report StringBuffer for reporting 155 * @throws Exception if something goes wrong 156 */ 157 public void startContentCheck(CmsObject cms, I_CmsReport report) throws Exception { 158 159 m_report = report; 160 m_report.println(Messages.get().container(Messages.RPT_CONTENT_CHECK_BEGIN_0), I_CmsReport.FORMAT_HEADLINE); 161 162 // collect all resources 163 m_report.print(Messages.get().container(Messages.RPT_CONTENT_COLLECT_BEGIN_0), I_CmsReport.FORMAT_HEADLINE); 164 m_report.println( 165 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0), 166 I_CmsReport.FORMAT_HEADLINE); 167 m_resources = collectResources(cms); 168 m_report.print( 169 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0), 170 I_CmsReport.FORMAT_HEADLINE); 171 m_report.println( 172 Messages.get().container(Messages.RPT_CONTENT_COLLECT_END_1, Integer.valueOf(m_resources.size())), 173 I_CmsReport.FORMAT_HEADLINE); 174 175 // now process all resources 176 m_report.print(Messages.get().container(Messages.RPT_CONTENT_PROCESS_BEGIN_0), I_CmsReport.FORMAT_HEADLINE); 177 m_report.println( 178 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0), 179 I_CmsReport.FORMAT_HEADLINE); 180 int count = 1; 181 Iterator i = m_resources.keySet().iterator(); 182 while (i.hasNext()) { 183 String resourceName = (String)i.next(); 184 CmsContentCheckResource res = (CmsContentCheckResource)m_resources.get(resourceName); 185 boolean errorWarning = false; 186 m_report.print( 187 Messages.get().container( 188 Messages.RPT_CONTENT_PROCESS_2, 189 Integer.valueOf(count++), 190 Integer.valueOf(m_resources.size())), 191 I_CmsReport.FORMAT_NOTE); 192 m_report.print( 193 Messages.get().container(Messages.RPT_CONTENT_PROCESS_RESOURCE_1, res.getResourceName()), 194 I_CmsReport.FORMAT_DEFAULT); 195 m_report.print( 196 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0), 197 I_CmsReport.FORMAT_NOTE); 198 199 // loop through all plugins and perform each content check 200 Iterator j = getPlugins().iterator(); 201 while (j.hasNext()) { 202 I_CmsContentCheck plugin = (I_CmsContentCheck)j.next(); 203 if (plugin.isActive()) { 204 try { 205 // process the content check 206 res = plugin.executeContentCheck(m_cms, res); 207 208 } catch (CmsException e) { 209 errorWarning = true; 210 m_report.println(Messages.get().container(Messages.RPT_EMPTY_0), I_CmsReport.FORMAT_DEFAULT); 211 m_report.print( 212 Messages.get().container(Messages.RPT_CONTENT_PROCESS_ERROR_2, plugin.getName(), e), 213 I_CmsReport.FORMAT_ERROR); 214 } 215 } 216 } 217 218 // check if there are some errors 219 List errors = res.getErrors(); 220 if ((errors != null) && (errors.size() > 0)) { 221 errorWarning = true; 222 m_report.println(Messages.get().container(Messages.RPT_EMPTY_0), I_CmsReport.FORMAT_DEFAULT); 223 m_report.println( 224 Messages.get().container(Messages.RPT_CONTENT_PROCESS_ERROR_0), 225 I_CmsReport.FORMAT_ERROR); 226 Iterator k = errors.iterator(); 227 while (k.hasNext()) { 228 String error = (String)k.next(); 229 m_report.println( 230 Messages.get().container(Messages.RPT_CONTENT_PROCESS_ERROR_1, error), 231 I_CmsReport.FORMAT_ERROR); 232 233 } 234 } 235 236 // check if there are some warnings 237 List warnings = res.getWarnings(); 238 if ((warnings != null) && (warnings.size() > 0)) { 239 errorWarning = true; 240 m_report.println(Messages.get().container(Messages.RPT_EMPTY_0), I_CmsReport.FORMAT_DEFAULT); 241 m_report.println( 242 Messages.get().container(Messages.RPT_CONTENT_PROCESS_WARNING_0), 243 I_CmsReport.FORMAT_WARNING); 244 Iterator k = warnings.iterator(); 245 while (k.hasNext()) { 246 String warning = (String)k.next(); 247 m_report.println( 248 Messages.get().container(Messages.RPT_CONTENT_PROCESS_WARNING_1, warning), 249 I_CmsReport.FORMAT_WARNING); 250 251 } 252 } 253 254 // store the updated CmsContentCheckResource 255 m_resources.put(resourceName, res); 256 257 if (!errorWarning) { 258 m_report.println( 259 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), 260 I_CmsReport.FORMAT_OK); 261 } else { 262 // there was an error or warning, so store the CmsContentCheckResource 263 // in the results 264 m_result.addResult(res); 265 } 266 } 267 m_report.print( 268 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0), 269 I_CmsReport.FORMAT_HEADLINE); 270 m_report.println(Messages.get().container(Messages.RPT_CONTENT_PROCESS_END_0), I_CmsReport.FORMAT_HEADLINE); 271 272 m_report.println(Messages.get().container(Messages.RPT_CONTENT_CHECK_END_0), I_CmsReport.FORMAT_HEADLINE); 273 } 274 275 /** 276 * 277 * @see java.lang.Object#toString() 278 */ 279 @Override 280 public String toString() { 281 282 StringBuffer buf = new StringBuffer(); 283 buf.append("CmsContentCheck Paths=["); 284 for (int i = 0; i < m_paths.size(); i++) { 285 String path = (String)m_paths.get(i); 286 buf.append(path); 287 if (i < (m_paths.size() - 1)) { 288 buf.append(","); 289 } 290 } 291 buf.append("] Plugins=["); 292 for (int i = 0; i < m_plugins.size(); i++) { 293 I_CmsContentCheck plugin = (I_CmsContentCheck)m_plugins.get(i); 294 buf.append(plugin.getName()); 295 buf.append(" ("); 296 buf.append(plugin.isActive()); 297 buf.append(")"); 298 if (i < (m_plugins.size() - 1)) { 299 buf.append(","); 300 } 301 } 302 buf.append("]"); 303 return buf.toString(); 304 } 305 306 /** 307 * Collects all resources required for the content checks and stores them in a Set.<p> 308 * 309 * The collection of resources is build based on the vfs paths stored in this object. 310 * To prevent that resources are collected multiple times (in case of overlapping vfs paths), 311 * the results will be stored as a map. 312 * 313 * @param cms the CmsObject 314 * @return map of CmsContentCheckResources 315 */ 316 private SortedMap collectResources(CmsObject cms) { 317 318 SortedMap collectedResources = new TreeMap(); 319 320 // get all vfs paths and extract the resources from there 321 Iterator i = CmsFileUtil.removeRedundancies(m_paths).iterator(); 322 while (i.hasNext()) { 323 String path = (String)i.next(); 324 m_report.print( 325 Messages.get().container(Messages.RPT_EXTRACT_FROM_PATH_BEGIN_1, path), 326 I_CmsReport.FORMAT_HEADLINE); 327 m_report.println( 328 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0), 329 I_CmsReport.FORMAT_HEADLINE); 330 try { 331 List resources = cms.readResources(path, CmsResourceFilter.IGNORE_EXPIRATION, true); 332 // get the single resources and store them 333 Iterator j = resources.iterator(); 334 while (j.hasNext()) { 335 CmsResource res = (CmsResource)j.next(); 336 // m_report.print( 337 // Messages.get().container(Messages.RPT_EXTRACT_FROM_PATH_1, cms.getSitePath(res)), 338 // I_CmsReport.FORMAT_DEFAULT); 339 // m_report.print( 340 // org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0), 341 // I_CmsReport.FORMAT_DEFAULT); 342 // create a CmsContentCheckResource for each resource 343 CmsContentCheckResource contentCheckRes = new CmsContentCheckResource(res); 344 collectedResources.put(contentCheckRes.getResourceName(), contentCheckRes); 345 // m_report.println( 346 // org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_OK_0), 347 // I_CmsReport.FORMAT_OK); 348 } 349 350 } catch (CmsException e) { 351 m_report.println( 352 Messages.get().container(Messages.RPT_EXTRACT_FROM_PATH_ERROR_2, path, e), 353 I_CmsReport.FORMAT_ERROR); 354 } 355 356 m_report.print( 357 org.opencms.report.Messages.get().container(org.opencms.report.Messages.RPT_DOTS_0), 358 I_CmsReport.FORMAT_HEADLINE); 359 m_report.println( 360 Messages.get().container(Messages.RPT_EXTRACT_FROM_PATH_END_0), 361 I_CmsReport.FORMAT_HEADLINE); 362 363 } 364 365 return collectedResources; 366 } 367 368 /** 369 * Initializes the CmsContent check and reads all available plugins.<p> 370 * 371 * @throws CmsException if somehting goes wrong 372 */ 373 private void init() throws CmsException { 374 375 // first get all installed plugins 376 // plugins are subfolders of the "/plugin/" folder with a template 377 // property holdding the name of the plugin class 378 List resources = m_cms.readResourcesWithProperty(VFS_PATH_PLUGIN_FOLDER, CmsToolManager.HANDLERCLASS_PROPERTY); 379 Iterator i = resources.iterator(); 380 while (i.hasNext()) { 381 CmsResource res = (CmsResource)i.next(); 382 // ony check folders 383 if (res.isFolder()) { 384 String classname = m_cms.readPropertyObject( 385 res.getRootPath(), 386 CmsToolManager.HANDLERCLASS_PROPERTY, 387 false).getValue(); 388 try { 389 Object objectInstance = Class.forName(classname).newInstance(); 390 if (objectInstance instanceof I_CmsContentCheck) { 391 I_CmsContentCheck plugin = (I_CmsContentCheck)objectInstance; 392 plugin.init(m_cms); 393 // store the plugin instance 394 m_plugins.add(plugin); 395 LOG.info(Messages.get().getBundle().key(Messages.LOG_CREATE_PLUGIN_1, classname)); 396 } else { 397 LOG.warn(Messages.get().getBundle().key(Messages.LOG_CANNOT_CREATE_PLUGIN_1, classname)); 398 } 399 } catch (Throwable t) { 400 LOG.error(Messages.get().getBundle().key(Messages.LOG_CANNOT_CREATE_PLUGIN_2, classname, t)); 401 } 402 } 403 } 404 } 405 406}