001/* 002 * Copyright 2010 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.ametys.plugins.repository.collection; 018 019import java.util.Iterator; 020import java.util.Map; 021import java.util.Set; 022 023import javax.jcr.Node; 024import javax.jcr.PathNotFoundException; 025import javax.jcr.RepositoryException; 026 027import org.ametys.core.group.GroupIdentity; 028import org.ametys.core.right.ProfileAssignmentStorage.AnonymousOrAnyConnectedKeys; 029import org.ametys.core.right.ProfileAssignmentStorage.UserOrGroup; 030import org.ametys.core.user.UserIdentity; 031import org.ametys.plugins.repository.AmetysObject; 032import org.ametys.plugins.repository.AmetysObjectIterable; 033import org.ametys.plugins.repository.AmetysRepositoryException; 034import org.ametys.plugins.repository.ModifiableACLAmetysObject; 035import org.ametys.plugins.repository.ModifiableTraversableAmetysObject; 036import org.ametys.plugins.repository.RepositoryIntegrityViolationException; 037import org.ametys.plugins.repository.UnknownAmetysObjectException; 038import org.ametys.plugins.repository.jcr.ACLJCRAmetysObjectHelper; 039import org.ametys.plugins.repository.jcr.SimpleAmetysObject; 040 041/** 042 * An {@link AmetysObject} representing a collection of other {@link AmetysObject}s.<br> 043 * The collection stored its contents in the JCR Repository in a hash tree for 044 * optimizing performances.<br> 045 * Please note that this implementation does not keep the insertion order of elements. 046 * @param <F> the type of the actual factory. 047 * @param <A> the type of the composite {@link AmetysObject}. 048 */ 049public class AmetysObjectCollection<F extends AmetysObjectCollectionFactory, A extends AmetysObject> extends SimpleAmetysObject<F> implements ModifiableTraversableAmetysObject, Iterable<A>, ModifiableACLAmetysObject 050{ 051 AmetysObjectCollectionFactory _factory; 052 053 /** 054 * Creates an {@link AmetysObjectCollection}. 055 * @param node the node backing this AmetysObject. 056 * @param parentPath the parentPath in the Ametys hierarchy. 057 * @param factory the {@link AmetysObjectCollectionFactory} which created the AmetysObject. 058 */ 059 public AmetysObjectCollection(Node node, String parentPath, F factory) 060 { 061 super(node, parentPath, factory); 062 _factory = factory; 063 } 064 065 @SuppressWarnings("unchecked") 066 public AmetysObjectIterable<A> getChildren() throws AmetysRepositoryException 067 { 068 return _factory.getChildren(getPath(), getNode()); 069 } 070 071 public Iterator<A> iterator() 072 { 073 return _factory.getChildren(getPath(), getNode()).iterator(); 074 } 075 076 public boolean hasChild(String name) throws AmetysRepositoryException 077 { 078 if (name == null || "".equals(name) || name.charAt(0) == '/') 079 { 080 throw new AmetysRepositoryException("Child name cannot be null, empty or absolute"); 081 } 082 083 if (".".equals(name) || "..".equals(name)) 084 { 085 throw new AmetysRepositoryException("Child name cannot be . or .."); 086 } 087 088 try 089 { 090 return getNode().hasNode(_getPath(name)); 091 } 092 catch (RepositoryException e) 093 { 094 throw new AmetysRepositoryException("An error occured getting child object " + name + " for object " + getName(), e); 095 } 096 } 097 098 @SuppressWarnings("unchecked") 099 public A getChild(String path) throws AmetysRepositoryException, UnknownAmetysObjectException 100 { 101 if (path == null || "".equals(path) || path.charAt(0) == '/') 102 { 103 throw new AmetysRepositoryException("Child path cannot be null, empty or absolute"); 104 } 105 106 String subPath = null; 107 String name; 108 109 int i = path.indexOf('/'); 110 if (i == -1) 111 { 112 name = path; 113 } 114 else 115 { 116 name = path.substring(0, i); 117 subPath = path.substring(i + 1); 118 } 119 120 if (".".equals(name) || "..".equals(name)) 121 { 122 throw new AmetysRepositoryException("Path cannot contain segment with . or .."); 123 } 124 125 try 126 { 127 Node childNode = getNode().getNode(_getPath(name)); 128 129 return (A) _factory.getObject(null, childNode, subPath); 130 } 131 catch (PathNotFoundException e) 132 { 133 throw new UnknownAmetysObjectException("Unable to retrieve child node for path: " + path, e); 134 } 135 catch (RepositoryException e) 136 { 137 throw new AmetysRepositoryException(e); 138 } 139 } 140 141 @SuppressWarnings("unchecked") 142 public A createChild(String name, String type) throws AmetysRepositoryException, RepositoryIntegrityViolationException 143 { 144 String[] hash = _factory.getHashedPath(name); 145 146 Node contextNode = getNode(); 147 148 try 149 { 150 for (String hashPart : hash) 151 { 152 if (!contextNode.hasNode(hashPart)) 153 { 154 contextNode = contextNode.addNode(hashPart, AmetysObjectCollectionFactory.COLLECTION_ELEMENT_NODETYPE); 155 } 156 else 157 { 158 contextNode = contextNode.getNode(hashPart); 159 } 160 } 161 162 return (A) _factory.createChild(getPath(), contextNode, name, type); 163 } 164 catch (RepositoryException e) 165 { 166 throw new AmetysRepositoryException("Unable to create child: " + name + " and type: " + type, e); 167 } 168 } 169 170 @Override 171 @SuppressWarnings("unchecked") 172 public AmetysObject getParent() throws AmetysRepositoryException 173 { 174 return _factory.getParent(this); 175 } 176 177 private String _getPath(String childName) 178 { 179 String[] hash = _factory.getHashedPath(childName); 180 181 StringBuilder path = new StringBuilder(); 182 183 for (String hashPart : hash) 184 { 185 path.append(hashPart); 186 path.append('/'); 187 } 188 189 path.append(childName); 190 191 return path.toString(); 192 } 193 194 public Map<AnonymousOrAnyConnectedKeys, Set<String>> getProfilesForAnonymousAndAnyConnectedUser() 195 { 196 return ACLJCRAmetysObjectHelper.getProfilesForAnonymousAndAnyConnectedUser(getNode()); 197 } 198 199 public Map<GroupIdentity, Map<UserOrGroup, Set<String>>> getProfilesForGroups(Set<GroupIdentity> groups) 200 { 201 return ACLJCRAmetysObjectHelper.getProfilesForGroups(getNode(), groups); 202 } 203 204 public Map<UserIdentity, Map<UserOrGroup, Set<String>>> getProfilesForUsers(UserIdentity user) 205 { 206 return ACLJCRAmetysObjectHelper.getProfilesForUsers(getNode(), user); 207 } 208 209 public void addAllowedProfilesForAnyConnectedUser(Set<String> profileIds) 210 { 211 ACLJCRAmetysObjectHelper.addAllowedProfilesForAnyConnectedUser(getNode(), profileIds); 212 } 213 214 public void removeAllowedProfilesForAnyConnectedUser(Set<String> profileIds) 215 { 216 ACLJCRAmetysObjectHelper.removeAllowedProfilesForAnyConnectedUser(getNode(), profileIds); 217 } 218 219 public void addDeniedProfilesForAnyConnectedUser(Set<String> profileIds) 220 { 221 ACLJCRAmetysObjectHelper.addDeniedProfilesForAnyConnectedUser(getNode(), profileIds); 222 } 223 224 public void removeDeniedProfilesForAnyConnectedUser(Set<String> profileIds) 225 { 226 ACLJCRAmetysObjectHelper.removeDeniedProfilesForAnyConnectedUser(getNode(), profileIds); 227 } 228 229 public void addAllowedProfilesForAnonymous(Set<String> profileIds) 230 { 231 ACLJCRAmetysObjectHelper.addAllowedProfilesForAnonymous(getNode(), profileIds); 232 } 233 234 public void removeAllowedProfilesForAnonymous(Set<String> profileIds) 235 { 236 ACLJCRAmetysObjectHelper.removeAllowedProfilesForAnonymous(getNode(), profileIds); 237 } 238 239 public void addDeniedProfilesForAnonymous(Set<String> profileIds) 240 { 241 ACLJCRAmetysObjectHelper.addDeniedProfilesForAnonymous(getNode(), profileIds); 242 } 243 244 public void removeDeniedProfilesForAnonymous(Set<String> profileIds) 245 { 246 ACLJCRAmetysObjectHelper.removeDeniedProfilesForAnonymous(getNode(), profileIds); 247 } 248 249 public void addAllowedUsers(Set<UserIdentity> users, String profileId) 250 { 251 ACLJCRAmetysObjectHelper.addAllowedUsers(users, getNode(), profileId); 252 } 253 254 public void removeAllowedUsers(Set<UserIdentity> users, String profileId) 255 { 256 ACLJCRAmetysObjectHelper.removeAllowedUsers(users, getNode(), profileId); 257 } 258 259 public void removeAllowedUsers(Set<UserIdentity> users) 260 { 261 ACLJCRAmetysObjectHelper.removeAllowedUsers(users, getNode()); 262 } 263 264 public void addAllowedGroups(Set<GroupIdentity> groups, String profileId) 265 { 266 ACLJCRAmetysObjectHelper.addAllowedGroups(groups, getNode(), profileId); 267 } 268 269 public void removeAllowedGroups(Set<GroupIdentity> groups, String profileId) 270 { 271 ACLJCRAmetysObjectHelper.removeAllowedGroups(groups, getNode(), profileId); 272 } 273 274 public void removeAllowedGroups(Set<GroupIdentity> groups) 275 { 276 ACLJCRAmetysObjectHelper.removeAllowedGroups(groups, getNode()); 277 } 278 279 public void addDeniedUsers(Set<UserIdentity> users, String profileId) 280 { 281 ACLJCRAmetysObjectHelper.addDeniedUsers(users, getNode(), profileId); 282 } 283 284 public void removeDeniedUsers(Set<UserIdentity> users, String profileId) 285 { 286 ACLJCRAmetysObjectHelper.removeDeniedUsers(users, getNode(), profileId); 287 } 288 289 public void removeDeniedUsers(Set<UserIdentity> users) 290 { 291 ACLJCRAmetysObjectHelper.removeDeniedUsers(users, getNode()); 292 } 293 294 public void addDeniedGroups(Set<GroupIdentity> groups, String profileId) 295 { 296 ACLJCRAmetysObjectHelper.addDeniedGroups(groups, getNode(), profileId); 297 } 298 299 public void removeDeniedGroups(Set<GroupIdentity> groups, String profileId) 300 { 301 ACLJCRAmetysObjectHelper.removeDeniedGroups(groups, getNode(), profileId); 302 } 303 304 public void removeDeniedGroups(Set<GroupIdentity> groups) 305 { 306 ACLJCRAmetysObjectHelper.removeDeniedGroups(groups, getNode()); 307 } 308 309 public boolean isInheritanceDisallowed() 310 { 311 return ACLJCRAmetysObjectHelper.isInheritanceDisallowed(getNode()); 312 } 313 314 public void disallowInheritance(boolean disallow) 315 { 316 ACLJCRAmetysObjectHelper.disallowInheritance(getNode(), disallow); 317 } 318}