Clover Coverage Report
Coverage timestamp: Sun Mar 23 2008 08:24:39 GMT
79   274   30   11.29
58   128   0.46   7
7     5.14  
1    
 
 
  DITSubtree       Line # 47 79 30 63.2% 0.6319444
 
  (1)
 
1    /*
2    * Copyright (c) 2000-2005, University of Salford
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are met:
7    *
8    * Redistributions of source code must retain the above copyright notice, this
9    * list of conditions and the following disclaimer.
10    *
11    * Redistributions in binary form must reproduce the above copyright notice,
12    * this list of conditions and the following disclaimer in the documentation
13    * and/or other materials provided with the distribution.
14    *
15    * Neither the name of the University of Salford nor the names of its
16    * contributors may be used to endorse or promote products derived from this
17    * software without specific prior written permission.
18    *
19    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22    * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29    * POSSIBILITY OF SUCH DAMAGE.
30    */
31   
32    package issrg.pba.rbac.policies;
33   
34    import issrg.pba.rbac.LDAPDNPrincipal;
35    import issrg.utils.RFC2253ParsingException;
36    import issrg.utils.repository.Entry;
37   
38    /**
39    * This is the object that represents a subtree of entries in LDAP DIT. It can
40    * specify a
41    * subtree, excluding subtrees, and does object class match.
42    *
43    * @author A Otenko
44    * @version 1.0
45    */
46   
 
