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.search; 029 030import org.opencms.main.CmsIllegalArgumentException; 031import org.opencms.main.CmsLog; 032import org.opencms.main.OpenCms; 033import org.opencms.search.documents.I_CmsDocumentFactory; 034import org.opencms.util.CmsStringUtil; 035 036import java.io.Serializable; 037import java.util.ArrayList; 038import java.util.HashMap; 039import java.util.Iterator; 040import java.util.LinkedHashMap; 041import java.util.List; 042import java.util.Map; 043 044import org.apache.commons.logging.Log; 045 046/** 047 * A search index source is a description of a list of Cms resources 048 * to be indexed.<p> 049 * 050 * @since 6.0.0 051 */ 052public class CmsSearchIndexSource implements Comparable<CmsSearchIndexSource>, Serializable { 053 054 /** The serial version id. */ 055 private static final long serialVersionUID = -3869627913906693823L; 056 057 /** The log object for this class. */ 058 private static final Log LOG = CmsLog.getLog(CmsSearchIndexSource.class); 059 060 /** A list of Cms resource types to be indexed. */ 061 private List<String> m_documentTypes; 062 063 /** The map from extraction keys to document factories. */ 064 private transient Map<String, I_CmsDocumentFactory> m_documentFactories; 065 066 /** The indexer. */ 067 private transient I_CmsIndexer m_indexer; 068 069 /** The class name of the indexer. */ 070 private String m_indexerClassName; 071 072 /** The logical key/name of this index. */ 073 private String m_name; 074 075 /** A map of optional key/value parameters. */ 076 private Map<String, String> m_params; 077 078 /** A list of Cms resources to be indexed. */ 079 private List<String> m_resourcesNames; 080 081 /** 082 * Creates a new CmsSearchIndexSource.<p> 083 */ 084 public CmsSearchIndexSource() { 085 086 m_params = new HashMap<String, String>(); 087 m_resourcesNames = new ArrayList<String>(); 088 m_documentTypes = new ArrayList<String>(); 089 m_documentFactories = new LinkedHashMap<>(); 090 } 091 092 /** 093 * Adds a parameter.<p> 094 * 095 * @param key the key/name of the parameter 096 * @param value the value of the parameter 097 */ 098 public void addConfigurationParameter(String key, String value) { 099 100 m_params.put(key, value); 101 } 102 103 /** 104 * Adds the name of a document type.<p> 105 * 106 * @param key the name of a document type to add 107 */ 108 public void addDocumentType(String key) { 109 110 m_documentTypes.add(key); 111 } 112 113 /** 114 * Adds the path of a Cms resource.<p> 115 * 116 * @param resourceName the path of a Cms resource 117 */ 118 public void addResourceName(String resourceName) { 119 120 m_resourcesNames.add(resourceName); 121 } 122 123 /** 124 * Returns <code>0</code> if the given object is an index source with the same name. <p> 125 * 126 * Note that the name of an index source has to be unique within OpenCms.<p> 127 * 128 * @param obj another index source 129 * 130 * @return <code>0</code> if the given object is an index source with the same name 131 * 132 * @see java.lang.Comparable#compareTo(java.lang.Object) 133 */ 134 public int compareTo(CmsSearchIndexSource obj) { 135 136 if (obj == this) { 137 return 0; 138 } 139 return m_name.compareTo(obj.m_name); 140 } 141 142 /** 143 * Two index sources are considered equal if their names as returned by {@link #getName()} is equal.<p> 144 * 145 * Note that the name of an index source has to be unique within OpenCms.<p> 146 * 147 * @see java.lang.Object#equals(java.lang.Object) 148 */ 149 @Override 150 public boolean equals(Object obj) { 151 152 if (obj == this) { 153 return true; 154 } 155 if (obj instanceof CmsSearchIndexSource) { 156 return m_name.equals(((CmsSearchIndexSource)obj).m_name); 157 } 158 return false; 159 } 160 161 /** 162 * Returns the document factory for given key.<p> 163 * Note that only the keys resulting from the document types for this source set are taken into account.<p> 164 * 165 * @param documentTypeKey the key for the factory to use. 166 * @return a document factory or null 167 */ 168 public I_CmsDocumentFactory getDocumentFactory(String documentTypeKey) { 169 170 return null == documentTypeKey ? null : m_documentFactories.get(documentTypeKey); 171 } 172 173 /** 174 * Returns the list of names (Strings) of the document types to be indexed.<p> 175 * 176 * @return the list of names (Strings) of the document types to be indexed 177 */ 178 public List<String> getDocumentTypes() { 179 180 return m_documentTypes; 181 } 182 183 /** 184 * Returns the indexer.<p> 185 * 186 * @return the indexer 187 */ 188 public I_CmsIndexer getIndexer() { 189 190 return m_indexer; 191 } 192 193 /** 194 * Returns the class name of the indexer.<p> 195 * 196 * @return the class name of the indexer 197 */ 198 public String getIndexerClassName() { 199 200 return m_indexerClassName; 201 } 202 203 /** 204 * Returns the logical key/name of this search index source.<p> 205 * 206 * @return the logical key/name of this search index source 207 */ 208 public String getName() { 209 210 return m_name; 211 } 212 213 /** 214 * Returns the value for a specified parameter key.<p> 215 * 216 * @param key the parameter key/name 217 * @return the value for the specified parameter key 218 */ 219 public String getParam(String key) { 220 221 return m_params.get(key); 222 } 223 224 /** 225 * Returns the map of optional key/value parameters.<p> 226 * 227 * @return the map of optional key/value parameters 228 */ 229 public Map<String, String> getParams() { 230 231 return m_params; 232 } 233 234 /** 235 * Returns the list of VFS resources to be indexed.<p> 236 * 237 * @return the list of VFS resources to be indexed 238 */ 239 public List<String> getResourcesNames() { 240 241 return m_resourcesNames; 242 } 243 244 /** 245 * Overriden to be consistents with overridden method 246 * <code>{@link #equals(Object)}</code>. 247 * 248 * @see java.lang.Object#hashCode() 249 */ 250 @Override 251 public int hashCode() { 252 253 return m_name.hashCode(); 254 } 255 256 /** 257 * Initialization for search index sources. 258 */ 259 public void init() { 260 261 m_documentFactories = OpenCms.getSearchManager().getDocumentTypeMapForTypeNames(m_documentTypes); 262 } 263 264 /** 265 * Returns <code>true</code> in case the given resource root path is contained in the list of 266 * configured resource names of this index source.<p> 267 * 268 * @param rootPath the resource root path to check 269 * 270 * @return <code>true</code> in case the given resource root path is contained in the list of 271 * configured resource names of this index source 272 * 273 * @see #getResourcesNames() 274 */ 275 public boolean isContaining(String rootPath) { 276 277 if ((rootPath != null) && (m_resourcesNames != null)) { 278 Iterator<String> i = m_resourcesNames.iterator(); 279 while (i.hasNext()) { 280 String path = i.next(); 281 if (rootPath.startsWith(path)) { 282 return true; 283 } 284 } 285 } 286 return false; 287 } 288 289 /** 290 * Returns <code>true</code> in case the given resource root path is contained in the list of 291 * configured resource names, and the given document type name is contained in the 292 * list if configured document type names of this index source.<p> 293 * 294 * @param rootPath the resource root path to check 295 * @param documentTypeKey the document type key for which the presence of a factory name has to be checked 296 * 297 * @return <code>true</code> in case the given resource root path is contained in the list of 298 * configured resource names, and the given document type name is contained in the 299 * list if configured document type names of this index source 300 * 301 * @see #isContaining(String) 302 * @see #getDocumentTypes() 303 */ 304 public boolean isIndexing(String rootPath, String documentTypeKey) { 305 306 return m_documentFactories.keySet().contains(documentTypeKey) && isContaining(rootPath); 307 } 308 309 /** 310 * Removes the name of a document type from the list of configured types of this index source.<p> 311 * 312 * @param key the name of the document type to remove 313 * 314 * @return true if the given document type name was contained before thus could be removed successfully, false otherwise 315 */ 316 public boolean removeDocumentType(String key) { 317 318 return m_documentTypes.remove(key); 319 } 320 321 /** 322 * Sets the list of document type names (Strings) to be indexed.<p> 323 * 324 * @param documentTypes the list of document type names (Strings) to be indexed 325 */ 326 public void setDocumentTypes(List<String> documentTypes) { 327 328 m_documentTypes = documentTypes; 329 } 330 331 /** 332 * Sets the class name of the indexer.<p> 333 * 334 * An Exception is thrown to allow GUI-display of wrong input.<p> 335 * 336 * @param indexerClassName the class name of the indexer 337 * 338 * @throws CmsIllegalArgumentException if the given String is not a fully qualified classname (within this Java VM) 339 */ 340 public void setIndexerClassName(String indexerClassName) throws CmsIllegalArgumentException { 341 342 try { 343 m_indexer = (I_CmsIndexer)Class.forName(indexerClassName).newInstance(); 344 m_indexerClassName = indexerClassName; 345 } catch (Exception exc) { 346 if (LOG.isWarnEnabled()) { 347 LOG.warn( 348 Messages.get().getBundle().key(Messages.LOG_INDEXER_CREATION_FAILED_1, m_indexerClassName), 349 exc); 350 } 351 throw new CmsIllegalArgumentException( 352 Messages.get().container( 353 Messages.ERR_INDEXSOURCE_INDEXER_CLASS_NAME_2, 354 indexerClassName, 355 I_CmsIndexer.class.getName())); 356 } 357 } 358 359 /** 360 * Sets the logical key/name of this search index source.<p> 361 * 362 * @param name the logical key/name of this search index source 363 * 364 * @throws CmsIllegalArgumentException if argument name is null, an empty or whitespace-only Strings 365 * or already used for another indexsource's name. 366 */ 367 public void setName(String name) throws CmsIllegalArgumentException { 368 369 if (CmsStringUtil.isEmptyOrWhitespaceOnly(name)) { 370 throw new CmsIllegalArgumentException( 371 Messages.get().container(Messages.ERR_INDEXSOURCE_CREATE_MISSING_NAME_0)); 372 } 373 // already used? Don't test this at xml-configuration time (no manager) 374 if (OpenCms.getRunLevel() > OpenCms.RUNLEVEL_2_INITIALIZING) { 375 CmsSearchManager mngr = OpenCms.getSearchManager(); 376 // don't test this if the indexsource is not new (widget invokes setName even if it was not changed) 377 if (mngr.getIndexSource(name) != this) { 378 if (mngr.getSearchIndexSources().keySet().contains(name)) { 379 throw new CmsIllegalArgumentException( 380 Messages.get().container(Messages.ERR_INDEXSOURCE_CREATE_INVALID_NAME_1, name)); 381 } 382 } 383 } 384 m_name = name; 385 } 386 387 /** 388 * Sets the map of optional key/value parameters.<p> 389 * 390 * @param params the map of optional key/value parameters 391 */ 392 public void setParams(Map<String, String> params) { 393 394 m_params = params; 395 } 396 397 /** 398 * Sets the list of Cms resources to be indexed.<p> 399 * 400 * @param resources the list of Cms resources (Strings) to be indexed 401 */ 402 public void setResourcesNames(List<String> resources) { 403 404 m_resourcesNames = resources; 405 } 406}