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 */ 016package org.ametys.cms.support; 017 018import javax.jcr.Item; 019import javax.jcr.Node; 020import javax.jcr.Property; 021import javax.jcr.RepositoryException; 022import javax.jcr.version.OnParentVersionAction; 023 024import org.apache.commons.collections.Predicate; 025import org.apache.commons.collections.PredicateUtils; 026import org.apache.commons.lang.ArrayUtils; 027import org.apache.jackrabbit.JcrConstants; 028 029import org.ametys.plugins.repository.RepositoryConstants; 030import org.ametys.plugins.repository.jcr.NodeTypeHelper; 031 032/** 033 * Provides the following predicates: 034 * <ul> 035 * <li>propertyNamePredicate - accept a property depending on his name. 036 * <li>nodeNamePredicate - accept a node depending on his name. 037 * <li>nodeTypePredicate - accept a node depending on his node type. 038 * </ul> 039 */ 040public class AmetysPredicateUtils extends PredicateUtils 041{ 042 private static AllowedForLivePredicate _allowedLivePredicate = new AllowedForLivePredicate(); 043 044 /** 045 * Tests if the property has the following name. 046 * @param propertyName the property name. 047 * @return <code>true</code> if the property has the given name, 048 * <code>false</code> otherwise. 049 */ 050 public static Predicate propertyNamePredicate(final String propertyName) 051 { 052 return new Predicate() 053 { 054 @Override 055 public boolean evaluate(Object object) 056 { 057 if (object instanceof Property) 058 { 059 try 060 { 061 return ((Property) object).getName().equals(propertyName); 062 } 063 catch (RepositoryException e) 064 { 065 throw new RuntimeException("Unable to get property name", e); 066 } 067 } 068 069 return false; 070 } 071 }; 072 } 073 074 /** 075 * Tests if the property has a given name in a list. 076 * @param propertyNames one or several property names. 077 * @return <code>true</code> if the property has on of the given names, 078 * <code>false</code> otherwise. 079 */ 080 public static Predicate propertyNamesPredicate(final String ... propertyNames) 081 { 082 return new Predicate() 083 { 084 @Override 085 public boolean evaluate(Object object) 086 { 087 if (object instanceof Property) 088 { 089 try 090 { 091 String propName = ((Property) object).getName(); 092 return ArrayUtils.contains(propertyNames, propName); 093 } 094 catch (RepositoryException e) 095 { 096 throw new RuntimeException("Unable to get property name", e); 097 } 098 } 099 return false; 100 } 101 }; 102 } 103 104 /** 105 * Tests if the property is not a protected one (e.g. jcr:uuid). 106 * @param predicate the additional predicate to evaluate. 107 * @return <code>true</code> if the property has the given name, 108 * <code>false</code> otherwise. 109 */ 110 public static Predicate ignoreProtectedProperties(final Predicate predicate) 111 { 112 return new IgnoreProtectedPredicate(predicate); 113 } 114 115 /** 116 * Tests if the node has the following name. 117 * @param nodeName the node name. 118 * @return <code>true</code> if the node has the given name, 119 * <code>false</code> otherwise. 120 */ 121 public static Predicate nodeNamePredicate(final String nodeName) 122 { 123 return new Predicate() 124 { 125 @Override 126 public boolean evaluate(Object object) 127 { 128 if (object instanceof Node) 129 { 130 try 131 { 132 return ((Node) object).getName().equals(nodeName); 133 } 134 catch (RepositoryException e) 135 { 136 throw new RuntimeException("Unable to get node name", e); 137 } 138 } 139 140 return false; 141 } 142 }; 143 } 144 145 /** 146 * Tests if the node or property is a Ametys attribute, ie. it is prefixed by 'ametys:' 147 * @return <code>true</code> if the name starts with 'ametys:' 148 * <code>false</code> otherwise. 149 */ 150 public static Predicate ametysAttributePredicate() 151 { 152 return new Predicate() 153 { 154 @Override 155 public boolean evaluate(Object object) 156 { 157 if (object instanceof Item) 158 { 159 try 160 { 161 return ((Item) object).getName().startsWith(RepositoryConstants.NAMESPACE_PREFIX + ":"); 162 } 163 catch (RepositoryException e) 164 { 165 throw new RuntimeException("Unable to get item name", e); 166 } 167 } 168 169 return false; 170 } 171 }; 172 } 173 174 /** 175 * Tests if the node is of the given node type. 176 * @param nodeTypeName the node type name. 177 * @return <code>true</code> if the node has the given node type, 178 * <code>false</code> otherwise. 179 */ 180 public static Predicate nodeTypePredicate(final String nodeTypeName) 181 { 182 return new Predicate() 183 { 184 @Override 185 public boolean evaluate(Object object) 186 { 187 if (object instanceof Node) 188 { 189 try 190 { 191 return ((Node) object).isNodeType(nodeTypeName); 192 } 193 catch (RepositoryException e) 194 { 195 throw new RuntimeException("Unable to test node type", e); 196 } 197 } 198 199 return false; 200 } 201 }; 202 } 203 204 private static final class IgnoreProtectedPredicate implements Predicate 205 { 206 private Predicate _predicate; 207 208 IgnoreProtectedPredicate(Predicate predicate) 209 { 210 _predicate = predicate; 211 } 212 213 @Override 214 public boolean evaluate(Object object) 215 { 216 if (object instanceof Property) 217 { 218 Property property = (Property) object; 219 220 try 221 { 222 Node parentNode = property.getParent(); 223 String propertyName = property.getName(); 224 225 if (parentNode.isNodeType(JcrConstants.NT_FROZENNODE)) 226 { 227 if (propertyName.startsWith("jcr:")) 228 { 229 if (!propertyName.equals(JcrConstants.JCR_ENCODING) && !propertyName.equals(JcrConstants.JCR_MIMETYPE) 230 && !propertyName.equals(JcrConstants.JCR_DATA) && !propertyName.equals(JcrConstants.JCR_LASTMODIFIED)) 231 { 232 // Refuse potential protected property 233 return false; 234 } 235 } 236 237 return _predicate.evaluate(object); 238 } 239 else 240 { 241 // If property is not protected, do process it 242 return !property.getDefinition().isProtected() && _predicate.evaluate(object); 243 } 244 } 245 catch (RepositoryException e) 246 { 247 throw new RuntimeException("Unable to process property", e); 248 } 249 } 250 251 return false; 252 } 253 } 254 255 /** 256 * Tests if the node or property is allowed in the live workspace 257 * @return <code>true</code> if the property or node is allowed, 258 * <code>false</code> otherwise. 259 */ 260 public static Predicate isAllowedForLiveContent() 261 { 262 return _allowedLivePredicate; 263 } 264 265 private static final class AllowedForLivePredicate implements Predicate 266 { 267 AllowedForLivePredicate() 268 { 269 } 270 271 @Override 272 public boolean evaluate(Object object) 273 { 274 if (object instanceof Property) 275 { 276 277 Property property = (Property) object; 278 try 279 { 280 // oswf:* item are not allowed 281 return !property.getName().startsWith("oswf:") 282 && !property.getName().equals(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":initial-content") 283 && !property.getName().equals(RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":workflowRef"); 284 } 285 catch (RepositoryException e) 286 { 287 throw new RuntimeException("Unable to process property", e); 288 } 289 } 290 else if (object instanceof Node) 291 { 292 Node node = (Node) object; 293 try 294 { 295 String nodeType = NodeTypeHelper.getNodeTypeName(node); 296 297 // oswf:* item are not allowed 298 return !nodeType.startsWith("oswf:"); 299 } 300 catch (RepositoryException e) 301 { 302 throw new RuntimeException("Unable to process node", e); 303 } 304 } 305 306 return false; 307 } 308 } 309 310 311 /** 312 * Tests if the node or property is allowed in the live workspace 313 * @param node The parent node. 314 * @return <code>true</code> if the property or node is allowed, 315 * <code>false</code> otherwise. 316 */ 317 public static Predicate isNonVersionned(Node node) 318 { 319 return new NonVersionnedPredicate(node); 320 } 321 322 private static final class NonVersionnedPredicate implements Predicate 323 { 324 private Node _node; 325 326 NonVersionnedPredicate(Node node) 327 { 328 _node = node; 329 } 330 331 @Override 332 public boolean evaluate(Object object) 333 { 334 if (object instanceof Property) 335 { 336 Property property = (Property) object; 337 338 try 339 { 340 if (!property.getParent().getIdentifier().equals(_node.getIdentifier())) 341 { 342 // The property must be one of a child node (of a non versionned node) 343 return true; 344 } 345 return property.getDefinition().getOnParentVersion() == OnParentVersionAction.IGNORE; 346 } 347 catch (RepositoryException e) 348 { 349 throw new RuntimeException("Unable to process property", e); 350 } 351 } 352 else if (object instanceof Node) 353 { 354 Node node = (Node) object; 355 try 356 { 357 if (!node.getParent().getIdentifier().equals(_node.getIdentifier())) 358 { 359 // The node must be one of a child node (of a non versionned node) 360 return true; 361 } 362 return node.getDefinition().getOnParentVersion() == OnParentVersionAction.IGNORE; 363 } 364 catch (RepositoryException e) 365 { 366 throw new RuntimeException("Unable to process node", e); 367 } 368 } 369 370 return false; 371 } 372 } 373}