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, 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.galleries; 029 030import org.opencms.db.CmsResourceState; 031import org.opencms.file.CmsObject; 032import org.opencms.file.CmsProperty; 033import org.opencms.file.CmsPropertyDefinition; 034import org.opencms.file.CmsResource; 035import org.opencms.file.CmsResourceFilter; 036import org.opencms.file.types.CmsResourceTypeFolderExtended; 037import org.opencms.i18n.CmsMessageContainer; 038import org.opencms.json.JSONArray; 039import org.opencms.json.JSONException; 040import org.opencms.json.JSONObject; 041import org.opencms.jsp.CmsJspActionElement; 042import org.opencms.lock.CmsLock; 043import org.opencms.main.CmsException; 044import org.opencms.main.CmsLog; 045import org.opencms.main.CmsRuntimeException; 046import org.opencms.main.OpenCms; 047import org.opencms.relations.CmsCategory; 048import org.opencms.relations.CmsCategoryService; 049import org.opencms.security.CmsPermissionSet; 050import org.opencms.staticexport.CmsLinkManager; 051import org.opencms.util.CmsStringUtil; 052import org.opencms.workplace.CmsDialog; 053import org.opencms.workplace.CmsWorkplace; 054import org.opencms.workplace.CmsWorkplaceManager; 055import org.opencms.workplace.CmsWorkplaceSettings; 056 057import java.io.IOException; 058import java.util.ArrayList; 059import java.util.Collections; 060import java.util.Iterator; 061import java.util.List; 062import java.util.Map; 063import java.util.TreeMap; 064 065import javax.servlet.http.HttpServletRequest; 066import javax.servlet.http.HttpServletResponse; 067import javax.servlet.http.HttpSession; 068import javax.servlet.jsp.JspWriter; 069import javax.servlet.jsp.PageContext; 070 071import org.apache.commons.logging.Log; 072 073/** 074 * Provides the general helper methods to generate the content of a gallery dialog used in the XML content editors, 075 * WYSIWYG editors and context menu. It <p> 076 * 077 * It is also used for AJAX requests to dynamically switch galleries or categories and get additional information 078 * for the currently active item of the dialog.<p> 079 * 080 * Extend this class for every gallery type (e.g. image gallery or download gallery) to build.<p> 081 * 082 * @since 7.5.0 083 */ 084public abstract class A_CmsAjaxGallery extends CmsDialog { 085 086 /** Request parameter value for the action: change the item link url value. */ 087 public static final String DIALOG_CHANGEITEMLINKURL = "changeitemlinkurl"; 088 089 /** Request parameter value for the action: change the item title property value. */ 090 public static final String DIALOG_CHANGEITEMTITLE = "changeitemtitle"; 091 092 /** Request parameter value for the action: get the currently active item object. */ 093 public static final String DIALOG_GETACTIVEITEM = "getactiveitem"; 094 095 /** Request parameter value for the action: get the category selection list. */ 096 public static final String DIALOG_GETCATEGORIES = "getcategories"; 097 098 /** Request parameter value for the action: get the gallery selection list. */ 099 public static final String DIALOG_GETGALLERIES = "getgalleries"; 100 101 /** Request parameter value for the action: get a specific gallery. */ 102 public static final String DIALOG_GETGALLERY = "getgallery"; 103 104 /** Request parameter value for the action: get the items for a gallery or category. */ 105 public static final String DIALOG_GETITEMS = "getitems"; 106 107 /** Request parameter value for the action: list gallery items. */ 108 public static final String DIALOG_LIST = "list"; 109 110 /** The list mode name "category" for getting the items. */ 111 public static final String LISTMODE_CATEGORY = "category"; 112 113 /** The list mode name "gallery" for getting the items. */ 114 public static final String LISTMODE_GALLERY = "gallery"; 115 116 /** Request parameter value for the dialog mode: editor. */ 117 public static final String MODE_EDITOR = "editor"; 118 119 /** Request parameter value for the dialog mode: view. */ 120 public static final String MODE_VIEW = "view"; 121 122 /** Request parameter value for the dialog mode: widget. */ 123 public static final String MODE_WIDGET = "widget"; 124 125 /** Request parameter name for the dialog mode (widget or editor). */ 126 public static final String PARAM_DIALOGMODE = "dialogmode"; 127 128 /** Request parameter name for the edited resource. */ 129 public static final String PARAM_EDITEDRESOURCE = "editedresource"; 130 131 /** Request parameter name for the input field id. */ 132 public static final String PARAM_FIELDID = "fieldid"; 133 134 /** Request parameter name for the gallery path. */ 135 public static final String PARAM_GALLERYPATH = "gallerypath"; 136 137 /** Request parameter name for the active item path. */ 138 public static final String PARAM_ITEMPATH = "itempath"; 139 140 /** Request parameter name for the dialog initialization parameters. */ 141 public static final String PARAM_PARAMS = "params"; 142 143 /** Request parameter name for the startup folder. */ 144 public static final String PARAM_STARTUPFOLDER = "startupfolder"; 145 146 /** Request parameter name for the startup type. */ 147 public static final String PARAM_STARTUPTYPE = "startuptype"; 148 149 /** The galleries path in the workplace containing the JSPs. */ 150 public static final String PATH_GALLERIES = CmsWorkplace.VFS_PATH_WORKPLACE + "galleries/"; 151 152 /** Value that is returned if no result was found. */ 153 public static final String RETURNVALUE_NONE = "none"; 154 155 /** The log object for this class. */ 156 private static final Log LOG = CmsLog.getLog(A_CmsAjaxGallery.class); 157 158 /** The optional parameters for the gallery from the XML configuration. */ 159 protected String m_galleryTypeParams; 160 161 /** The gallery items to display. */ 162 private List<CmsResource> m_galleryItems; 163 164 /** The dialog mode the gallery is running in. */ 165 private String m_paramDialogMode; 166 167 /** The input field id that is required when in widget mode. */ 168 private String m_paramFieldId; 169 170 /** The current gallery path. */ 171 private String m_paramGalleryPath; 172 173 /** The list mode to get the item either from a gallery or by a category. */ 174 private String m_paramListMode; 175 176 /** The value of the property (current property definition: Title). */ 177 private String m_paramPropertyValue; 178 179 /** The gallery base resource type. */ 180 private CmsResourceTypeFolderExtended m_resourceType; 181 182 /** 183 * Public empty constructor, required for {@link A_CmsAjaxGallery#createInstance(String, CmsJspActionElement)}.<p> 184 */ 185 public A_CmsAjaxGallery() { 186 187 this(null); 188 } 189 190 /** 191 * Public constructor with JSP action element.<p> 192 * 193 * @param jsp an initialized JSP action element 194 */ 195 public A_CmsAjaxGallery(CmsJspActionElement jsp) { 196 197 super(jsp); 198 // perform other initialization 199 init(); 200 201 } 202 203 /** 204 * Public constructor with JSP variables.<p> 205 * 206 * @param context the JSP page context 207 * @param req the JSP request 208 * @param res the JSP response 209 */ 210 public A_CmsAjaxGallery(PageContext context, HttpServletRequest req, HttpServletResponse res) { 211 212 this(new CmsJspActionElement(context, req, res)); 213 } 214 215 /** 216 * Creates a new gallery instance of the given gallery type name.<p> 217 * 218 * @param galleryTypeName the gallery type name to create the instance for 219 * @param jsp an initialized JSP action element 220 * 221 * @return a new gallery instance of the given gallery type name 222 */ 223 public static A_CmsAjaxGallery createInstance(String galleryTypeName, CmsJspActionElement jsp) { 224 225 if (jsp != null) { 226 // must have a valid JSP in order to read from the user session 227 HttpSession session = jsp.getRequest().getSession(); 228 // lookup the workplace settings 229 CmsWorkplaceSettings settings = (CmsWorkplaceSettings)session.getAttribute( 230 CmsWorkplaceManager.SESSION_WORKPLACE_SETTINGS); 231 if (settings != null) { 232 if (CmsStringUtil.isEmpty(galleryTypeName)) { 233 // look up the gallery type from the settings 234 galleryTypeName = settings.getGalleryType(); 235 } else { 236 // store the last used gallery type name 237 settings.setGalleryType(galleryTypeName); 238 } 239 } 240 } 241 // get the gallery class name for the type 242 A_CmsAjaxGallery template = OpenCms.getWorkplaceManager().getGalleries().get(galleryTypeName); 243 244 if (template == null) { 245 // requested gallery type is not configured 246 CmsMessageContainer message; 247 if (jsp == null) { 248 message = Messages.get().container(Messages.LOG_UNKNOWN_GALLERY_TYPE_REQ_1, galleryTypeName); 249 } else { 250 message = Messages.get().container( 251 Messages.LOG_UNKNOWN_GALLERY_TYPE_REQ_JSP_2, 252 galleryTypeName, 253 jsp.info("opencms.request.element.uri")); 254 } 255 LOG.error(message.key()); 256 throw new CmsRuntimeException(message); 257 } 258 259 try { 260 // first get the class of the gallery 261 Class<?> galleryClass = Class.forName(template.getResourceType().getFolderClassName()); 262 // create a new instance and cast to a gallery 263 A_CmsAjaxGallery galleryInstance = (A_CmsAjaxGallery)galleryClass.newInstance(); 264 // set the type name and id 265 galleryInstance.m_resourceType = template.getResourceType(); 266 galleryInstance.m_galleryTypeParams = template.getResourceType().getFolderClassParams(); 267 // initialize the members 268 galleryInstance.initWorkplaceMembers(jsp); 269 // perform other initialization 270 galleryInstance.init(); 271 // return the result 272 return galleryInstance; 273 } catch (Exception e) { 274 // requested type is not configured 275 CmsMessageContainer message; 276 if (jsp == null) { 277 message = Messages.get().container( 278 Messages.LOG_CREATE_GALLERY_INSTANCE_FAILED_2, 279 template.getResourceType().getFolderClassName(), 280 galleryTypeName); 281 } else { 282 message = Messages.get().container( 283 Messages.LOG_CREATE_GALLERY_INSTANCE_FAILED_JSP_3, 284 template.getResourceType().getFolderClassName(), 285 galleryTypeName, 286 jsp.info("opencms.request.element.uri")); 287 } 288 LOG.error(message.key()); 289 throw new CmsRuntimeException(message); 290 } 291 } 292 293 /** 294 * Returns a list of galleries which have the required gallery type id.<p> 295 * 296 * @param galleryTypeId type id of the gallery 297 * @param cms the initialized CmsObject for the current user 298 * @return a list of galleries 299 */ 300 public static List<CmsResource> getGalleries(int galleryTypeId, CmsObject cms) { 301 302 List<CmsResource> galleries = new ArrayList<CmsResource>(); 303 try { 304 // get the galleries of the current site 305 galleries = cms.readResources("/", CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(galleryTypeId)); 306 } catch (CmsException e) { 307 // error reading resources with filter 308 LOG.error(e.getLocalizedMessage(), e); 309 } 310 311 // if the current site is NOT the root site - add all other galleries from the system path 312 if (!cms.getRequestContext().getSiteRoot().equals("")) { 313 List<CmsResource> systemGalleries = null; 314 try { 315 // get the galleries in the /system/ folder 316 systemGalleries = cms.readResources( 317 CmsWorkplace.VFS_PATH_SYSTEM, 318 CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireType(galleryTypeId)); 319 } catch (CmsException e) { 320 // error reading resources with filter 321 LOG.error(e.getLocalizedMessage(), e); 322 } 323 324 if ((systemGalleries != null) && (systemGalleries.size() > 0)) { 325 // add the found system galleries to the result 326 galleries.addAll(systemGalleries); 327 } 328 } 329 330 // return the found galleries 331 return galleries; 332 } 333 334 /** 335 * Initializes the gallery dialog before redirecting.<p> 336 * 337 * @param wp the workplace object 338 */ 339 public static void initGallery(CmsDialog wp) { 340 341 // 1. get "gallerytypename" by reading the folderpath 342 String galleryTypeName = null; 343 if (wp.useNewStyle()) { 344 galleryTypeName = CmsResource.getName(CmsResource.getFolderPath(wp.getAdminTool().getHandler().getLink())); 345 } else { 346 galleryTypeName = CmsResource.getName(CmsResource.getFolderPath(wp.getJsp().getRequestContext().getUri())); 347 } 348 if (galleryTypeName.endsWith("/")) { 349 galleryTypeName = galleryTypeName.substring(0, galleryTypeName.length() - 1); 350 } 351 if (!galleryTypeName.equals("commons")) { 352 // 2. set in user settings 353 wp.getSettings().setGalleryType(galleryTypeName); 354 } 355 } 356 357 /** 358 * Called from the JSP that is used for the AJAX requests to OpenCms.<p> 359 */ 360 public void displayDialog() { 361 362 if (DIALOG_CHANGEITEMTITLE.equals(getParamAction())) { 363 // build the JSON object for the current item with changed title property 364 changeItemTitle(getJsp().getRequest().getParameter(PARAM_ITEMPATH)); 365 } else if (DIALOG_CHANGEITEMLINKURL.equals(getParamAction())) { 366 // build the JSON object for the current item with changed resource content (CmsResourcePointer) 367 changeItemLinkUrl(getJsp().getRequest().getParameter(PARAM_ITEMPATH)); 368 } else if (DIALOG_GETCATEGORIES.equals(getParamAction())) { 369 // get the available categories as JSON array 370 buildJsonCategoryList(); 371 } else if (DIALOG_GETGALLERIES.equals(getParamAction())) { 372 // get the available galleries as JSON array 373 buildJsonGalleryList(); 374 } else if (DIALOG_GETGALLERY.equals(getParamAction())) { 375 // get the desired gallery as JSON object 376 buildJsonGalleryItem(getJsp().getRequest().getParameter(PARAM_GALLERYPATH)); 377 } else if (DIALOG_GETITEMS.equals(getParamAction())) { 378 if (LISTMODE_CATEGORY.equals(getParamListMode())) { 379 // get the items of selected category 380 buildJsonResourceItems(getCategoryItems(), null); 381 } else { 382 // get the items of a selected gallery 383 buildJsonResourceItems(getGalleryItems(), getParamGalleryPath()); 384 } 385 } else if (DIALOG_GETACTIVEITEM.equals(getParamAction())) { 386 // build the JSON object for the currently active item 387 buildJsonActiveItem(getJsp().getRequest().getParameter(PARAM_ITEMPATH)); 388 } 389 } 390 391 /** 392 * Returns a list of galleries which have the required gallery type id.<p> 393 * 394 * @return a list of galleries 395 */ 396 public List<CmsResource> getGalleries() { 397 398 return getGalleries(getGalleryTypeId(), getCms()); 399 } 400 401 /** 402 * Returns a list of gallery items (resources) for the currently selected gallery and resource type id.<p> 403 * 404 * @return a list of gallery items (resources) 405 */ 406 public List<CmsResource> getGalleryItems() { 407 408 if (m_galleryItems == null) { 409 // gallery items have not been read yet 410 int resTypeId = getGalleryItemsTypeId(); 411 if (CmsStringUtil.isNotEmpty(getParamGalleryPath())) { 412 try { 413 // set last used gallery in settings to current gallery 414 getSettings().setLastUsedGallery("" + getGalleryTypeId(), getParamGalleryPath()); 415 CmsResourceFilter filter; 416 if (resTypeId == -1) { 417 // filter all resources that are files 418 filter = CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireTimerange().addRequireFile(); 419 } else { 420 // filter all resources of the required type 421 filter = CmsResourceFilter.ONLY_VISIBLE_NO_DELETED.addRequireTimerange().addRequireType( 422 resTypeId); 423 } 424 m_galleryItems = getCms().readResources(getParamGalleryPath(), filter, false); 425 } catch (CmsException e) { 426 // error reading resources 427 LOG.error(e.getLocalizedMessage(), e); 428 } catch (NullPointerException e) { 429 // ignore this exception 430 } 431 } 432 } 433 return m_galleryItems; 434 } 435 436 /** 437 * Returns the type id of the gallery items that should be listed.<p> 438 * 439 * In case of downloadgallery use '-1' to list all resources excluding folders.<p> 440 * 441 * @return the type id of the gallery items that should be listed 442 */ 443 public abstract int getGalleryItemsTypeId(); 444 445 /** 446 * Returns the type id of this gallery instance.<p> 447 * 448 * @return the type id of this gallery instance 449 */ 450 public abstract int getGalleryTypeId(); 451 452 /** 453 * Returns the type name of this gallery instance.<p> 454 * 455 * @return the type name of this gallery instance 456 */ 457 public abstract String getGalleryTypeName(); 458 459 /** 460 * Returns the (optional) parameters of this gallery instance.<p> 461 * 462 * @return the (optional) parameters of this gallery instance 463 */ 464 public String getGalleryTypeParams() { 465 466 return m_galleryTypeParams; 467 } 468 469 /** 470 * Returns the current mode of the dialog.<p> 471 * 472 * This is necessary to distinguish between widget mode, view mode and editor mode.<p> 473 * 474 * @return the current mode of the dialog 475 */ 476 public String getParamDialogMode() { 477 478 if (m_paramDialogMode == null) { 479 return ""; 480 } 481 return m_paramDialogMode; 482 } 483 484 /** 485 * Returns the input field ID when in widget mode.<p> 486 * 487 * @return the input field ID 488 */ 489 public String getParamFieldId() { 490 491 return m_paramFieldId; 492 } 493 494 /** 495 * Returns the path of the gallery to display.<p> 496 * 497 * @return the path of the gallery to display 498 */ 499 public String getParamGalleryPath() { 500 501 if (CmsStringUtil.isEmpty(m_paramGalleryPath)) { 502 m_paramGalleryPath = ""; 503 } 504 return m_paramGalleryPath; 505 } 506 507 /** 508 * Returns the list mode for getting the items, either {@link #LISTMODE_CATEGORY} or {@link #LISTMODE_GALLERY}.<p> 509 * 510 * @return the list mode for getting the item 511 */ 512 public String getParamListMode() { 513 514 return m_paramListMode; 515 } 516 517 /** 518 * Returns the property value parameter.<p> 519 * 520 * @return the property value parameter 521 */ 522 public String getParamPropertyValue() { 523 524 return m_paramPropertyValue; 525 } 526 527 /** 528 * Returns the extended folder resource type this gallery is based on.<p> 529 * 530 * @return the extended folder resource type this gallery is based on 531 */ 532 public CmsResourceTypeFolderExtended getResourceType() { 533 534 return m_resourceType; 535 } 536 537 /** 538 * Initialization method that is called after the gallery instance has been created.<p> 539 * 540 * It can be overwritten in the inherited class, e.g. {@link org.opencms.workplace.galleries.CmsAjaxImageGallery#init()}.<p> 541 */ 542 public void init() { 543 544 // default gallery does not require initialization 545 } 546 547 /** 548 * Returns if the dialog mode is the "editor" mode.<p> 549 * 550 * @return <code>true</code> if the dialog mode is the "editor" mode, otherwise <code>false</code> 551 */ 552 public boolean isModeEditor() { 553 554 return MODE_EDITOR.equals(getParamDialogMode()); 555 } 556 557 /** 558 * Returns if the dialog mode is the "view" mode.<p> 559 * 560 * @return <code>true</code> if the dialog mode is the "view" mode, otherwise <code>false</code> 561 */ 562 public boolean isModeView() { 563 564 return MODE_VIEW.equals(getParamDialogMode()); 565 } 566 567 /** 568 * Returns if the dialog mode is the "widget" mode.<p> 569 * 570 * @return <code>true</code> if the dialog mode is the "editor" mode, otherwise <code>false</code> 571 */ 572 public boolean isModeWidget() { 573 574 return MODE_WIDGET.equals(getParamDialogMode()); 575 } 576 577 /** 578 * Sets the current mode of the dialog.<p> 579 * 580 * This is necessary to distinguish between widget mode and editor mode.<p> 581 * 582 * @param dialogMode the current mode of the dialog 583 */ 584 public void setParamDialogMode(String dialogMode) { 585 586 m_paramDialogMode = dialogMode; 587 } 588 589 /** 590 * Sets the input field ID if in widget mode.<p> 591 * 592 * @param fieldId the input field ID 593 */ 594 public void setParamFieldId(String fieldId) { 595 596 m_paramFieldId = fieldId; 597 } 598 599 /** 600 * Sets the path of the gallery to display.<p> 601 * 602 * @param galleryPath the path of the gallery to display 603 */ 604 public void setParamGalleryPath(String galleryPath) { 605 606 m_paramGalleryPath = galleryPath; 607 } 608 609 /** 610 * Sets the list mode for getting the items, either {@link #LISTMODE_CATEGORY} or {@link #LISTMODE_GALLERY}.<p> 611 * 612 * @param paramListMode the list mode for getting the items 613 */ 614 public void setParamListMode(String paramListMode) { 615 616 m_paramListMode = paramListMode; 617 } 618 619 /** 620 * Sets the property value parameter.<p> 621 * 622 * @param paramPropertyValue the property value parameter to set 623 */ 624 public void setParamPropertyValue(String paramPropertyValue) { 625 626 m_paramPropertyValue = paramPropertyValue; 627 } 628 629 /** 630 * Sets the extended folder resource type this gallery is based on.<p> 631 * 632 * @param type the extended folder resource type this gallery is based on 633 */ 634 public void setResourceType(CmsResourceTypeFolderExtended type) { 635 636 m_resourceType = type; 637 } 638 639 /** 640 * Builds the Javascript to set the currently active item object.<p> 641 * 642 * @param itemUrl the URL of the currently selected item 643 */ 644 protected void buildJsonActiveItem(String itemUrl) { 645 646 if (itemUrl.startsWith(OpenCms.getSiteManager().getWorkplaceServer())) { 647 // remove workplace server prefix 648 itemUrl = itemUrl.substring(OpenCms.getSiteManager().getWorkplaceServer().length()); 649 } 650 // remove context prefix to read resource from VFS 651 itemUrl = CmsLinkManager.removeOpenCmsContext(itemUrl); 652 try { 653 JspWriter out = getJsp().getJspContext().getOut(); 654 if (getCms().existsResource(itemUrl)) { 655 try { 656 out.print(buildJsonItemObject(getCms().readResource(itemUrl))); 657 } catch (CmsException e) { 658 // can not happen in theory, because we used existsResource() before... 659 } 660 } else { 661 out.print(RETURNVALUE_NONE); 662 } 663 } catch (IOException e) { 664 if (LOG.isErrorEnabled()) { 665 LOG.error(e.getLocalizedMessage(), e); 666 } 667 } 668 } 669 670 /** 671 * Builds the JSON code for the category list as JSON array.<p> 672 */ 673 protected void buildJsonCategoryList() { 674 675 CmsCategoryService catService = CmsCategoryService.getInstance(); 676 List<CmsCategory> foundCategories = Collections.emptyList(); 677 String editedResource = null; 678 if (CmsStringUtil.isNotEmpty(getParamResource())) { 679 editedResource = getParamResource(); 680 } 681 try { 682 foundCategories = catService.readCategories(getCms(), "", true, editedResource); 683 } catch (CmsException e) { 684 // error reading categories 685 } 686 687 // the next lines sort the categories according to their path 688 Map<String, CmsCategory> sorted = new TreeMap<String, CmsCategory>(); 689 690 Iterator<CmsCategory> i = foundCategories.iterator(); 691 while (i.hasNext()) { 692 CmsCategory category = i.next(); 693 String categoryPath = category.getPath(); 694 if (sorted.get(categoryPath) != null) { 695 continue; 696 } 697 sorted.put(categoryPath, category); 698 } 699 700 foundCategories = new ArrayList<CmsCategory>(sorted.values()); 701 JSONArray categories = new JSONArray(); 702 i = foundCategories.iterator(); 703 while (i.hasNext()) { 704 CmsCategory cat = i.next(); 705 706 JSONObject jsonObj = new JSONObject(); 707 try { 708 // 1: category title 709 jsonObj.put("title", cat.getTitle()); 710 // 2: category path 711 jsonObj.put("path", cat.getPath()); 712 // 3: category root path 713 jsonObj.put("rootpath", cat.getRootPath()); 714 // 4 category level 715 jsonObj.put("level", CmsResource.getPathLevel(cat.getPath())); 716 // 4: active flag 717 jsonObj.put("active", false); 718 categories.put(jsonObj); 719 } catch (JSONException e) { 720 // TODO: error handling 721 } 722 } 723 JspWriter out = getJsp().getJspContext().getOut(); 724 try { 725 out.print(categories.toString()); 726 } catch (IOException e) { 727 if (LOG.isErrorEnabled()) { 728 LOG.error(e.getLocalizedMessage(), e); 729 } 730 } 731 732 } 733 734 /** 735 * Creates a JSON object with the information found on the given gallery URL.<p> 736 * 737 * @param galleryUrl the given gallery URL 738 */ 739 protected void buildJsonGalleryItem(String galleryUrl) { 740 741 try { 742 JspWriter out = getJsp().getJspContext().getOut(); 743 if (getCms().existsResource(galleryUrl)) { 744 JSONObject jsonObj = new JSONObject(); 745 try { 746 CmsResource res = getCms().readResource(galleryUrl); 747 String path = getCms().getSitePath(res); 748 // read the gallery title 749 String title = getCms().readPropertyObject( 750 res, 751 CmsPropertyDefinition.PROPERTY_TITLE, 752 false).getValue(""); 753 try { 754 // 1: gallery title 755 jsonObj.put("title", title); 756 // 2: gallery path 757 jsonObj.put("path", path); 758 // 3: active flag 759 jsonObj.put("active", true); 760 out.print(jsonObj); 761 } catch (JSONException e) { 762 if (LOG.isErrorEnabled()) { 763 LOG.error(e.getLocalizedMessage(), e); 764 } 765 } 766 } catch (CmsException e) { 767 // error reading title property 768 if (LOG.isErrorEnabled()) { 769 LOG.error(e.getLocalizedMessage(), e); 770 } 771 } 772 } else { 773 out.print(RETURNVALUE_NONE); 774 } 775 } catch (IOException e) { 776 if (LOG.isErrorEnabled()) { 777 LOG.error(e.getLocalizedMessage(), e); 778 } 779 } 780 } 781 782 /** 783 * Builds the JSON code for the gallery list as JSON array.<p> 784 */ 785 protected void buildJsonGalleryList() { 786 787 String lastUsed = getSettings().getLastUsedGallery("" + getGalleryTypeId()); 788 // check the value of last Used, if gallery is opened for the first time 789 if (CmsStringUtil.isEmpty(lastUsed)) { 790 // start gallery settings for this gallery type for the current user 791 String startGallerySetting = getSettings().getUserSettings().getStartGallery( 792 getGalleryTypeName(), 793 getCms()); 794 if (startGallerySetting != null) { 795 // handle the case, "global settings" are selected 796 if (startGallerySetting.equals(CmsWorkplace.INPUT_DEFAULT)) { 797 // get selected value from workplace xml settings 798 String preselectedValue = OpenCms.getWorkplaceManager().getDefaultUserSettings().getStartGallery( 799 getGalleryTypeName()); 800 if (preselectedValue != null) { 801 startGallerySetting = preselectedValue; 802 } 803 } 804 // checks if the resource exists 805 String sitePath = getCms().getRequestContext().removeSiteRoot(startGallerySetting); 806 if (getCms().existsResource(sitePath)) { 807 lastUsed = sitePath; 808 } 809 } 810 } 811 JSONArray galleries = new JSONArray(); 812 Iterator<CmsResource> i = getGalleries().iterator(); 813 boolean isFirst = true; 814 while (i.hasNext()) { 815 CmsResource res = i.next(); 816 String path = getCms().getSitePath(res); 817 JSONObject jsonObj = new JSONObject(); 818 // 1: gallery title 819 String title = ""; 820 try { 821 // read the gallery title 822 title = getCms().readPropertyObject(path, CmsPropertyDefinition.PROPERTY_TITLE, false).getValue(""); 823 } catch (CmsException e) { 824 // error reading title property 825 if (LOG.isErrorEnabled()) { 826 LOG.error(e.getLocalizedMessage(), e); 827 } 828 } 829 try { 830 jsonObj.put("title", title); 831 // 2: gallery path 832 jsonObj.put("path", path); 833 // 3: active flag 834 boolean active = false; 835 if ((CmsStringUtil.isEmpty(lastUsed) && isFirst) || path.equals(lastUsed)) { 836 // TODO: adjust logic to get active gallery 837 active = true; 838 } 839 jsonObj.put("active", active); 840 galleries.put(jsonObj); 841 } catch (JSONException e) { 842 if (LOG.isErrorEnabled()) { 843 LOG.error(e.getLocalizedMessage(), e); 844 } 845 } 846 isFirst = false; 847 } 848 JspWriter out = getJsp().getJspContext().getOut(); 849 try { 850 out.print(galleries.toString()); 851 } catch (IOException e) { 852 if (LOG.isErrorEnabled()) { 853 LOG.error(e.getLocalizedMessage(), e); 854 } 855 } 856 } 857 858 /** 859 * Fills the JSON object with the information used for all resource types.<p> 860 * 861 * <ul> 862 * <li><code>sitepath</code>: site path to the resource.</li> 863 * <li><code>linkpath</code>: substituted url of the resource.</li> 864 * <li><code>title</code>: title property of the resource.</li> 865 * <li><code>size</code>: size of the resource in kb.</li> 866 * <li><code>datecreated</code>: the creation date of the resource.</li> 867 * <li><code>datelastmodified</code>: the modification date.</li> 868 * <li><code>state</code>: the state of the resource, new or changed.</li> 869 * <li><code>lockedby</code>: indicates if the resource is locked by another user.</li> 870 * <li><code>editable</code>: editable flag to determine if item is editable and can be lockes by the user.</li> 871 * <li><code>writepermission</code>: flag to indicate if the user has write permissions for given resource.</li> 872 * <li><code>directpublish</code>: flag to indicate if the user has write direct publish permission for given resource.</li> 873 * <li><code>description</code>: description property of the resource.</li> 874 * </ul> 875 * 876 * @param jsonObj containing information used by all possible resource 877 * @param res the resource to create the object from 878 * @param sitePath site path to the object 879 */ 880 protected void buildJsonItemCommonPart(JSONObject jsonObj, CmsResource res, String sitePath) { 881 882 try { 883 // 1: file item site path 884 jsonObj.put("sitepath", sitePath); 885 // 2: substituted file item url 886 jsonObj.put("linkpath", getJsp().link(sitePath)); 887 // 3: file item title 888 jsonObj.put( 889 "title", 890 CmsStringUtil.escapeJavaScript( 891 getJsp().property(CmsPropertyDefinition.PROPERTY_TITLE, sitePath, res.getName()))); 892 // 4: file size (in kb) 893 jsonObj.put( 894 "size", 895 (res.getLength() / 1024) + " " + key(org.opencms.workplace.galleries.Messages.GUI_LABEL_KILOBYTES_0)); 896 // 5: file creation date (formatted) 897 jsonObj.put("datecreated", getMessages().getDateTime(res.getDateCreated())); 898 // 6: file modification date (formatted) 899 jsonObj.put("datelastmodified", getMessages().getDateTime(res.getDateLastModified())); 900 // 7: file state, if the item is new or changed 901 CmsResourceState state = res.getState(); 902 CmsLock lock = CmsLock.getNullLock(); 903 try { 904 // obtain current lock state to determine correct resource state and editable flag 905 lock = getCms().getLock(res); 906 } catch (CmsException e) { 907 // ignore, lock state could not be determined 908 } 909 if (!lock.isNullLock() && lock.getType().isPublish()) { 910 state = CmsResourceState.STATE_UNCHANGED; 911 } 912 jsonObj.put("state", state); 913 // 8: determine if the item is locked by another user 914 String locked = ""; 915 if (!lock.isNullLock() 916 && !lock.getType().isPublish() 917 && !lock.getUserId().equals(getCms().getRequestContext().getCurrentUser().getId())) { 918 try { 919 locked = getCms().readUser(lock.getUserId()).getName(); 920 } catch (CmsException e) { 921 // failed to read user, use ID as user name 922 locked = lock.getUserId().toString(); 923 } 924 } 925 jsonObj.put("lockedby", locked); 926 // 9: item editable flag to determine if item is editable (offline project and can be locked by the current user) 927 boolean editable = false; 928 // 10: item write permissions to determine if the user has write permission 929 boolean writePermission = false; 930 // 10: item direct publish flag to determine if the user has direct publish permission 931 boolean directPublishPermission = false; 932 try { 933 // test if the resource is in the offline project and it can be locked by the user 934 if (!getCms().getRequestContext().getCurrentProject().isOnlineProject() 935 && lock.isLockableBy(getCms().getRequestContext().getCurrentUser())) { 936 editable = true; 937 // test if the user has the write permission 938 if (getCms().hasPermissions(res, CmsPermissionSet.ACCESS_WRITE, false, CmsResourceFilter.ALL)) { 939 writePermission = true; 940 } 941 // test if the user has direct publish permission 942 if (getCms().hasPermissions( 943 res, 944 CmsPermissionSet.ACCESS_DIRECT_PUBLISH, 945 false, 946 CmsResourceFilter.ALL)) { 947 directPublishPermission = true; 948 } 949 950 } 951 } catch (CmsException e) { 952 if (LOG.isErrorEnabled()) { 953 LOG.error(e.getLocalizedMessage(), e); 954 } 955 } 956 jsonObj.put("editable", editable); 957 jsonObj.put("writepermission", writePermission); 958 jsonObj.put("directpublish", directPublishPermission); 959 // 11: item description 960 String desc = getJsp().property(CmsPropertyDefinition.PROPERTY_DESCRIPTION, sitePath, ""); 961 jsonObj.put("description", CmsStringUtil.escapeJavaScript(desc)); 962 } catch (JSONException e) { 963 if (LOG.isErrorEnabled()) { 964 LOG.error(e.getLocalizedMessage(), e); 965 } 966 } 967 } 968 969 /** 970 * Returns a JSON object containing information of the given resource for usage in the gallery.<p> 971 * 972 * The content of the JSON object consists of a common and a specific part of the given resource.<p> 973 * 974 * @param res the resource to create the object from 975 * @return the JSON object containing information from the given resource 976 */ 977 protected JSONObject buildJsonItemObject(CmsResource res) { 978 979 // create a new JSON object 980 JSONObject jsonObj = new JSONObject(); 981 String sitePath = getCms().getRequestContext().getSitePath(res); 982 // fill JSON object with common information 983 buildJsonItemCommonPart(jsonObj, res, sitePath); 984 // fill JSON object with specific information 985 buildJsonItemSpecificPart(jsonObj, res, sitePath); 986 987 return jsonObj; 988 } 989 990 /** 991 * Fills the JSON object with the specific information used for this resource type.<p> 992 * 993 * @param jsonObj containing information used by all possible resource 994 * @param res the resource to create the object from 995 * @param sitePath site path to the object 996 */ 997 protected abstract void buildJsonItemSpecificPart(JSONObject jsonObj, CmsResource res, String sitePath); 998 999 /** 1000 * Builds the JSON code to create items for the folder.<p> 1001 * 1002 * @param resourceitems the file resource to build the displayed items 1003 * @param parentFolder the parent folder of the collected files (for a gallery) 1004 */ 1005 protected void buildJsonResourceItems(List<CmsResource> resourceitems, String parentFolder) { 1006 1007 if (resourceitems == null) { 1008 resourceitems = new ArrayList<CmsResource>(); 1009 } 1010 1011 boolean isPublishEnabled = false; 1012 boolean hasDirectPublish = false; 1013 boolean hasWritePermission = false; 1014 if (CmsStringUtil.isNotEmpty(parentFolder)) { 1015 // check if there are changes in the currently selected gallery and the user has direct edit permissions 1016 try { 1017 if ((OpenCms.getPublishManager().getPublishList( 1018 getCms(), 1019 getCms().readResource(parentFolder), 1020 false).size() > 0)) { 1021 isPublishEnabled = true; 1022 } 1023 } catch (CmsException e) { 1024 // ignore, gallery can not be published 1025 } 1026 // check if the user has direst publish permissions, 1027 // used to enable the gallerypublish button, if user has enough permissions 1028 try { 1029 if (getCms().hasPermissions( 1030 getCms().readResource(parentFolder), 1031 CmsPermissionSet.ACCESS_DIRECT_PUBLISH, 1032 false, 1033 CmsResourceFilter.ALL)) { 1034 hasDirectPublish = true; 1035 } 1036 } catch (CmsException e) { 1037 // ignore, no publish permissions for gallery 1038 } 1039 try { 1040 // check if the user has write permissions, 1041 // used to display the upload buttons 1042 if (getCms().hasPermissions( 1043 getCms().readResource(parentFolder), 1044 CmsPermissionSet.ACCESS_WRITE, 1045 false, 1046 CmsResourceFilter.ALL)) { 1047 hasWritePermission = true; 1048 } 1049 } catch (CmsException e) { 1050 // ignore, no write permissions for gallery 1051 } 1052 } 1053 JSONObject publishInfo = new JSONObject(); 1054 try { 1055 publishInfo.put("publishable", isPublishEnabled); 1056 publishInfo.put("directpublish", hasDirectPublish); 1057 publishInfo.put("writepermission", hasWritePermission); 1058 } catch (JSONException e) { 1059 // ignore 1060 } 1061 JSONArray items = new JSONArray(); 1062 items.put(publishInfo); 1063 Iterator<CmsResource> i = resourceitems.iterator(); 1064 while (i.hasNext()) { 1065 CmsResource res = i.next(); 1066 // build a JSON object from the item and add it to the list 1067 items.put(buildJsonItemObject(res)); 1068 } 1069 JspWriter out = getJsp().getJspContext().getOut(); 1070 try { 1071 // print the JSON array 1072 out.print(items.toString()); 1073 } catch (IOException e) { 1074 if (LOG.isErrorEnabled()) { 1075 LOG.error(e.getLocalizedMessage(), e); 1076 } 1077 } 1078 } 1079 1080 /** 1081 * Changes the content of the CmsResource.<p> 1082 * This function should be overwritten in {@link org.opencms.workplace.galleries.CmsAjaxLinkGallery}.<p> 1083 * 1084 * @param itemUrl the item URL 1085 * 1086 */ 1087 protected void changeItemLinkUrl(String itemUrl) { 1088 1089 // the most galleries do not provide this method 1090 1091 } 1092 1093 /** 1094 * Changes the title property value of the given item.<p> 1095 * 1096 * @param itemUrl the item URL on which the title is changed 1097 */ 1098 protected void changeItemTitle(String itemUrl) { 1099 1100 try { 1101 JspWriter out = getJsp().getJspContext().getOut(); 1102 if (getCms().existsResource(itemUrl)) { 1103 try { 1104 writeTitleProperty(getCms().readResource(itemUrl)); 1105 out.print(buildJsonItemObject(getCms().readResource(itemUrl))); 1106 } catch (CmsException e) { 1107 // can not happen in theory, because we used existsResource() before... 1108 } 1109 } else { 1110 out.print(RETURNVALUE_NONE); 1111 } 1112 } catch (IOException e) { 1113 if (LOG.isErrorEnabled()) { 1114 LOG.error(e.getLocalizedMessage(), e); 1115 } 1116 } 1117 } 1118 1119 /** 1120 * Returns the resource items for the selected category.<p> 1121 * 1122 * @return the resource items for the selected category 1123 */ 1124 protected List<CmsResource> getCategoryItems() { 1125 1126 List<CmsResource> result = Collections.emptyList(); 1127 if (CmsStringUtil.isNotEmpty(getParamGalleryPath())) { 1128 try { 1129 CmsCategoryService service = CmsCategoryService.getInstance(); 1130 // get the edited resource if present 1131 String editedResource = "/"; 1132 if (CmsStringUtil.isNotEmpty(getParamResource())) { 1133 editedResource = CmsResource.getFolderPath(getParamResource()); 1134 } 1135 // read the matching resources for the category 1136 result = service.readCategoryResources(getCms(), getParamGalleryPath(), true, editedResource); 1137 // filter the matched resources to get only the specific items as result 1138 int resTypeId = getGalleryItemsTypeId(); 1139 if (resTypeId != -1) { 1140 List<CmsResource> unfiltered = new ArrayList<CmsResource>(result); 1141 result = new ArrayList<CmsResource>(unfiltered.size()); 1142 Iterator<CmsResource> i = unfiltered.iterator(); 1143 while (i.hasNext()) { 1144 CmsResource res = i.next(); 1145 if (res.getTypeId() == resTypeId) { 1146 result.add(res); 1147 } 1148 } 1149 } 1150 } catch (CmsException e) { 1151 // error reading resources 1152 if (LOG.isErrorEnabled()) { 1153 LOG.error(e.getLocalizedMessage(), e); 1154 } 1155 } catch (NullPointerException e) { 1156 // ignore this exception 1157 if (LOG.isErrorEnabled()) { 1158 LOG.error(e.getLocalizedMessage(), e); 1159 } 1160 } 1161 } 1162 return result; 1163 } 1164 1165 /** 1166 * @see org.opencms.workplace.CmsWorkplace#initWorkplaceRequestValues(org.opencms.workplace.CmsWorkplaceSettings, javax.servlet.http.HttpServletRequest) 1167 */ 1168 @Override 1169 protected void initWorkplaceRequestValues(CmsWorkplaceSettings settings, HttpServletRequest request) { 1170 1171 // fill the parameter values in the get/set methods 1172 fillParamValues(request); 1173 // set the dialog type 1174 setParamDialogtype(LISTMODE_GALLERY); 1175 if (CmsStringUtil.isEmpty(getParamGalleryPath())) { 1176 String lastUsedGallery = getSettings().getLastUsedGallery("" + getGalleryTypeId()); 1177 if (CmsStringUtil.isNotEmpty(lastUsedGallery)) { 1178 // set the resourcepath of the last used gallery if the resource is not deleted 1179 try { 1180 getCms().readResource(lastUsedGallery, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED); 1181 setParamGalleryPath(lastUsedGallery); 1182 } catch (CmsException e) { 1183 // reading the last used gallery failed, may be deleted 1184 } 1185 } 1186 } 1187 } 1188 1189 /** 1190 * Changes the value of the property title for the specified resource.<p> 1191 * 1192 * @param res the resource to change the property value 1193 */ 1194 protected void writeTitleProperty(CmsResource res) { 1195 1196 String resPath = getCms().getSitePath(res); 1197 String currentPropertyValue = getParamPropertyValue(); 1198 try { 1199 CmsProperty currentProperty = getCms().readPropertyObject( 1200 resPath, 1201 CmsPropertyDefinition.PROPERTY_TITLE, 1202 false); 1203 // detect if property is a null property or not 1204 if (currentProperty.isNullProperty()) { 1205 // create new property object and set key and value 1206 currentProperty = new CmsProperty(); 1207 currentProperty.setName(CmsPropertyDefinition.PROPERTY_TITLE); 1208 if (OpenCms.getWorkplaceManager().isDefaultPropertiesOnStructure()) { 1209 // set structure value 1210 currentProperty.setStructureValue(currentPropertyValue); 1211 currentProperty.setResourceValue(null); 1212 } else { 1213 // set resource value 1214 currentProperty.setStructureValue(null); 1215 currentProperty.setResourceValue(currentPropertyValue); 1216 } 1217 } else if (currentProperty.getStructureValue() != null) { 1218 // structure value has to be updated 1219 currentProperty.setStructureValue(currentPropertyValue); 1220 currentProperty.setResourceValue(null); 1221 } else { 1222 // resource value has to be updated 1223 currentProperty.setStructureValue(null); 1224 currentProperty.setResourceValue(currentPropertyValue); 1225 } 1226 CmsLock lock = getCms().getLock(res); 1227 if (lock.isUnlocked()) { 1228 // lock resource before operation 1229 getCms().lockResource(resPath); 1230 } 1231 // write the property to the resource 1232 getCms().writePropertyObject(resPath, currentProperty); 1233 // unlock the resource 1234 getCms().unlockResource(resPath); 1235 } catch (CmsException e) { 1236 // writing the property failed, log error 1237 LOG.error(e.getLocalizedMessage(), e); 1238 } 1239 } 1240}