Coverage Report - org.openpermis.policy.bean.basic.BasicDomain
 
Classes in this File Line Coverage Branch Coverage Complexity
BasicDomain
94%
63/67
85%
48/56
3.474
BasicDomain$1
100%
2/2
N/A
3.474
BasicDomain$2
77%
7/9
100%
2/2
3.474
BasicDomain$3
50%
1/2
N/A
3.474
BasicDomain$PathMatcher
N/A
N/A
3.474
 
 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 java.net.URI;
 13  
 
 14  
 import javax.naming.NamingException;
 15  
 import javax.naming.ldap.LdapName;
 16  
 
 17  
 import org.openpermis.policy.Domain;
 18  
 import org.openpermis.policy.bean.DomainBean;
 19  
 import org.openpermis.policy.bean.SerialNumber;
 20  
 
 21  
 /**
 22  
  * A basic implementation of {@link Domain}.
 23  
  * @since 0.1.0
 24  
  */
 25  
 public class BasicDomain
 26  
         extends BasicPartBean
 27  
         implements DomainBean
 28  
 {
 29  
 
 30  
         //---- Static
 31  
 
 32  
         /**
 33  
          * Determines if a path is contained within a domain path.
 34  
          * @since 0.3.0
 35  
          */
 36  
         public static interface PathMatcher {
 37  
                 /**
 38  
                  * Returns whether a domain contains a resource.
 39  
                  * @param domainPath the path for the domain.
 40  
                  * @param resourcePath the path for the resource.
 41  
                  * @return <code>true</code> if this matcher considers the resource to part of the domain.
 42  
                  * @since 0.3.0
 43  
                  */
 44  
                 boolean contains (String domainPath, String resourcePath);
 45  
         }
 46  
         
 47  
         /**
 48  
          * A path matcher where a domain contains a resource if the path of the resource starts
 49  
          * with the path of the domain.
 50  
          * <p>This matcher fits paths in a file system or a HTTP URL.
 51  
          * @since 0.3.0
 52  
          */
 53  1
         protected static final PathMatcher DIRECTORY_PATH_MATCHER =
 54  
                 new PathMatcher() {
 55  1
                         public boolean contains (String domainPath, String resourcePath) {
 56  15
                                 return resourcePath.startsWith(domainPath);
 57  
                         }
 58  
                 };
 59  
         
 60  
         /**
 61  
          * A path matcher where a domain contains a resource if both the domain and the resource
 62  
          * can be interpreted as LDAP distinguished names and the resource DN starts with the
 63  
          * domain DN.
 64  
          * @since 0.3.0
 65  
          */
 66  1
         protected static final PathMatcher LDAP_PATH_MATCHER =
 67  
                 new PathMatcher() {
 68  
                         public String toDN (String path) {
 69  166
                                 if (path.startsWith("/")) {
 70  15
                                         return path.substring(1);
 71  
                                 }
 72  151
                                 return path;
 73  
                         }
 74  
                         
 75  1
                         public boolean contains (String domainPath, String resourcePath) {
 76  
                                 try {
 77  83
                                         final LdapName domainName = new LdapName(toDN(domainPath));
 78  83
                                         final LdapName resourceName = new LdapName(toDN(resourcePath));
 79  83
                                         return resourceName.startsWith(domainName);
 80  0
                                 } catch (NamingException e) {
 81  0
                                         return false;
 82  
                                 }
 83  
                         }
 84  
                 };
 85  
         
 86  
         /**
 87  
          * A path matcher where no resource is part of any domain.
 88  
          * @since 0.3.0
 89  
          */
 90  1
         protected static final PathMatcher UNKNOWN_PATH_MATCHER =
 91  
                 new PathMatcher() {
 92  1
                         public boolean contains (String domainPath, String resourcePath) {
 93  0
                                 return false;
 94  
                         }
 95  
                 };
 96  
                 
 97  
         /**
 98  
          * @since 0.3.0
 99  
          */
 100  
         protected static final int HTTP_DEFAULT_PORT = 80;
 101  
 
 102  
         /**
 103  
          * @since 0.3.0
 104  
          */
 105  
         protected static final int HTTPS_DEFAULT_PORT = 443;
 106  
 
 107  
         /**
 108  
          * @since 0.3.0
 109  
          */
 110  
         protected static final int LDAP_DEFAULT_PORT = 389;
 111  
         
 112  
         /**
 113  
          * @since 0.3.0
 114  
          */
 115  
         protected static final int LDAPS_DEFAULT_PORT = 636;
 116  
 
 117  
         /**
 118  
          * @since 0.1.0
 119  
          */
 120  
         private static final long serialVersionUID = -5330051822856507613L;
 121  
 
 122  
         //---- Constructors
 123  
 
 124  
         /**
 125  
          * Creates a domain that initially includes only the specified {@link URI}.
 126  
          * @param serialNumber the serial number of this part.
 127  
          * @param uri the URI of this domain.
 128  
          * @since 0.1.0
 129  
          */
 130  
         protected BasicDomain (SerialNumber serialNumber, URI uri) {
 131  578
                 super(DomainBean.class, serialNumber);
 132  578
                 setIdentity(uri);
 133  578
         }
 134  
 
 135  
         //---- Methods
 136  
         
 137  
         /**
 138  
          * Returns whether the specified domain contains the specified resource.
 139  
          * @param domain the {@link URI} of the domain.
 140  
          * @param resource the {@link URI} of the resource.
 141  
          * @return <code>true</code> if this domain considers the resource to be included in the domain.
 142  
          * @see #contains(URI)
 143  
          * @since 0.3.0
 144  
          */
 145  
         protected boolean contains (URI domain, URI resource) {
 146  103
                 if (!schemesMatch(domain.getScheme(), resource.getScheme())) {
 147  1
                         return false;
 148  
                 }
 149  102
                 if (!hostsMatch(domain.getHost(), resource.getHost())) {
 150  2
                         return false;
 151  
                 }
 152  100
                 if (!portsMatch(getPort(domain), getPort(resource))) {
 153  2
                         return false;
 154  
                 }
 155  98
                 final PathMatcher pathMatcher = findPathMatcher(domain, resource);
 156  98
                 return pathMatcher.contains(getPath(domain), getPath(resource));
 157  
         }
 158  
 
 159  
         /**
 160  
          * Returns whether the specified schemes are compatible.
 161  
          * @param domainScheme the scheme of the domain.
 162  
          * @param resourceScheme the scheme of the resource.
 163  
          * @return <code>true</code> if both schemes are <code>null</code>, if both schemes are equal,
 164  
          * or if only the domain scheme is specified.
 165  
          * @since 0.3.0
 166  
          */
 167  
         protected boolean schemesMatch (String domainScheme, String resourceScheme) {
 168  103
                 if (domainScheme == null) {
 169  78
                         return resourceScheme == null;
 170  
                 }
 171  25
                 if (resourceScheme == null) {
 172  4
                         return true;
 173  
                 }
 174  21
                 return domainScheme.equals(resourceScheme);
 175  
         }
 176  
 
 177  
         /**
 178  
          * Returns whether the specified host names are compatible.
 179  
          * @param domainHost the host name of the domain.
 180  
          * @param resourceHost the host name of the resource.
 181  
          * @return <code>true</code> if both host names are <code>null</code>, if both host names
 182  
          * are equal, or if only the domain host is specified.
 183  
          * @since 0.3.0
 184  
          */
 185  
         protected boolean hostsMatch (String domainHost, String resourceHost) {
 186  102
                 if (domainHost == null) {
 187  85
                         return resourceHost == null;
 188  
                 }
 189  17
                 if (resourceHost == null) {
 190  3
                         return true;
 191  
                 }
 192  14
                 return domainHost.equals(resourceHost);
 193  
         }
 194  
         
 195  
         /**
 196  
          * Returns the port number of the specified URI.
 197  
          * @param uri the {@link URI} whose (default) port number to return.
 198  
          * @return the port number specified in the URI or the default port number for the
 199  
          * URI scheme. If neither scheme nor port are specified or the scheme is unknown,
 200  
          * -1 is returned.
 201  
          * @since 0.3.0
 202  
          */
 203  
         protected int getPort (URI uri) {
 204  200
                 int port = uri.getPort();
 205  200
                 if (port < 0) {
 206  188
                         port = getDefaultPort(uri.getScheme());
 207  
                 }
 208  200
                 return port;
 209  
         }
 210  
 
 211  
         /**
 212  
          * Returns the default port number for the specified URI scheme.
 213  
          * @param scheme a URI scheme.
 214  
          * @return the default port number for the scheme or -1 if the scheme is undefined or unknown.
 215  
          * @since 0.3.0
 216  
          */
 217  
         protected int getDefaultPort (String scheme) {
 218  188
                 if ("http".equalsIgnoreCase(scheme)) {
 219  12
                         return HTTP_DEFAULT_PORT;
 220  176
                 } else if ("https".equalsIgnoreCase(scheme)) {
 221  0
                         return HTTPS_DEFAULT_PORT;
 222  176
                 } else if ("ldap".equalsIgnoreCase(scheme)) {
 223  16
                         return LDAP_DEFAULT_PORT;
 224  160
                 } else if ("ldaps".equalsIgnoreCase(scheme)) {
 225  0
                         return LDAPS_DEFAULT_PORT;
 226  
                 }
 227  160
                 return -1;
 228  
         }
 229  
 
 230  
         /**
 231  
          * Returns whether port numbers of the specified domain and resource are compatible.
 232  
          * @param domainPort the port number of the domain.
 233  
          * @param resourcePort the port number of the resource.
 234  
          * @return <code>true</code> if both port numbers are unspecified, both port numbers
 235  
          * are equal, or the resource port is unspecified.
 236  
          * @since 0.3.0
 237  
          */
 238  
         protected boolean portsMatch (int domainPort, int resourcePort) {
 239  100
                 if (domainPort < 0) {
 240  78
                         return resourcePort < 0;
 241  
                 }
 242  22
                 if (resourcePort < 0) {
 243  4
                         return true;
 244  
                 }
 245  18
                 return domainPort == resourcePort;
 246  
         }
 247  
         
 248  
         /**
 249  
          * Returns a path matcher for the specified domain and resource URI.
 250  
          * @param domain the {@link URI} of the domain.
 251  
          * @param resource the {@link URI} of the resource.
 252  
          * @return a suitable {@link PathMatcher}. The returned matcher is never <code>null</code>,
 253  
          * but may be {@link #UNKNOWN_PATH_MATCHER}.
 254  
          * @since 0.3.0
 255  
          */
 256  
         protected PathMatcher findPathMatcher (URI domain, URI resource) {
 257  98
                 PathMatcher pathMatcher = findPathMatcherForScheme(domain.getScheme());
 258  98
                 if (pathMatcher == UNKNOWN_PATH_MATCHER) {
 259  78
                         pathMatcher = guessPathMatcherForPath(getPath(domain));
 260  
                 }
 261  98
                 if (pathMatcher == UNKNOWN_PATH_MATCHER) {
 262  6
                         pathMatcher = guessPathMatcherForPath(getPath(resource));
 263  
                 }
 264  98
                 return pathMatcher;
 265  
         }
 266  
         
 267  
         /**
 268  
          * Returns the path part of the specified URI.
 269  
          * @param uri a {@link URI}.
 270  
          * @return the path part of the URI or the scheme-specific part if the proper path is
 271  
          * <code>null</code>.
 272  
          * @since 0.3.0
 273  
          */
 274  
         protected String getPath (URI uri) {
 275  280
                 final String path = uri.getPath();
 276  280
                 if (path != null) {
 277  279
                         return path;
 278  
                 }
 279  1
                 return uri.getSchemeSpecificPart();
 280  
         }
 281  
 
 282  
         /**
 283  
          * Derives a path matcher given a URI scheme.
 284  
          * @param scheme a scheme for which to return a suitable {@link PathMatcher}.
 285  
          * @return a {@link PathMatcher}, equal to {@link #UNKNOWN_PATH_MATCHER} if the scheme
 286  
          * is undefined or unknown.
 287  
          * @since 0.3.0
 288  
          */
 289  
         protected PathMatcher findPathMatcherForScheme (String scheme) {
 290  98
                 if ("http".equalsIgnoreCase(scheme) || "https".equalsIgnoreCase(scheme)) {
 291  9
                         return DIRECTORY_PATH_MATCHER;
 292  
                 }
 293  89
                 if ("ldap".equalsIgnoreCase(scheme) || "ldaps".equalsIgnoreCase(scheme)) {
 294  11
                         return LDAP_PATH_MATCHER;
 295  
                 }
 296  78
                 return UNKNOWN_PATH_MATCHER;
 297  
         }
 298  
 
 299  
         /**
 300  
          * Derives a path matcher from special characters in a path.
 301  
          * @param path the path part of a URI.
 302  
          * @return a {@link PathMatcher}, equal to {@link #UNKNOWN_PATH_MATCHER} if the scheme
 303  
          * cannot be derived from the contents of the path.
 304  
          * @since 0.3.0
 305  
          */
 306  
         protected PathMatcher guessPathMatcherForPath (String path) {
 307  84
                 if (path.indexOf('/') > 0) {
 308  6
                         return DIRECTORY_PATH_MATCHER;
 309  
                 }
 310  78
                 if (path.indexOf(',') > 0) {
 311  72
                         return LDAP_PATH_MATCHER;
 312  
                 }
 313  6
                 return UNKNOWN_PATH_MATCHER;
 314  
         }
 315  
 
 316  
         //---- Domain
 317  
         
 318  
         /**
 319  
          * @since 0.1.0
 320  
          */
 321  
         public boolean contains (URI entity) {
 322  103
                 if (entity == null) {
 323  0
                         return false;
 324  
                 }
 325  103
                 return contains(getIdentity().normalize(), entity.normalize());
 326  
         }
 327  
 
 328  
         //---- BasicPart
 329  
 
 330  
         /**
 331  
          * Checks that the part supplied is an domain.
 332  
          * @since 0.1.0
 333  
          */
 334  
         @Override
 335  
         protected final boolean comparablePart (BasicPart part) {
 336  240
                 return part instanceof Domain;
 337  
         }
 338  
 
 339  
         /**
 340  
          * @since 0.1.0
 341  
          */
 342  
         @Override
 343  
         protected String getSimpleClassName () {
 344  0
                 return BasicDomain.class.getSimpleName();
 345  
         }
 346  
 
 347  
 }