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; 029 030import org.opencms.configuration.CmsSearchConfiguration; 031import org.opencms.jsp.CmsJspActionElement; 032import org.opencms.main.CmsIllegalStateException; 033import org.opencms.main.OpenCms; 034import org.opencms.search.A_CmsSearchIndex; 035import org.opencms.search.CmsSearchIndex; 036import org.opencms.search.CmsSearchIndexSource; 037import org.opencms.search.CmsSearchManager; 038import org.opencms.search.I_CmsSearchIndex; 039import org.opencms.util.CmsStringUtil; 040import org.opencms.workplace.CmsWidgetDialog; 041import org.opencms.workplace.CmsWorkplaceSettings; 042 043import java.util.ArrayList; 044import java.util.HashMap; 045import java.util.List; 046import java.util.Locale; 047import java.util.Map; 048 049import javax.servlet.http.HttpServletRequest; 050import javax.servlet.http.HttpServletResponse; 051import javax.servlet.jsp.PageContext; 052 053/** 054 * Abstract dialog class for all dialogs that work on a <code>A_CmsSearchIndex</code>.<p> 055 * 056 * The <code>{@link #PARAM_INDEXNAME}</code> ("searchindex") is supported 057 * by means of widget technology (setter / getter).<p> 058 * 059 * Also - for accessing search functionality a member <code>{@link #m_searchManager}</code> 060 * is accessible for implementations. <p> 061 * 062 * @since 6.0.0 063 */ 064public abstract class A_CmsEditSearchIndexDialog extends CmsWidgetDialog { 065 066 /** The name constraints when generating new index names. */ 067 public static final String INDEX_NAME_CONSTRAINTS = "-._~$ "; 068 069 /** localized messages Keys prefix. */ 070 public static final String KEY_PREFIX = "searchindex"; 071 072 /** Defines which pages are valid for this dialog. */ 073 public static final String[] PAGES = {"page1"}; 074 075 /** 076 * The request parameter for the search index to work with when contacting 077 * this dialog from another. <p> 078 * 079 * It may be emtpy if we are on the new index dialog (/searchindex/new-index.jsp).<p> 080 * 081 **/ 082 public static final String PARAM_INDEXNAME = "indexname"; 083 084 /** The user object that is edited on this dialog. */ 085 protected A_CmsSearchIndex m_index; 086 087 /** The search manager singleton for convenient access. **/ 088 protected CmsSearchManager m_searchManager; 089 090 /** Stores the value of the request parameter for the search index Name. */ 091 private String m_paramIndexName; 092 093 /** 094 * Public constructor with JSP action element.<p> 095 * 096 * @param jsp an initialized JSP action element 097 */ 098 public A_CmsEditSearchIndexDialog(CmsJspActionElement jsp) { 099 100 super(jsp); 101 } 102 103 /** 104 * Public constructor with JSP variables.<p> 105 * 106 * @param context the JSP page context 107 * @param req the JSP request 108 * @param res the JSP response 109 */ 110 public A_CmsEditSearchIndexDialog(PageContext context, HttpServletRequest req, HttpServletResponse res) { 111 112 this(new CmsJspActionElement(context, req, res)); 113 } 114 115 /** 116 * Writes the updated search configuration back to the XML 117 * configuration file and refreshes the complete list.<p> 118 */ 119 protected static void writeConfiguration() { 120 121 // update the XML configuration 122 OpenCms.writeConfiguration(CmsSearchConfiguration.class); 123 } 124 125 /** 126 * Commits the edited search index to the search manager.<p> 127 */ 128 @Override 129 public void actionCommit() { 130 131 List<Throwable> errors = new ArrayList<Throwable>(); 132 133 try { 134 135 // if new create it first 136 if (!m_searchManager.getSearchIndexesAll().contains(m_index)) { 137 // check the index name for invalid characters 138 CmsStringUtil.checkName( 139 m_index.getName(), 140 INDEX_NAME_CONSTRAINTS, 141 Messages.ERR_SEARCHINDEX_BAD_INDEXNAME_4, 142 Messages.get()); 143 // empty or null name and uniqueness check in add method 144 m_searchManager.addSearchIndex(m_index); 145 } 146 // check if field configuration has been updated, if thus set field configuration to the now used 147 if (!m_index.getFieldConfigurationName().equals(m_index.getFieldConfiguration().getName())) { 148 m_index.setFieldConfiguration( 149 m_searchManager.getFieldConfiguration(m_index.getFieldConfigurationName())); 150 } 151 writeConfiguration(); 152 153 } catch (Throwable t) { 154 errors.add(t); 155 } 156 157 // set the list of errors to display when saving failed 158 setCommitErrors(errors); 159 } 160 161 /** 162 * Returns the request parameter value for parameter paramSearchIndex. <p> 163 * 164 * @return the request parameter value for parameter paramSearchIndex 165 */ 166 public String getParamIndexName() { 167 168 return m_paramIndexName; 169 } 170 171 /** 172 * Sets the value of the request parameter paramSearchIndex. 173 * 174 * @param paramSearchIndex the value of the request parameter paramSearchIndex to set 175 */ 176 public void setParamIndexName(String paramSearchIndex) { 177 178 m_paramIndexName = paramSearchIndex; 179 } 180 181 /** 182 * Initializes the user object (a <code>{@link A_CmsSearchIndex}</code> instance.<p> 183 * 184 * Implementation always have to call <code>"super.defineWidgets()"</code> first as 185 * this action may only be done here (relies on filled request parameters, the next 186 * following operation <code>{@link CmsWidgetDialog#createDialogHtml()}</code> will 187 * rely on this. <p> 188 * 189 * @see org.opencms.workplace.CmsWidgetDialog#defineWidgets() 190 */ 191 @Override 192 protected void defineWidgets() { 193 194 initUserObject(); 195 setKeyPrefix(KEY_PREFIX); 196 197 } 198 199 /** 200 * @see org.opencms.workplace.CmsWidgetDialog#getPageArray() 201 */ 202 @Override 203 protected String[] getPageArray() { 204 205 return PAGES; 206 } 207 208 /** 209 * Returns the search index.<p> 210 * 211 * @return the search index 212 */ 213 protected A_CmsSearchIndex getSearchIndexIndex() { 214 215 return m_index; 216 } 217 218 /** 219 * Returns the root path of this dialog (path relative to "/system/workplace/admin").<p> 220 * 221 * @return the root path of this dialog (path relative to "/system/workplace/admin") 222 */ 223 protected String getToolPath() { 224 225 return "/searchindex"; 226 } 227 228 /** 229 * @see org.opencms.workplace.CmsWorkplace#initMessages() 230 */ 231 @Override 232 protected void initMessages() { 233 234 // add specific dialog resource bundle 235 addMessages(Messages.get().getBundleName()); 236 // add default resource bundles 237 super.initMessages(); 238 } 239 240 /** 241 * Initializes the user object to work with depending on the dialog state and request parameters.<p> 242 * 243 * Two initializations of the user object on first dialog call are possible: 244 * <ul> 245 * <li>edit an existing search index</li> 246 * <li>create a new search index with default initialization</li> 247 * </ul> 248 */ 249 protected void initUserObject() { 250 251 try { 252 I_CmsSearchIndex idx = m_searchManager.getIndex(getParamIndexName()); 253 m_index = idx instanceof CmsSearchIndex ? (CmsSearchIndex)idx : null; 254 if (m_index == null) { 255 m_index = createDummySearchIndex(); 256 } 257 } catch (Exception e) { 258 m_index = createDummySearchIndex(); 259 } 260 } 261 262 /** 263 * Overridden to initialize the internal <code>CmsSearchManager</code> before initWorkplaceRequestValues -> 264 * defineWidgets -> will access it (NPE). <p> 265 * 266 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceMembers(org.opencms.jsp.CmsJspActionElement) 267 */ 268 @Override 269 protected void initWorkplaceMembers(CmsJspActionElement jsp) { 270 271 m_searchManager = OpenCms.getSearchManager(); 272 super.initWorkplaceMembers(jsp); 273 } 274 275 /** 276 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 277 */ 278 @Override 279 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 280 281 // initialize parameters and dialog actions in super implementation 282 super.initWorkplaceRequestValues(settings, request); 283 284 // save the current search index 285 @SuppressWarnings("unchecked") 286 Map<String, A_CmsSearchIndex> dialogObject = (Map<String, A_CmsSearchIndex>)getDialogObject(); 287 if (dialogObject == null) { 288 dialogObject = new HashMap<String, A_CmsSearchIndex>(); 289 dialogObject.put(PARAM_INDEXNAME, m_index); 290 setDialogObject(dialogObject); 291 } 292 293 } 294 295 /** 296 * Checks if the new search index dialog has to be displayed.<p> 297 * 298 * @return <code>true</code> if the new search index dialog has to be displayed 299 */ 300 protected boolean isNewSearchIndex() { 301 302 return DIALOG_INITIAL.equals(getParamAction()); 303 } 304 305 /** 306 * @see org.opencms.workplace.CmsWidgetDialog#validateParamaters() 307 */ 308 @Override 309 protected void validateParamaters() throws Exception { 310 311 if (!isNewSearchIndex()) { 312 // test the needed parameters: if initial we have "indexname", if from same widget we have name.0 313 if ((getParamIndexName() == null) && (getJsp().getRequest().getParameter("name.0") == null)) { 314 throw new CmsIllegalStateException( 315 Messages.get().container(Messages.ERR_SEARCHINDEX_EDIT_MISSING_PARAM_1, PARAM_INDEXNAME)); 316 } 317 } 318 } 319 320 /** 321 * Creates a dummy index source.<p> 322 * 323 * @return the dummy search index source 324 */ 325 private CmsSearchIndexSource createDummyIndexSource() { 326 327 CmsSearchIndexSource result = new CmsSearchIndexSource(); 328 result.setName("default"); 329 result.setIndexerClassName("org.opencms.search.CmsVfsIndexer"); 330 result.addDocumentType("html"); 331 result.addDocumentType("generic"); 332 result.addDocumentType("pdf"); 333 // add search index source to config: 334 m_searchManager.addSearchIndexSource(result); 335 return result; 336 } 337 338 /** 339 * Creates a "dummy" search index that is not linked to the search manager and has 340 * a <code>null</code> name property that will be used for being filled with 341 * the widget bean technology. <p> 342 * 343 * @return a "dummy" search index that is not linked to the search manager and has 344 * a <code>null</code> name property that will be used for being filled with 345 * the widget bean technology 346 */ 347 private CmsSearchIndex createDummySearchIndex() { 348 349 CmsSearchIndex result = new CmsSearchIndex(); 350 result.setLocale(Locale.ENGLISH); 351 result.setProject("Online"); 352 result.setRebuildMode("auto"); 353 354 // find default source 355 Map<String, CmsSearchIndexSource> sources = m_searchManager.getSearchIndexSources(); 356 if (sources.isEmpty()) { 357 CmsSearchIndexSource source = createDummyIndexSource(); 358 sources.put(source.getName(), source); 359 } 360 result.addSourceName(sources.keySet().iterator().next()); 361 362 return result; 363 } 364}