47    public class DITSubtree implements Subtree {
48    /**
49    * This is the subtree root node.
50    */
51    protected LDAPDNPrincipal subtree;
52   
53    protected int min;
54    protected int max;
55   
56    /**
57    * This is an array of object classes, allowed in this subtree. Can be null,
58    * if no restrictions on object class are applied.
59    */
60    protected String [] objectclasses;
61   
62    /**
63    * This is an array of exclusion subtrees. Can be null, if no exclusion
64    * subtrees have been specified.
65    */
66    protected Subtree [] exclusive;
67   
 
68  0 toggle protected DITSubtree(){}
69   
70    /**
71    * This constructor can build an object out of the full subtree specification.
72    *
73    * @param subtree is the LDAP DN of the root node of the subtree; if null,
74    * means "any DN is a subtree": the World
75    * @param min is the integer lower margin of the subtree; cannot be less than
76    * 0; see also max
77    * @param max is the integer higher margin of the subtree; together with min
78    * they define the minimum and maximum length of the matching DN,
79    * relative
80    * to the subtree DN; value of -1 means "unlimited length", no other
81    * negative values
82    * are accepted for max
83    * @param objectClass is the array of LDAP object classes that the subtree
84    * entry can be of; if null, no restrictions on the objectClass are
85    * applied
86    * @param exclude is an array of subtrees that an entry cannot be a part of;
87    * if null, no subtrees are excluded
88    */
 
89  3741 toggle public DITSubtree(LDAPDNPrincipal subtree, int min, int max,
90    String [] objectClass, Subtree [] exclude) {
91   
92  3741 this.subtree = subtree;
93  3741 objectclasses = objectClass;
94  3741 exclusive = exclude;
95   
96  3741 this.min=min;
97  3741 this.max=max;
98   
99  3741 if (min<0 || max<-1){
100  0 throw new IllegalArgumentException("Subtree margins exceed the allowed range");
101    }
102    }
103   
104    /**
105    * This method tests whether or not the given entry belongs to this subtree.
106    * If the entry's DN maps below the subtree root node and its object class is
107    * at least one of the allowed object classes, and the entry is not an entry
108    * of any of the exclusion subtrees, the method returns true. It returns false
109    * otherwise.
110    *
111    * @param entry is the LDAPEntry; it can tell the DN and the objectClass of
112    * the entry
113    *
114    * @return true, if the entry is included in the subtree and is of one of the
115    * objectClasses, specified at the construction time, and it is not
116    * contained in any of the exclusion subtrees
117    */
 
118  22404 toggle public boolean contains(LDAPEntry entry){
119  22404 boolean result=false;
120   
121  22404 if (subtree!=null){
122  22404 String [][][] alien = entry.getDN().getParsedDN();
123  22404 String [][][] subtree = this.subtree.getParsedDN();
124   
125  22404 int o = alien.length-subtree.length;
126  22404 if (o>=min && (max==-1 || o<=max)){
127   
128  20802 result=true;
129  20802 match_DN:
130  71280 for (int i=subtree.length; i-->0; ){ // for each RDN
131  63125 int i1=o+i;
132  63125 if (alien[i1].length!=subtree[i].length){
133  0 result=false;
134  0 break;
135    }
136   
137  113603 for (int j=0; j<subtree[i].length; j++){ // for each AVA in the RDN of the subtree
138  63125 String s = subtree[i][j][0].toUpperCase().intern(); // attribute name
139   
140  63125 int k;
141   
142  63131 for (k=0; k<alien[i1].length; k++){ // find matching AVA in the RDN of the alien
143  63125 if (s==alien[i1][k][0].toUpperCase().intern()){
144  63119 break; // found the right attribute in the DN
145    }
146    }
147   
148    // k still points into the right row in the alien[i] array
149   
150  63125 if (k>=alien[i1].length){ // no matching attribute found
151  6 result=false;
152  6 break match_DN;
153    }
154   
155    // the values are in real string representation so they must be just compared
156    // as case-insensitive strings
157   
158    /*
159    * TODO: what about comparing binary values? (toUpperCase might spoil them...)
160    */
161   
162  63119 if (subtree[i][j][1].toUpperCase().intern()!=alien[i1][k][1].toUpperCase().intern()){
163  12641 result=false;
164  12641 break match_DN;
165    }
166    }
167    }
168   
169    // if gone through the loop up to this point, then the DN matched the subtree specification
170   
171    //System.out.println("\t\t*** SUBTREE MATCHING ***\n\t"+s+" < "+s1); //*****
172   
173    //System.out.println("\t"+result); //*****
174    }
175    }
176   
177  22404 if (objectclasses!=null && result){
178  840 result=false;
179  1680 for (int i=0; i<objectclasses.length; i++){
180  0 if (!(result=entry.isObjectClass(objectclasses[i]))){ // this makes it loop as long as the target matches the object class
181    // the result will either always be true, or will become false and the loop breaks the same instant
182  0 break;
183    }
184   
185    //System.out.println("\tis object class: "+oc[i]); //*****
186   
187    }
188    }
189   
190  22404 if (exclusive!=null && result){
191    //System.out.println("\tsome exclusions"); //*****
192  9175 for (int i=0; i<exclusive.length; i++){
193  0 if (!(result=!exclusive[i].contains(entry))){ // note, that it is not a != comparison; result is assigned the inversion of the method return value
194    /* so: the loop must go through all exclusive trees, and break as soon as
195    * either of the exclusion trees contains an entry, assigning false to the result
196    */
197    //System.out.println("\tone exclusion matches. Excluded "+entry.getDN().getName()); //*****
198  8 break;
199    }
200    }
201    }
202   
203    //System.out.println("\ttotal: "+result); //*****
204  22404 return result;
205    }
206   
207    /**
208    * This method checks whether this Subtree contains a given Entry. If the
209    * entry is not an LDAPEntry, returns false; otherwise returns the same result
210    * as contains(LDAPEntry e)
211    */
 
212  22507 toggle public boolean contains(Entry e){
213  22507 return (e instanceof LDAPEntry)? contains((LDAPEntry)e): false;
214    }
215   
 
216  3975 toggle public String toString(){
217  3975 String exclude=null;
218  3975 if (exclusive!=null){
219  3975 exclude=", excluding [";
220  3975 for (int i=0; i<exclusive.length; i++){
221  0 exclude+=(i==0?"":", ")+exclusive[i].toString();
222    }
223  3975 exclude+="]";
224    }
225   
226  3975 String objClasses=null;
227  3975 if (objectclasses!=null){
228  210 objClasses=", objectClasses {";
229  420 for (int i=0; i<objectclasses.length; i++){
230  210 objClasses+=(i==0?"":", ")+objectclasses[i];
231    }
232  210 objClasses="}";
233    }
234  3975 return "DITSubtree with base DN="+subtree.getName()+", min="+min+", max="+max+
235  3975 (exclude==null?"":exclude)+(objClasses==null?"":objClasses);
236    }
237   
238    /**
239    * This method excludes the specified Entry from the Subtree, if it is an
240    * LDAPEntry; otherwise does nothing.
241    */
 
242  0 toggle public void excludeEntry(Entry e) {
243  0 if (!(e instanceof LDAPEntry)) return;
244  0 Subtree[] r;
245  0 if (exclusive == null) {
246  0 r = new Subtree[1];
247  0 r[0]=new DITSubtree(((LDAPEntry)e).getDN(), 0, -1, null, null);
248  0 exclusive = r;
249    } else {
250  0 r = new Subtree[exclusive.length];
251  0 System.arraycopy(exclusive, 0, r, 0, exclusive.length);
252  0 exclusive = new Subtree[r.length + 1];
253  0 System.arraycopy(r, 0, exclusive, 0, r.length);
254  0 exclusive[r.length] = new DITSubtree(((LDAPEntry) e).getDN(), 0, -1, null, null);
255    }
256    }
257   
 
258  0 toggle public Object clone() {
259  0 String[] a = null;
260  0 if (objectclasses != null) {
261  0 a = new String[objectclasses.length];
262  0 System.arraycopy(objectclasses, 0, a, 0, a.length);
263    }
264  0 Subtree[] b = null;
265  0 if (exclusive != null) {
266  0 b = new Subtree[exclusive.length];
267  0 System.arraycopy(exclusive, 0, b, 0, b.length);
268    }
269   
270  0 try {
271  0 return new DITSubtree(new LDAPDNPrincipal(subtree.getName()), min, max, a, b);
272  0 } catch (RFC2253ParsingException pe) {pe.printStackTrace(); return null;}
273    }
274    }