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.ui.apps.user; 029 030import org.opencms.file.CmsGroup; 031import org.opencms.file.CmsObject; 032import org.opencms.main.CmsException; 033import org.opencms.main.CmsLog; 034import org.opencms.main.OpenCms; 035import org.opencms.security.CmsOrganizationalUnit; 036import org.opencms.security.CmsRole; 037import org.opencms.ui.A_CmsUI; 038import org.opencms.ui.CmsCssIcon; 039import org.opencms.ui.components.OpenCmsTheme; 040import org.opencms.util.CmsUUID; 041 042import java.util.ArrayList; 043import java.util.Collection; 044import java.util.List; 045 046import org.apache.commons.lang3.tuple.Pair; 047import org.apache.commons.logging.Log; 048 049import com.vaadin.v7.data.Item; 050import com.vaadin.v7.data.util.HierarchicalContainer; 051import com.vaadin.v7.event.ItemClickEvent; 052import com.vaadin.v7.event.ItemClickEvent.ItemClickListener; 053import com.vaadin.v7.ui.Tree; 054 055/** 056 * Class for the OU Tree.<p> 057 */ 058@SuppressWarnings("deprecation") 059public class CmsOuTree extends Tree { 060 061 /** Log instance for this class. */ 062 private static final Log LOG = CmsLog.getLog(CmsOuTree.class); 063 064 /**Root OU.*/ 065 private static CmsOrganizationalUnit m_rootSystemOU; 066 067 /**name property. */ 068 private static final String PROP_NAME = "name"; 069 070 /**type property. */ 071 private static final String PROP_TYPE = "type"; 072 073 /**vaadin serial id.*/ 074 private static final long serialVersionUID = -3532367333216144806L; 075 076 private static final String PROP_SID = "sid"; 077 078 /**Calling app. */ 079 private CmsAccountsApp m_app; 080 081 /**CmsObject. */ 082 private CmsObject m_cms; 083 084 /**Root ou. */ 085 private CmsOrganizationalUnit m_rootOu; 086 087 /**Container. */ 088 private HierarchicalContainer m_treeContainer; 089 090 /** 091 * constructor.<p> 092 * 093 * @param cms CmsObject 094 * @param app app instance 095 * @param baseOU baseOu 096 */ 097 public CmsOuTree(CmsObject cms, CmsAccountsApp app, String baseOU) { 098 099 m_cms = cms; 100 try { 101 m_rootSystemOU = OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, ""); 102 } catch (CmsException e1) { 103 // 104 } 105 m_app = app; 106 addStyleName(OpenCmsTheme.FULL_WIDTH_PADDING); 107 addStyleName(OpenCmsTheme.SIMPLE_DRAG); 108 setWidth("100%"); 109 m_treeContainer = new HierarchicalContainer(); 110 m_treeContainer.addContainerProperty(PROP_NAME, String.class, ""); 111 m_treeContainer.addContainerProperty(PROP_TYPE, I_CmsOuTreeType.class, null); 112 m_treeContainer.addContainerProperty(PROP_SID, CmsUUID.class, null); 113 setContainerDataSource(m_treeContainer); 114 115 m_rootOu = null; 116 try { 117 m_rootOu = OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, baseOU); 118 Item item = m_treeContainer.addItem(m_rootOu); 119 item.getItemProperty(PROP_NAME).setValue(getIconCaptionHTML(m_rootOu, CmsOuTreeType.OU)); 120 item.getItemProperty(PROP_TYPE).setValue(CmsOuTreeType.OU); 121 } catch (CmsException e) { 122 LOG.error("Unable to read OU", e); 123 } 124 setItemCaptionPropertyId(PROP_NAME); 125 setHtmlContentAllowed(true); 126 setNullSelectionAllowed(false); 127 addChildrenForOUNode(m_rootOu); 128 expandItem(m_rootOu); 129 addItemClickListener(new ItemClickListener() { 130 131 private static final long serialVersionUID = -6475529853027436127L; 132 133 public void itemClick(ItemClickEvent event) { 134 135 handleItemClick(event.getItemId()); 136 137 } 138 }); 139 addExpandListener(new ExpandListener() { 140 141 private static final long serialVersionUID = 589297480547091120L; 142 143 public void nodeExpand(ExpandEvent event) { 144 145 handleExpand(event.getItemId()); 146 147 } 148 }); 149 } 150 151 /** 152 * Opens given path.<p> 153 * 154 * @param path ou path (=ou-name) 155 * @param type type (ou,group or user) 156 * @param groupID id of group (optional) 157 */ 158 public void openPath(String path, I_CmsOuTreeType type, CmsUUID groupID) { 159 160 if (type == null) { 161 return; 162 } 163 try { 164 expandItem(m_rootOu); 165 String[] pathP = path.split("/"); 166 String complPath = ""; 167 for (String subP : pathP) { 168 complPath += subP + "/"; 169 CmsOrganizationalUnit ou = OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, complPath); 170 addChildrenForOUNode(ou); 171 expandItem(ou); 172 } 173 174 if (type.isGroup() || type.isRole()) { 175 String itemId = type.getId() 176 + OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, path).getName(); 177 expandItem(itemId); 178 if (groupID == null) { 179 setValue(itemId); 180 return; 181 } 182 setValue(groupID); 183 return; 184 } 185 if (type.isUser()) { 186 setValue(type.getId() + OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, path).getName()); 187 return; 188 } 189 190 setValue(OpenCms.getOrgUnitManager().readOrganizationalUnit(m_cms, path)); 191 192 } catch (CmsException e) { 193 LOG.error("Unable to read OU", e); 194 } 195 } 196 197 /** 198 * Handle expand action.<p> 199 * 200 * @param itemId which was expended 201 */ 202 protected void handleExpand(Object itemId) { 203 204 I_CmsOuTreeType type = (I_CmsOuTreeType)getItem(itemId).getItemProperty(PROP_TYPE).getValue(); 205 loadAndExpand(itemId, type); 206 } 207 208 /** 209 * Handle item click.<p> 210 * 211 * @param itemId item which was clicked 212 */ 213 214 protected void handleItemClick(Object itemId) { 215 216 Item item = getItem(itemId); 217 I_CmsOuTreeType type = (I_CmsOuTreeType)getItem(itemId).getItemProperty(PROP_TYPE).getValue(); 218 CmsUUID roleOrGroupID = null; 219 boolean idInItem = false; 220 if (itemId instanceof CmsUUID) { 221 roleOrGroupID = (CmsUUID)itemId; 222 idInItem = true; 223 } else if (item.getItemProperty(PROP_SID).getValue() != null) { 224 roleOrGroupID = (CmsUUID)(item.getItemProperty(PROP_SID).getValue()); 225 idInItem = true; 226 } 227 if (type.equals(CmsOuTreeType.ROLE)) { 228 String ou = getOuFromItem(itemId, CmsOuTreeType.ROLE); 229 boolean isRoot = ou.isEmpty(); 230 if (isRoot) { 231 ou = "/"; 232 } 233 if (!((String)itemId).endsWith(ou)) { 234 if (isRoot) { 235 if (((String)itemId).length() > (ou.length() + 1)) { 236 roleOrGroupID = new CmsUUID(((String)itemId).substring(ou.length() + 1)); 237 } 238 } else { 239 roleOrGroupID = new CmsUUID(((String)itemId).substring(ou.length() + 2)); 240 } 241 } 242 } 243 244 m_app.update(getOuFromItem(itemId, type), type, roleOrGroupID, ""); 245 if (isExpanded(itemId) || idInItem) { 246 return; 247 } 248 loadAndExpand(itemId, type); 249 setValue(itemId); 250 251 } 252 253 /** 254 * Updates items of current ou for item.<p> 255 * 256 * @param item to update ou for 257 */ 258 void updateOU(CmsOrganizationalUnit item) { 259 260 //Check if ou has children ... vaadin returns null if not 261 if (m_treeContainer.getChildren(item) == null) { 262 return; 263 } 264 for (Object it : m_treeContainer.getChildren(item)) { 265 if (isExpanded(it)) { 266 I_CmsOuTreeType type = (I_CmsOuTreeType)getItem(it).getItemProperty(PROP_TYPE).getValue(); 267 if (type.isGroup()) { 268 addChildrenForGroupsNode(type, type.getId() + item.getName()); 269 } 270 } 271 } 272 } 273 274 /** 275 * Add groups for given group parent item. 276 * 277 * @param type the tree type 278 * @param ouItem group parent item 279 */ 280 private void addChildrenForGroupsNode(I_CmsOuTreeType type, String ouItem) { 281 282 try { 283 // Cut of type-specific prefix from ouItem with substring() 284 List<CmsGroup> groups = m_app.readGroupsForOu(m_cms, ouItem.substring(1), type, false); 285 286 List<Object> itemsToRemove = new ArrayList<Object>(); 287 288 Collection<?> childCol = m_treeContainer.getChildren(ouItem); 289 if (childCol != null) { 290 itemsToRemove.addAll(childCol); 291 } 292 for (CmsGroup group : groups) { 293 Pair<String, CmsUUID> key = Pair.of(type.getId(), group.getId()); 294 Item groupItem = m_treeContainer.addItem(key); 295 if (groupItem == null) { 296 groupItem = getItem(key); 297 itemsToRemove.remove(key); 298 } 299 groupItem.getItemProperty(PROP_SID).setValue(group.getId()); 300 groupItem.getItemProperty(PROP_NAME).setValue(getIconCaptionHTML(group, CmsOuTreeType.GROUP)); 301 groupItem.getItemProperty(PROP_TYPE).setValue(type); 302 setChildrenAllowed(key, false); 303 m_treeContainer.setParent(key, ouItem); 304 } 305 306 for (Object item : itemsToRemove) { 307 m_treeContainer.removeItem(item); 308 } 309 310 } catch (CmsException e) { 311 LOG.error("Can not read group", e); 312 } 313 314 } 315 316 /** 317 * Add children for ou.<p> 318 * 319 * @param item ou item 320 */ 321 private void addChildrenForOUNode(CmsOrganizationalUnit item) { 322 323 List<Object> itemsToRemove = new ArrayList<Object>(); 324 325 Collection<?> childCol = m_treeContainer.getChildren(item); 326 if (childCol != null) { 327 itemsToRemove.addAll(childCol); 328 } 329 330 try { 331 if (m_app.isOUManagable(item.getName())) { 332 333 List<I_CmsOuTreeType> types = m_app.getTreeTypeProvider().getTreeTypes(); 334 for (I_CmsOuTreeType type : types) { 335 if (!type.isValidForOu(m_cms, item.getName())) { 336 continue; 337 } 338 if (type.isOrgUnit()) { 339 continue; 340 } 341 String itemId = type.getId() + item.getName(); 342 Item newItem = m_treeContainer.addItem(itemId); 343 itemsToRemove.remove(itemId); 344 if (newItem != null) { 345 newItem.getItemProperty(PROP_NAME).setValue(getIconCaptionHTML(itemId, type)); 346 newItem.getItemProperty(PROP_TYPE).setValue(type); 347 m_treeContainer.setParent(itemId, item); 348 setChildrenAllowed(itemId, type.isExpandable()); 349 } 350 } 351 } 352 List<CmsOrganizationalUnit> ous = OpenCms.getOrgUnitManager().getOrganizationalUnits( 353 m_cms, 354 item.getName(), 355 false); 356 List<CmsOrganizationalUnit> webOus = new ArrayList<CmsOrganizationalUnit>(); 357 for (CmsOrganizationalUnit ou : ous) { 358 if (m_app.isParentOfManagableOU(ou.getName())) { 359 itemsToRemove.remove(ou); 360 if (ou.hasFlagWebuser()) { 361 webOus.add(ou); 362 } else { 363 addOuToTree(ou, item); 364 } 365 } 366 } 367 for (CmsOrganizationalUnit ou : webOus) { 368 if (m_app.isParentOfManagableOU(ou.getName())) { 369 itemsToRemove.remove(ou); 370 addOuToTree(ou, item); 371 } 372 } 373 } catch (CmsException e) { 374 LOG.error("Can't read ou", e); 375 } 376 for (Object it : itemsToRemove) { 377 m_treeContainer.removeItemRecursively(it); 378 } 379 } 380 381 /** 382 * Add roles for given role parent item. 383 * 384 * @param ouItem group parent item 385 */ 386 private void addChildrenForRolesNode(String ouItem) { 387 388 try { 389 List<CmsRole> roles = OpenCms.getRoleManager().getRoles(m_cms, ouItem.substring(1), false); 390 CmsRole.applySystemRoleOrder(roles); 391 for (CmsRole role : roles) { 392 String roleId = ouItem + "/" + role.getId(); 393 Item roleItem = m_treeContainer.addItem(roleId); 394 if (roleItem == null) { 395 roleItem = getItem(roleId); 396 } 397 roleItem.getItemProperty(PROP_NAME).setValue(getIconCaptionHTML(role, CmsOuTreeType.ROLE)); 398 roleItem.getItemProperty(PROP_TYPE).setValue(CmsOuTreeType.ROLE); 399 setChildrenAllowed(roleId, false); 400 m_treeContainer.setParent(roleId, ouItem); 401 } 402 } catch (CmsException e) { 403 LOG.error("Can not read group", e); 404 } 405 } 406 407 /** 408 * Adds an ou to the tree.<p> 409 * 410 * @param ou to be added 411 * @param parent_ou parent ou 412 */ 413 private void addOuToTree(CmsOrganizationalUnit ou, CmsOrganizationalUnit parent_ou) { 414 415 Item containerItem; 416 containerItem = m_treeContainer.addItem(ou); 417 if (containerItem == null) { 418 containerItem = getItem(ou); 419 } 420 containerItem.getItemProperty(PROP_NAME).setValue(getIconCaptionHTML(ou, CmsOuTreeType.OU)); 421 containerItem.getItemProperty(PROP_TYPE).setValue(CmsOuTreeType.OU); 422 m_treeContainer.setParent(ou, parent_ou); 423 } 424 425 /** 426 * Get HTML for icon and item caption.<p> 427 * 428 * @param item item to get icon and caption for 429 * @param type type 430 * @return html 431 */ 432 private String getIconCaptionHTML(Object item, I_CmsOuTreeType type) { 433 434 CmsCssIcon icon = type.getIcon(); 435 String caption = type.getName(); 436 if (item instanceof CmsOrganizationalUnit) { 437 CmsOrganizationalUnit ou = (CmsOrganizationalUnit)item; 438 if (ou.hasFlagWebuser()) { 439 icon = new CmsCssIcon(OpenCmsTheme.ICON_OU_WEB); 440 } 441 caption = (ou.equals(m_rootSystemOU) ? ou.getDisplayName(A_CmsUI.get().getLocale()) : ou.getName()); 442 } 443 444 if (item instanceof CmsGroup) { 445 //Real group shown under groups 446 caption = ((CmsGroup)item).getName(); 447 icon = m_app.getGroupIcon((CmsGroup)item); 448 } 449 450 if (item instanceof CmsRole) { 451 //Real group shown under groups 452 caption = ((CmsRole)item).getName(A_CmsUI.get().getLocale()); 453 } 454 455 if (icon != null) { 456 return "<span class=\"o-resource-icon\">" 457 + icon.getHtml() 458 + "</span>" 459 + "<span class=\"o-tree-caption\">" 460 + caption 461 + "</span>"; 462 } 463 return ""; 464 } 465 466 /** 467 * Gets ou from given item.<p> 468 * 469 * @param itemId to get ou for 470 * @param type of given item 471 * @return name of ou 472 */ 473 private String getOuFromItem(Object itemId, I_CmsOuTreeType type) { 474 475 if (type.equals(CmsOuTreeType.OU)) { 476 return ((CmsOrganizationalUnit)itemId).getName(); 477 } 478 Object o = m_treeContainer.getParent(itemId); 479 while (!(o instanceof CmsOrganizationalUnit)) { 480 o = m_treeContainer.getParent(o); 481 } 482 return ((CmsOrganizationalUnit)o).getName(); 483 } 484 485 /** 486 * Load and expand given item.<p> 487 * 488 * @param itemId to be expanded 489 * @param type of item 490 */ 491 private void loadAndExpand(Object itemId, I_CmsOuTreeType type) { 492 493 if (type.isOrgUnit()) { 494 addChildrenForOUNode((CmsOrganizationalUnit)itemId); 495 } 496 if (type.isGroup()) { 497 addChildrenForGroupsNode(type, (String)itemId); 498 } 499 if (type.isRole()) { 500 addChildrenForRolesNode((String)itemId); 501 } 502 expandItem(itemId); 503 } 504 505}