Coverage Report - org.openpermis.policy.bean.basic.BasicTargetAccessRule
 
Classes in this File Line Coverage Branch Coverage Complexity
BasicTargetAccessRule
66%
72/109
59%
38/64
2.714
 
 1  
 /*
 2  
  * Copyright (c) 2009, Swiss Federal Department of Defence Civil Protection and Sport
 3  
  *                     (http://www.vbs.admin.ch)
 4  
  * Copyright (c) 2009, Ergon Informatik AG (http://www.ergon.ch)
 5  
  * All rights reserved.
 6  
  *
 7  
  * Licensed under the Open Permis License which accompanies this distribution,
 8  
  * and is available at http://www.openpermis.org/BSDlicenceKent.txt
 9  
  */
 10  
 package org.openpermis.policy.bean.basic;
 11  
 
 12  
 import static org.openpermis.policy.bean.basic.BasicUtilities.getShortStringDetails;
 13  
 import static org.openpermis.policy.bean.basic.BasicUtilities.getStringDetails;
 14  
 import static org.openpermis.policy.bean.basic.BasicUtilities.listHashCode;
 15  
 import static org.openpermis.policy.bean.basic.BasicUtilities.multiHashCode;
 16  
 
 17  
 import java.net.URI;
 18  
 import java.util.ArrayList;
 19  
 import java.util.Collection;
 20  
 import java.util.HashMap;
 21  
 import java.util.HashSet;
 22  
 import java.util.List;
 23  
 import java.util.Map;
 24  
 
 25  
 import org.openpermis.policy.Action;
 26  
 import org.openpermis.policy.AuthorizedRoles;
 27  
 import org.openpermis.policy.PartProblemReporter;
 28  
 import org.openpermis.policy.Predicate;
 29  
 import org.openpermis.policy.Role;
 30  
 import org.openpermis.policy.TimeStamp;
 31  
 import org.openpermis.policy.ParameterList.Parameter;
 32  
 import org.openpermis.policy.PartProblemReporter.ProblemMessage;
 33  
 import org.openpermis.policy.bean.ActionBean;
 34  
 import org.openpermis.policy.bean.ObligationBean;
 35  
 import org.openpermis.policy.bean.ObligationBeanCollection;
 36  
 import org.openpermis.policy.bean.PartBean;
 37  
 import org.openpermis.policy.bean.RoleCollection;
 38  
 import org.openpermis.policy.bean.SerialNumber;
 39  
 import org.openpermis.policy.bean.TargetAccessRuleBean;
 40  
 import org.openpermis.policy.bean.TargetBean;
 41  
 import org.openpermis.policy.bean.TargetBeanCollection;
 42  
 
 43  
 /**
 44  
  * A target access rule defines a set of roles that are allowed to access a target.
 45  
  * @since 0.1.0
 46  
  */
 47  
 public class BasicTargetAccessRule
 48  
         extends BasicPartBean
 49  
         implements TargetAccessRuleBean
 50  
 {
 51  
 
 52  
         //---- Static
 53  
 
 54  
         private static final long serialVersionUID = -3795054107954794737L;
 55  
 
 56  
         
 57  
         //---- State
 58  
 
 59  
         /**
 60  
          * The targets of this access rule.
 61  
          */
 62  
         private TargetBeanCollection targets;
 63  
 
 64  
         /**
 65  
          * The roles to which this rule grants access.
 66  
          */
 67  
         private RoleCollection roles;
 68  
 
 69  
         /**
 70  
          * The condition of this access rule.
 71  
          */
 72  
         private Predicate condition;
 73  
         
 74  
         /**
 75  
          * The obligations of this rule.
 76  
          */
 77  
         private ObligationBeanCollection obligations;
 78  
         
 79  
         //---- Constructors
 80  
 
 81  
         /**
 82  
          * Creates a target access rule.
 83  
          * @param serialNumber the serial number of this part.
 84  
          * @param targets a {@link TargetBeanCollection} to which this rule grants access.
 85  
          * @param roles a {@link Collection} of {@link Role}s that are granted access.
 86  
          * @since 0.1.0
 87  
          */
 88  
         protected BasicTargetAccessRule (
 89  
                 SerialNumber serialNumber,
 90  
                 TargetBeanCollection targets,
 91  
                 Collection<Role> roles
 92  
         ) {
 93  46
                 this(serialNumber, targets, roles, Predicate.TRUE, null);
 94  46
         }
 95  
 
 96  
         /**
 97  
          * Creates a target access rule.
 98  
          * @param serialNumber the serial number of this part.
 99  
          * @param targets a {@link TargetBeanCollection} to which this rule grants access.
 100  
          * @param roles a {@link Collection} of {@link Role}s that are granted access.
 101  
          * @param condition a {@link Predicate} of this rule.
 102  
          * @param obligations an {@link ObligationBeanCollection}.
 103  
          * @since 0.3.0
 104  
          */
 105  
         protected BasicTargetAccessRule (
 106  
                 SerialNumber serialNumber,
 107  
                 TargetBeanCollection targets,
 108  
                 Collection<Role> roles,
 109  
                 Predicate condition,
 110  
                 ObligationBeanCollection obligations
 111  
         ) {
 112  536
                 super(TargetAccessRuleBean.class, serialNumber);
 113  536
                 this.targets = new BasicTargetCollection(getSerialNumber().next());
 114  536
                 this.roles = RoleCollection.EMPTY;
 115  536
                 this.obligations = new BasicObligationCollection(getSerialNumber().next());
 116  536
                 setTargets(targets);
 117  536
                 setRoles(RoleCollection.create(roles));
 118  536
                 setCondition(condition);
 119  536
                 setObligations(obligations);
 120  536
         }
 121  
 
 122  
         //---- TargetAccessRule
 123  
         
 124  
         /**
 125  
          * @since 0.3.0
 126  
          */
 127  
         public AuthorizedRoles findAuthorizedRoleSet (
 128  
                 URI resourceUri,
 129  
                 String actionName,
 130  
                 List<?> arguments,
 131  
                 TimeStamp timeStamp
 132  
         ) {
 133  52
                 if (actionName == null || resourceUri == null || timeStamp == null || arguments == null) {
 134  0
                         throw new IllegalArgumentException(
 135  
                                 "ActionName, resourceUri, arguments, or time is null."
 136  
                         );
 137  
                 }
 138  
 
 139  52
                 for (TargetBean target : getTargets()) {
 140  52
                         final Action action = target.findAction(resourceUri, actionName, arguments);
 141  52
                         if (action != null) {
 142  13
                                 if (getCondition().matches(timeStamp, action.mapArguments(arguments))) {
 143  13
                                         return 
 144  
                                                 new AuthorizedRoles(
 145  
                                                         new HashSet<Role>(this.roles.toList()),
 146  
                                                         this.obligations
 147  
                                                 );
 148  
                                 }
 149  0
                                 return null;
 150  
                         }
 151  39
                 }
 152  39
                 return null;
 153  
         }
 154  
         
 155  
         //---- TargetAccessRuleBean
 156  
 
 157  
         /**
 158  
          * @since 0.3.0
 159  
          */
 160  
         public TargetBeanCollection getTargets () {
 161  1328
                 return this.targets;
 162  
         }
 163  
 
 164  
         /**
 165  
          * @since 0.3.0
 166  
          */
 167  
         public void setTargets (TargetBeanCollection targets) {
 168  536
                 final TargetBeanCollection oldTargets = getTargets();
 169  536
                 if (targets == null) {
 170  1
                         this.targets = new BasicTargetCollection(getSerialNumber().next());
 171  
                 } else {
 172  535
                         this.targets = new BasicTargetCollection(getSerialNumber().next(), targets.toList());
 173  
                 }
 174  536
                 firePropertyChange("targets", oldTargets, getTargets());
 175  536
         }
 176  
 
 177  
         /**
 178  
          * @since 0.1.0
 179  
          */
 180  
         public Predicate getCondition () {
 181  1227
                 return this.condition;
 182  
         }
 183  
 
 184  
         /**
 185  
          * @since 0.1.0
 186  
          */
 187  
         public void setCondition (Predicate condition) {
 188  536
                 final Predicate oldCondition = getCondition();
 189  536
                 this.condition = condition;
 190  536
                 firePropertyChange("condition", oldCondition, getCondition());
 191  536
         }
 192  
 
 193  
         /**
 194  
          * @since 0.1.0
 195  
          */
 196  
         public RoleCollection getRoles () {
 197  1227
                 return this.roles;
 198  
         }
 199  
 
 200  
         /**
 201  
          * @since 0.1.0
 202  
          */
 203  
         public void setRoles (RoleCollection roles) {
 204  536
                 final RoleCollection oldRoles = getRoles();
 205  536
                 if (roles == null) {
 206  0
                         this.roles = RoleCollection.EMPTY;
 207  
                 } else {
 208  536
                         this.roles = roles;
 209  
                 }
 210  536
                 firePropertyChange("roles", oldRoles, getRoles());
 211  536
         }
 212  
         
 213  
         /**
 214  
          * @since 0.3.0
 215  
          */
 216  
         public ObligationBeanCollection getObligations () {
 217  1229
                 return this.obligations;
 218  
         }
 219  
 
 220  
         /**
 221  
          * @since 0.3.0
 222  
          */
 223  
         public void setObligations (ObligationBeanCollection obligations) {
 224  536
                 final ObligationBeanCollection oldObligations = getObligations();
 225  536
                 if (obligations == null) {
 226  64
                         this.obligations = new BasicObligationCollection(getSerialNumber().next());
 227  
                 } else {
 228  472
                         this.obligations = 
 229  
                                 new BasicObligationCollection(getSerialNumber().next(), obligations.toList());
 230  
                 }
 231  536
                 firePropertyChange("obligations", oldObligations, getObligations());
 232  536
         }
 233  
         
 234  
         /**
 235  
          * Removes a target child element.
 236  
          * @param part a {@link TargetBean}.
 237  
          * @since 0.1.0
 238  
          */
 239  
         public void removeTarget (TargetBean part) {
 240  0
                 final TargetBeanCollection oldTargets = this.getTargets();
 241  0
                 final List<TargetBean> list = new ArrayList<TargetBean>();
 242  
                 
 243  0
                 boolean removed = false;
 244  0
                 for (TargetBean target : oldTargets) {
 245  0
                         if (!removed && target.equals(part)) {
 246  0
                                 removed = true;
 247  
                         } else {
 248  0
                                 list.add(target);
 249  
                         }
 250  
                 }
 251  0
                 final TargetBeanCollection newTargets = 
 252  
                         new BasicTargetCollection(getSerialNumber().next(), list);
 253  
                 
 254  0
                 this.setTargets(newTargets);
 255  0
                 firePropertyChange("targets", oldTargets, newTargets);
 256  0
         }
 257  
         
 258  
         /**
 259  
          * Removes a obligation child element.
 260  
          * @param part a {@link ObligationBean}.
 261  
          * @since 0.3.0
 262  
          */
 263  
         public void removeObligation (ObligationBean part) {
 264  0
                 final ObligationBeanCollection oldObligations = this.getObligations();
 265  0
                 final List<ObligationBean> list = new ArrayList<ObligationBean>();
 266  
                 
 267  0
                 boolean removed = false;
 268  0
                 for (ObligationBean obligation : oldObligations) {
 269  0
                         if (!removed && obligation.equals(part)) {
 270  0
                                 removed = true;
 271  
                         } else {
 272  0
                                 list.add(obligation);
 273  
                         }
 274  
                 }
 275  0
                 final ObligationBeanCollection newObligations = 
 276  
                         new BasicObligationCollection(getSerialNumber().next(), list);
 277  
                 
 278  0
                 this.setObligations(newObligations);
 279  0
                 firePropertyChange("obligations", oldObligations, newObligations);
 280  0
         }
 281  
 
 282  
         //---- BasicPart
 283  
 
 284  
         /**
 285  
          * @since 0.1.0
 286  
          */
 287  
         @Override
 288  
         public boolean isPartValid (PartProblemReporter reporter) {
 289  
                 boolean valid;
 290  
 
 291  8
                 valid = true;
 292  
 
 293  
                 // Check condition.
 294  8
                 if (!isChildValid(reporter, getCondition())) {
 295  1
                         valid = false;
 296  1
                         reportProblem(reporter, ProblemMessage.illegalCondition);
 297  
                 }
 298  8
                 if (!isConditionMatchable()) {
 299  0
                         valid = false;
 300  0
                         reportProblem(reporter, ProblemMessage.illegalCondition);
 301  
                 }
 302  
                 
 303  
                 // Check for roles. 
 304  8
                 if (getRoles() == null || getRoles().isEmpty()) {
 305  3
                         valid = false;
 306  3
                         reportProblem(reporter, ProblemMessage.illegalRoles);
 307  
                 }
 308  
 
 309  
                 // Check for targets.
 310  8
                 if (!isChildCollectionValid(reporter, getTargets(), true, true, false, true, false)) {
 311  2
                         valid = false;
 312  2
                         reportProblem(reporter, ProblemMessage.illegalTargets);
 313  
                 }
 314  
 
 315  
                 // Check for obligations.
 316  8
                 if (!isChildCollectionValid(reporter, getObligations(), false, true, false, true, false)) {
 317  1
                         valid = false;
 318  1
                         reportProblem(reporter, ProblemMessage.illegalObligations);
 319  
                 }
 320  
         
 321  8
                 return valid;
 322  
         }
 323  
         
 324  
         /**
 325  
          * Check for each action of all targets of this rule that they are matchable and won't throw 
 326  
          * a runtime exception.
 327  
          * @return <code>true</code> if predicate is matchable.
 328  
          * @since 0.3.0
 329  
          */
 330  
         private boolean isConditionMatchable () {
 331  
                 // TODO Any (Written by David) The problem is, that the bean interface is used to check all
 332  
                 // actions of all targets of this rule. But isValid() will be a function of the PDP 
 333  
                 // interface and therefore all this information should be gathered over the PDP interface.
 334  8
                 for (TargetBean target : getTargets()) {
 335  7
                         for (ActionBean action : target.getActions()) {
 336  6
                                 for (Parameter parameter : action.getParameters()) {
 337  0
                                         final Map<String, Class<?>> arguments = new HashMap<String, Class<?>>();
 338  0
                                         arguments.put(parameter.getName(), parameter.getType());
 339  0
                                         if (!getCondition().isMatchable(arguments)) {
 340  0
                                                 return false;
 341  
                                         }
 342  0
                                 }
 343  
                         }
 344  
                 }
 345  8
                 return true;
 346  
         }
 347  
 
 348  
         /**
 349  
          * @since 0.1.0
 350  
          */
 351  
         @Override
 352  
         protected boolean comparablePart (BasicPart part) {
 353  104
                 return part instanceof TargetAccessRuleBean;
 354  
         }
 355  
 
 356  
         /**
 357  
          * @since 0.1.0
 358  
          */
 359  
         @Override
 360  
         protected boolean equalPart (BasicPart part) {
 361  52
                 final TargetAccessRuleBean targetAccessRule = (TargetAccessRuleBean) part;
 362  52
                 return
 363  
                         getTargets().equals(targetAccessRule.getTargets()) &&
 364  
                         getRoles().equals(targetAccessRule.getRoles()) &&
 365  
                         getCondition().equals(targetAccessRule.getCondition()) &&
 366  
                         getObligations().equals(targetAccessRule.getObligations());
 367  
         }
 368  
 
 369  
         /**
 370  
          * @since 0.1.0
 371  
          */
 372  
         @Override
 373  
         protected int partHashCode () {
 374  24
                 return multiHashCode(
 375  
                         listHashCode(getTargets().iterator()),
 376  
                         getRoles().hashCode(),
 377  
                         getCondition().hashCode(),
 378  
                         getObligations().hashCode()
 379  
                 );
 380  
         }
 381  
 
 382  
         /**
 383  
          * @since 0.1.0
 384  
          */
 385  
         @Override
 386  
         protected String getSimpleClassName () {
 387  0
                 return TargetAccessRuleBean.class.getSimpleName();
 388  
         }
 389  
 
 390  
         /**
 391  
          * @since 0.1.0
 392  
          */
 393  
         @Override
 394  
         protected void appendPartDetails (StringBuilder sb) {
 395  0
                 appendDetails(sb, "targets", getShortStringDetails(getTargets()));
 396  0
                 appendDetails(sb, "roles", getStringDetails(getRoles()));
 397  0
                 appendDetails(sb, "condition", getCondition());
 398  
                 // David Append obligation details.
 399  0
         }
 400  
         
 401  
         //---- BasicPartBean
 402  
 
 403  
         /**
 404  
          * @since 0.1.0
 405  
          */
 406  
         @Override
 407  
         public PartBean findBySerialNumber (SerialNumber partSerialNumber) {
 408  
                 PartBean bean;
 409  
 
 410  2
                 for (final TargetBean target : getTargets()) {
 411  2
                         bean = target.findBySerialNumber(partSerialNumber);
 412  2
                         if (bean != null) {
 413  1
                                 return bean;
 414  
                         }
 415  
                 }
 416  
 
 417  1
                 return super.findBySerialNumber(partSerialNumber);
 418  
         }
 419  
 
 420  
 }