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.i18n.CmsMessageContainer; 032import org.opencms.jsp.CmsJspActionElement; 033import org.opencms.main.CmsIllegalStateException; 034import org.opencms.main.CmsLog; 035import org.opencms.main.OpenCms; 036import org.opencms.search.CmsSearchDocumentType; 037import org.opencms.search.CmsSearchException; 038import org.opencms.search.CmsSearchIndexSource; 039import org.opencms.search.CmsSearchManager; 040import org.opencms.search.I_CmsSearchIndex; 041import org.opencms.workplace.CmsWorkplaceSettings; 042import org.opencms.workplace.list.CmsListColumnAlignEnum; 043import org.opencms.workplace.list.CmsListColumnDefinition; 044import org.opencms.workplace.list.CmsListDefaultAction; 045import org.opencms.workplace.list.CmsListDirectAction; 046import org.opencms.workplace.list.CmsListItem; 047import org.opencms.workplace.list.CmsListItemDetails; 048import org.opencms.workplace.list.CmsListItemDetailsFormatter; 049import org.opencms.workplace.list.CmsListMetadata; 050import org.opencms.workplace.list.CmsListMultiAction; 051import org.opencms.workplace.list.CmsListOrderEnum; 052import org.opencms.workplace.tools.CmsToolDialog; 053 054import java.io.IOException; 055import java.util.ArrayList; 056import java.util.HashMap; 057import java.util.Iterator; 058import java.util.List; 059import java.util.Map; 060 061import javax.servlet.ServletException; 062import javax.servlet.http.HttpServletRequest; 063import javax.servlet.http.HttpServletResponse; 064import javax.servlet.jsp.PageContext; 065 066import org.apache.commons.logging.Log; 067 068/** 069 * A list that displays the <code>{@link org.opencms.search.CmsSearchIndexSource}</code> 070 * instances of the OpenCms system that are assigned to the 071 * <code>{@link org.opencms.search.CmsSearchIndex}</code> in the current request scope (param "searchindex") and allows to remove those sources to the 072 * current searchindex.<p> 073 * 074 * This list is no stand-alone page but has to be embedded in another dialog 075 * (see <code> {@link org.opencms.workplace.tools.searchindex.A_CmsEmbeddedListDialog}</code>. <p> 076 * 077 * @since 6.0.0 078 */ 079public class CmsSearchIndexSourceRemoveList extends A_CmsEmbeddedListDialog { 080 081 /** list action dummy id constant. */ 082 public static final String LIST_ACTION_NONE = "an"; 083 084 /** list action dummy id constant. */ 085 public static final String LIST_ACTION_REMOVESOURCE = "ars"; 086 087 /** list column id constant. */ 088 public static final String LIST_COLUMN_ICON = "ci"; 089 090 /** list column id constant. */ 091 public static final String LIST_COLUMN_INDEXER = "ca"; 092 093 /** list column id constant. */ 094 public static final String LIST_COLUMN_NAME = "cn"; 095 096 /** list column id constant. */ 097 public static final String LIST_COLUMN_REMOVESOURCE = "crs"; 098 099 /** list item detail id constant. */ 100 public static final String LIST_DETAIL_DOCTYPES = "dd"; 101 102 /** list item detail id constant. */ 103 public static final String LIST_DETAIL_RESOURCES = "dr"; 104 105 /** list id constant. */ 106 public static final String LIST_ID = "lssisr"; 107 108 /** list action id constant. */ 109 public static final String LIST_MACTION_REMOVESOURCE = "mars"; 110 111 /** list action dummy id constant. */ 112 protected static final String LIST_ACTION_REMOVESOURCE2 = LIST_ACTION_REMOVESOURCE + "2"; 113 114 /** The log object for this class. */ 115 private static final Log LOG = CmsLog.getLog(CmsSearchIndexSourceRemoveList.class); 116 117 /** Stores the value of the request parameter for the search index Name. */ 118 private String m_paramIndexName; 119 120 /** 121 * Public constructor.<p> 122 * 123 * @param jsp an initialized JSP action element 124 */ 125 public CmsSearchIndexSourceRemoveList(CmsJspActionElement jsp) { 126 127 this(jsp, LIST_ID, Messages.get().container(Messages.GUI_LIST_INDEXSOURCES_NAME_0)); 128 } 129 130 /** 131 * Public constructor.<p> 132 * 133 * @param jsp an initialized JSP action element 134 * @param listId the id of the list 135 * @param listName the list name 136 */ 137 public CmsSearchIndexSourceRemoveList(CmsJspActionElement jsp, String listId, CmsMessageContainer listName) { 138 139 this(jsp, listId, listName, LIST_COLUMN_NAME, CmsListOrderEnum.ORDER_ASCENDING, null); 140 } 141 142 /** 143 * Public constructor.<p> 144 * 145 * @param jsp an initialized JSP action element 146 * @param listId the id of the displayed list 147 * @param listName the name of the list 148 * @param sortedColId the a priory sorted column 149 * @param sortOrder the order of the sorted column 150 * @param searchableColId the column to search into 151 */ 152 public CmsSearchIndexSourceRemoveList( 153 CmsJspActionElement jsp, 154 String listId, 155 CmsMessageContainer listName, 156 String sortedColId, 157 CmsListOrderEnum sortOrder, 158 String searchableColId) { 159 160 super(jsp, listId, listName, sortedColId, sortOrder, searchableColId); 161 162 } 163 164 /** 165 * Public constructor.<p> 166 * 167 * Public constructor with JSP variables.<p> 168 * 169 * @param context the JSP page context 170 * @param req the JSP request 171 * @param res the JSP response 172 */ 173 public CmsSearchIndexSourceRemoveList(PageContext context, HttpServletRequest req, HttpServletResponse res) { 174 175 this(new CmsJspActionElement(context, req, res)); 176 } 177 178 /** 179 * @see org.opencms.workplace.list.A_CmsListDialog#executeListMultiActions() 180 */ 181 @Override 182 public void executeListMultiActions() { 183 184 CmsSearchManager searchManager = OpenCms.getSearchManager(); 185 CmsListItem listItem = getSelectedItem(); 186 String action = getParamListAction(); 187 if (action.equals(LIST_MACTION_REMOVESOURCE)) { 188 // execute the delete multiaction 189 Iterator<CmsListItem> itItems = getSelectedItems().iterator(); 190 I_CmsSearchIndex idx = searchManager.getIndex(getParamIndexName()); 191 while (itItems.hasNext()) { 192 listItem = itItems.next(); 193 if (idx.getSourceNames().size() > 1) { 194 idx.removeSourceName((String)listItem.get(LIST_COLUMN_NAME)); 195 } else { 196 break; 197 } 198 } 199 try { 200 idx.initialize(); 201 } catch (CmsSearchException e) { 202 if (LOG.isErrorEnabled()) { 203 LOG.error(e.getLocalizedMessage(), e); 204 } 205 } 206 refreshList(); 207 writeConfiguration(false); 208 } 209 listSave(); 210 } 211 212 /** 213 * @see org.opencms.workplace.list.A_CmsListDialog#executeListSingleActions() 214 */ 215 @Override 216 public void executeListSingleActions() throws IOException, ServletException { 217 218 CmsSearchManager searchManager = OpenCms.getSearchManager(); 219 CmsListItem item = getSelectedItem(); 220 String action = getParamListAction(); 221 String indexsourceName = (String)item.get(LIST_COLUMN_NAME); 222 if (action.equals(LIST_ACTION_REMOVESOURCE) || action.equals(LIST_ACTION_REMOVESOURCE2)) { 223 I_CmsSearchIndex idx = searchManager.getIndex(getParamIndexName()); 224 // Don't allow removing last index source, config file will become invalid: 225 if (idx.getSourceNames().size() > 1) { 226 idx.removeSourceName((String)item.get(LIST_COLUMN_NAME)); 227 try { 228 idx.initialize(); 229 } catch (CmsSearchException e) { 230 if (LOG.isErrorEnabled()) { 231 LOG.error(e.getLocalizedMessage(), e); 232 } 233 } 234 refreshList(); 235 writeConfiguration(false); 236 } 237 } else if (action.equals(CmsSearchIndexSourceControlList.LIST_ACTION_OVERVIEW_INDEXSOURCE)) { 238 239 // currently unused action (not triggered by a column 240 Map<String, String[]> params = new HashMap<String, String[]>(); 241 // forward to the edit indexsource screen 242 params.put(A_CmsEditIndexSourceDialog.PARAM_INDEXSOURCE, new String[] {indexsourceName}); 243 params.put(PARAM_STYLE, new String[] {CmsToolDialog.STYLE_NEW}); 244 getToolManager().jspForwardTool(this, "/searchindex/indexsources/indexsource", params); 245 246 } 247 } 248 249 /** 250 * Returns the request parameter mapped to member <code>m_searchindex</code> 251 * or null if no one was received. <p> 252 * 253 * @return the request parameter mapped to member <code>m_searchindex</code> 254 * or null if no one was received 255 */ 256 public String getParamIndexName() { 257 258 return m_paramIndexName; 259 } 260 261 /** 262 * Maps the request parameter to member <code>m_searchindex</code>. <p> 263 * 264 * @param paramSearchIndex the request parameter <code>searchindex</code> 265 * that is filled using this method. 266 */ 267 public void setParamIndexName(String paramSearchIndex) { 268 269 m_paramIndexName = paramSearchIndex; 270 } 271 272 /** 273 * @see org.opencms.workplace.list.A_CmsListDialog#fillDetails(java.lang.String) 274 */ 275 @Override 276 protected void fillDetails(String detailId) { 277 278 // get content 279 List<CmsListItem> items = getList().getAllContent(); 280 Iterator<CmsListItem> itItems = items.iterator(); 281 CmsListItem item; 282 if (detailId.equals(LIST_DETAIL_DOCTYPES)) { 283 while (itItems.hasNext()) { 284 item = itItems.next(); 285 fillDetailDocTypes(item, detailId); 286 } 287 } 288 if (detailId.equals(LIST_DETAIL_RESOURCES)) { 289 while (itItems.hasNext()) { 290 item = itItems.next(); 291 fillDetailResources(item, detailId); 292 } 293 } 294 } 295 296 /** 297 * @see org.opencms.workplace.list.A_CmsListDialog#getListItems() 298 */ 299 @Override 300 protected List<CmsListItem> getListItems() { 301 302 List<CmsListItem> result = new ArrayList<CmsListItem>(); 303 // get content 304 List<CmsSearchIndexSource> sources = searchIndexSources(); 305 Iterator<CmsSearchIndexSource> itSources = sources.iterator(); 306 CmsSearchIndexSource source; 307 while (itSources.hasNext()) { 308 source = itSources.next(); 309 CmsListItem item = getList().newItem(source.getName()); 310 item.set(LIST_COLUMN_NAME, source.getName()); 311 item.set(LIST_COLUMN_INDEXER, source.getIndexer().getClass().getName()); 312 result.add(item); 313 } 314 return result; 315 } 316 317 /** 318 * @see org.opencms.workplace.CmsWorkplace#initMessages() 319 */ 320 @Override 321 protected void initMessages() { 322 323 // add specific dialog resource bundle 324 addMessages(Messages.get().getBundleName()); 325 // add default resource bundles 326 super.initMessages(); 327 } 328 329 /** 330 * @see org.opencms.workplace.list.A_CmsListDialog#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 331 */ 332 @Override 333 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 334 335 super.initWorkplaceRequestValues(settings, request); 336 } 337 338 /** 339 * @see org.opencms.workplace.list.A_CmsListDialog#setColumns(org.opencms.workplace.list.CmsListMetadata) 340 */ 341 @Override 342 protected void setColumns(CmsListMetadata metadata) { 343 344 // create dummy column for icon 345 CmsListColumnDefinition editCol = new CmsListColumnDefinition(LIST_COLUMN_ICON); 346 editCol.setName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ICON_NAME_0)); 347 editCol.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ICON_NAME_HELP_0)); 348 editCol.setWidth("5"); 349 editCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT); 350 editCol.setSorteable(false); 351 // add dummy icon 352 CmsListDirectAction editAction = new CmsListDirectAction(LIST_ACTION_NONE); 353 editAction.setName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ICON_NAME_0)); 354 editAction.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_ICON_NAME_HELP_0)); 355 editAction.setIconPath(CmsSearchIndexList.LIST_ICON_INDEXSOURCE); 356 // disable! 357 editAction.setEnabled(false); 358 editCol.addDirectAction(editAction); 359 // add it to the list definition 360 metadata.addColumn(editCol); 361 362 // add column for remove action 363 CmsListColumnDefinition addCol = new CmsListColumnDefinition(LIST_COLUMN_REMOVESOURCE); 364 addCol.setName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_REMOVESOURCE_NAME_0)); 365 addCol.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_REMOVESOURCE_NAME_HELP_0)); 366 addCol.setWidth("5"); 367 addCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT); 368 addCol.setSorteable(false); 369 // add remove action 370 CmsListDirectAction addAction = new CmsListDirectAction(LIST_ACTION_REMOVESOURCE); 371 addAction.setName(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_ACTION_REMOVESOURCE_NAME_0)); 372 addAction.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_REMOVESOURCE_NAME_HELP_0)); 373 addAction.setIconPath(ICON_MINUS); 374 addCol.addDirectAction(addAction); 375 // add it to the list definition 376 metadata.addColumn(addCol); 377 378 // add column for name 379 CmsListColumnDefinition nameCol = new CmsListColumnDefinition(LIST_COLUMN_NAME); 380 nameCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT); 381 nameCol.setName(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_COL_NAME_0)); 382 nameCol.setWidth("55%"); 383 // add a duplicate action 384 CmsListDefaultAction defEditAction = new CmsListDefaultAction(LIST_ACTION_REMOVESOURCE2); 385 defEditAction.setName(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_ACTION_REMOVESOURCE_NAME_0)); 386 defEditAction.setHelpText(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_REMOVESOURCE_NAME_HELP_0)); 387 nameCol.addDefaultAction(defEditAction); 388 metadata.addColumn(nameCol); 389 390 // add column for analyzer 391 CmsListColumnDefinition analyzerCol = new CmsListColumnDefinition(LIST_COLUMN_INDEXER); 392 analyzerCol.setAlign(CmsListColumnAlignEnum.ALIGN_LEFT); 393 analyzerCol.setName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_COL_INDEXER_0)); 394 analyzerCol.setWidth("30%"); 395 metadata.addColumn(analyzerCol); 396 397 } 398 399 /** 400 * @see org.opencms.workplace.list.A_CmsListDialog#setIndependentActions(org.opencms.workplace.list.CmsListMetadata) 401 */ 402 @Override 403 protected void setIndependentActions(CmsListMetadata metadata) { 404 405 // add document types of index source detail help 406 CmsListItemDetails doctypeDetails = new CmsListItemDetails(LIST_DETAIL_DOCTYPES); 407 doctypeDetails.setAtColumn(LIST_COLUMN_NAME); 408 doctypeDetails.setVisible(false); 409 doctypeDetails.setShowActionName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_DETAIL_DOCTYPE_NAME_0)); 410 doctypeDetails.setShowActionHelpText( 411 Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_DETAIL_DOCTYPE_SHOW_HELP_0)); 412 doctypeDetails.setHideActionName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_DETAIL_DOCTYPE_NAME_0)); 413 doctypeDetails.setHideActionHelpText( 414 Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_DETAIL_DOCTYPE_HIDE_HELP_0)); 415 doctypeDetails.setName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_DETAIL_DOCTYPE_NAME_0)); 416 doctypeDetails.setFormatter( 417 new CmsListItemDetailsFormatter( 418 Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_DETAIL_DOCTYPE_NAME_0))); 419 metadata.addItemDetails(doctypeDetails); 420 421 // add resources of index source detail help 422 CmsListItemDetails resourceDetails = new CmsListItemDetails(LIST_DETAIL_RESOURCES); 423 resourceDetails.setAtColumn(LIST_COLUMN_NAME); 424 resourceDetails.setVisible(false); 425 resourceDetails.setShowActionName( 426 Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_DETAIL_RESOURCE_NAME_0)); 427 resourceDetails.setShowActionHelpText( 428 Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_DETAIL_RESOURCE_SHOW_HELP_0)); 429 resourceDetails.setHideActionName( 430 Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_DETAIL_RESOURCE_NAME_0)); 431 resourceDetails.setHideActionHelpText( 432 Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_DETAIL_RESOURCE_HIDE_HELP_0)); 433 resourceDetails.setName(Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_DETAIL_RESOURCE_NAME_0)); 434 resourceDetails.setFormatter( 435 new CmsListItemDetailsFormatter( 436 Messages.get().container(Messages.GUI_LIST_INDEXSOURCE_DETAIL_RESOURCE_NAME_0))); 437 metadata.addItemDetails(resourceDetails); 438 439 } 440 441 /** 442 * @see org.opencms.workplace.list.A_CmsListDialog#setMultiActions(org.opencms.workplace.list.CmsListMetadata) 443 */ 444 @Override 445 protected void setMultiActions(CmsListMetadata metadata) { 446 447 // add add multi action 448 CmsListMultiAction addMultiAction = new CmsListMultiAction(LIST_MACTION_REMOVESOURCE); 449 addMultiAction.setName(Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_MACTION_REMOVESOURCE_NAME_0)); 450 addMultiAction.setHelpText( 451 Messages.get().container(Messages.GUI_LIST_SEARCHINDEX_MACTION_REMOVESOURCE_NAME_HELP_0)); 452 addMultiAction.setIconPath(ICON_MULTI_MINUS); 453 metadata.addMultiAction(addMultiAction); 454 } 455 456 /** 457 * @see org.opencms.workplace.list.A_CmsListDialog#validateParamaters() 458 */ 459 @Override 460 protected void validateParamaters() throws Exception { 461 462 // test the needed parameters 463 if (getParamIndexName() == null) { 464 throw new CmsIllegalStateException( 465 Messages.get().container( 466 Messages.ERR_SEARCHINDEX_EDIT_MISSING_PARAM_1, 467 A_CmsEditSearchIndexDialog.PARAM_INDEXNAME)); 468 } 469 } 470 471 /** 472 * Writes the updated search configuration back to the XML 473 * configuration file and refreshes the complete list.<p> 474 * 475 * @param refresh if true, the list items are refreshed 476 */ 477 protected void writeConfiguration(boolean refresh) { 478 479 // update the XML configuration 480 OpenCms.writeConfiguration(CmsSearchConfiguration.class); 481 if (refresh) { 482 refreshList(); 483 } 484 } 485 486 /** 487 * Fills details about document types of the index source into the given item. <p> 488 * 489 * @param item the list item to fill 490 * @param detailId the id for the detail to fill 491 * 492 */ 493 private void fillDetailDocTypes(CmsListItem item, String detailId) { 494 495 CmsSearchManager searchManager = OpenCms.getSearchManager(); 496 StringBuffer html = new StringBuffer(); 497 498 // search for the corresponding CmsSearchIndexSource: 499 String idxSourceName = (String)item.get(LIST_COLUMN_NAME); 500 CmsSearchIndexSource idxSource = searchManager.getIndexSource(idxSourceName); 501 502 // get the index sources doc types 503 List<String> docTypes = idxSource.getDocumentTypes(); 504 // output of found index sources 505 Iterator<String> itDocTypes = docTypes.iterator(); 506 CmsSearchDocumentType docType; 507 html.append("<ul>\n"); 508 while (itDocTypes.hasNext()) { 509 // get the instance (instead of plain name) for more detail in future... 510 docType = searchManager.getDocumentTypeConfig(itDocTypes.next()); 511 // harden against unconfigured doctypes that are refferred to by indexsource nodes 512 if (docType != null) { 513 514 html.append(" <li>\n").append(" ").append(docType.getName()).append("\n"); 515 html.append(" </li>"); 516 } 517 } 518 519 html.append("</ul>\n"); 520 item.set(detailId, html.toString()); 521 } 522 523 /** 524 * Fills details about resource paths of the index source into the given item. <p> 525 * 526 * @param item the list item to fill 527 * @param detailId the id for the detail to fill 528 * 529 */ 530 private void fillDetailResources(CmsListItem item, String detailId) { 531 532 CmsSearchManager searchManager = OpenCms.getSearchManager(); 533 StringBuffer html = new StringBuffer(); 534 535 // search for the corresponding CmsSearchIndexSource: 536 String idxSourceName = (String)item.get(LIST_COLUMN_NAME); 537 CmsSearchIndexSource idxSource = searchManager.getIndexSource(idxSourceName); 538 539 // get the index sources resource strings 540 List<String> resources = idxSource.getResourcesNames(); 541 // output of found index sources 542 Iterator<String> itResources = resources.iterator(); 543 html.append("<ul>\n"); 544 while (itResources.hasNext()) { 545 546 html.append(" <li>\n").append(" ").append(itResources.next()).append("\n"); 547 html.append(" </li>"); 548 } 549 550 html.append("</ul>\n"); 551 552 item.set(detailId, html.toString()); 553 } 554 555 /** 556 * Returns the available search indexes of this installation. 557 * 558 * @return the available search indexes of this installation 559 */ 560 private List<CmsSearchIndexSource> searchIndexSources() { 561 562 CmsSearchManager manager = OpenCms.getSearchManager(); 563 I_CmsSearchIndex index = manager.getIndex(getParamIndexName()); 564 List<CmsSearchIndexSource> sources = index.getSources(); 565 return sources; 566 } 567 568}