Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A class that handles checking permssision for a document
4
               and subtree in a document 
5
 *             
6
 *  Copyright: 2000 Regents of the University of California and the
7
 *             National Center for Ecological Analysis and Synthesis
8
 *    Authors: Chad Berkley
9
 *    Release: @release@
10
 *
11
 *   '$Author: tao $'
12
 *     '$Date: 2003-04-07 17:48:56 -0700 (Mon, 07 Apr 2003) $'
13
 * '$Revision: 1521 $'
14
 *
15
 * This program is free software; you can redistribute it and/or modify
16
 * it under the terms of the GNU General Public License as published by
17
 * the Free Software Foundation; either version 2 of the License, or
18
 * (at your option) any later version.
19
 *
20
 * This program is distributed in the hope that it will be useful,
21
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23
 * GNU General Public License for more details.
24
 *
25
 * You should have received a copy of the GNU General Public License
26
 * along with this program; if not, write to the Free Software
27
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28
 */
29
package edu.ucsb.nceas.metacat;
30
 
31
import java.sql.*;
32
import java.util.Enumeration;
33
import java.util.Hashtable;
34
import java.util.Stack;
35
import java.util.Vector;
36

    
37
public class PermissionController
38
{
39
   private String docId = null;
40
   private boolean hasSubTreeAccessControl = false; // flag if has a subtree
41
                                                    // access for this docid
42
   private Vector subTreeList = new Vector();
43
   
44
   
45
   /**
46
    * Constructor for PermissionController
47
    * @param myDocid      the docid need to access
48
    */
49
   public PermissionController(String myDocid) throws McdbException
50
   {
51
     // Get rid of rev number
52
     docId = MetaCatUtil.getDocIdFromString(myDocid);
53
     hasSubTreeAccessControl = checkSubTreeAccessControl();
54
   }
55
   
56
   /**
57
    * Return if a document has subtree access control
58
    */
59
   public boolean hasSubTreeAccessControl()
60
   {
61
     return hasSubTreeAccessControl;
62
   }
63
   
64
   /*
65
    * Go through the access table and find if has subtree access control
66
    * if has, store the subtree into list and return true. Otherwise, 
67
    * return false
68
    */
69
  private boolean checkSubTreeAccessControl() throws McdbException
70
  {
71
    boolean flag = false;
72
    PreparedStatement pStmt=null;
73
    ResultSet rs=null;
74
    DBConnection conn=null;
75
    int serialNumber=-1;
76
    String query="SELECT subtreeid, startnodeid, endnodeid from xml_access " +
77
                 "where docid =? ";
78
    
79
    try
80
    {
81
      //check out DBConnection
82
      conn=DBConnectionPool.getDBConnection("PermissionController.hasSubTreeA");
83
      serialNumber=conn.getCheckOutSerialNumber();
84
      
85
      pStmt=conn.prepareStatement(query);
86
      //bind the value to query
87
      pStmt.setString(1, docId);
88
      //execute the query
89
      pStmt.execute();
90
      rs=pStmt.getResultSet();
91
      //process the result
92
      while (rs.next()) //
93
      {
94
        String subTreeId = rs.getString(1);
95
        MetaCatUtil.debugMessage("subtreeid: "+subTreeId, 35);
96
        long startNodeId = rs.getLong(2);
97
        MetaCatUtil.debugMessage("subtree startNodeId: "+startNodeId, 35);
98
        long endNodeId = rs.getLong(3);
99
        MetaCatUtil.debugMessage("subtree endNodeId: "+endNodeId, 35);
100
        // if startnodeid field in table is empty,startNodeId will be 0
101
        if (subTreeId != null && startNodeId != 0 && startNodeId != 0)
102
        {
103
          flag = true;// has subtree control
104
          SubTree tree = new SubTree();
105
          tree.setSubTreeId(subTreeId);
106
          tree.setStartNodeId(startNodeId);
107
          tree.setEndNodeId(endNodeId);
108
          subTreeList.add(tree);
109
         }
110
      }
111
    }//try
112
    catch (SQLException e)
113
    {
114
      throw new McdbException(e);
115
    }
116
    finally
117
    {
118
      try
119
      {
120
        pStmt.close();
121
      }
122
      catch(SQLException ee)
123
      {
124
        throw new McdbException(ee);
125
      }
126
      finally
127
      {
128
        DBConnectionPool.returnDBConnection(conn, serialNumber);
129
      }
130
    }
131
    return flag;
132
  }
133
   
134
  /**
135
    * Check from db connection if at least one of the list of @principals
136
    * @param user  the user name
137
    * @param groups  the groups which the use is in
138
    * @param myPermission  permission type to check for
139
    */
140
  public boolean hasPermission(String user, String[]groups, String myPermission) 
141
                              throws SQLException, Exception
142
  {
143
    boolean hasPermission=false;
144
    String [] userPackage=null;
145
    int permission =AccessControlList.intValue(myPermission);
146
       
147
    //for the commnad line invocation
148
    if ((user==null) && (groups==null || groups.length==0))
149
    {
150
      return true;
151
    }
152
   
153
    //create a userpackage including user, public and group member
154
    userPackage=createUsersPackage(user, groups);
155
    
156
    //if the requested document is access documents and requested permission
157
    //is "write", the user should have "all" right
158
    if (isAccessDocument(docId) && (permission == AccessControlInterface.WRITE))
159
    {
160
      hasPermission = hasPermission(userPackage,docId, 7);// 7 is all permission
161
    }//if
162
    else //in other situation, just check the request permission
163
    {
164
    
165
      // Check for @permission on @docid for @user and/or @groups
166
      hasPermission = hasPermission(userPackage,docId, permission);
167
     
168
    }//else
169
    
170
    return hasPermission;
171
  }
172
  
173
 
174
  /**
175
    * Check from db connection if the users in String array @principals has
176
    * @permission on @docid* 
177
    * @param principals, names in userPakcage need to check for @permission
178
    * @param docid, document identifier to check on
179
    * @param permission, permission (write or all...) to check for 
180
    */
181
  private boolean hasPermission(String [] principals, String docId,
182
                                           int permission)
183
                         throws SQLException
184
  {
185
    String subTreeId = null;// this is for top level, so subtree id is null
186
    try 
187
    {
188
      //first, if there is a docid owner in user package, return true
189
      //because doc owner has all permssion 
190
      if (containDocumentOwner(principals, docId))
191
      {
192
          
193
          return true;
194
      }
195
      
196
      //If there is no owner in user package, checking the table
197
      //check perm_order
198
      if (isAllowFirst(principals, docId, subTreeId))
199
      {
200
        
201
        if (hasExplicitDenyRule(principals, docId, permission, subTreeId))
202
        {
203
          //if it is allowfirst and has deny rule(either explicit )
204
          //deny access
205
          return false;
206
        }//if
207
        else if ( hasAllowRule(principals, docId, permission, subTreeId))
208
        {
209
          //if it is allowfirst and hasn't deny rule and has allow rule
210
          //allow access
211
          return true;
212
        }//else if
213
        else
214
        {
215
          //other situation deny access
216
          return false;
217
        }//else
218
     }//if isAllowFirst
219
     else //denyFirst
220
     {
221
       if (hasAllowRule(principals, docId, permission, subTreeId))
222
       {
223
         //if it is denyFirst and has allow rule, allow access
224
         return true;
225
       }
226
       else
227
       {
228
         //if it is denyfirst but no allow rule, deny access
229
         return false;
230
       }
231
     }//else denyfirst
232
    }//try
233
    catch (Exception e)
234
    {
235
      MetaCatUtil.debugMessage("There is a exception in hasPermission method: "
236
                         +e.getMessage(), 50);
237
    }
238
   
239
    return false;
240
  }//hasPermission
241
  
242
  /**
243
   * The method to determine of a node can be access by a user just by subtree
244
   * access control
245
   */
246
  public boolean hasPermissionForSubTreeNode(String user, String[] groups,
247
                                             String myPermission, long nodeId)
248
                                             throws McdbException
249
  {
250
    boolean flag = true;
251
    // Get unaccessble subtree for this user
252
    Hashtable unaccessableSubTree = hasUnaccessableSubTree(user, groups, 
253
                                                           myPermission);
254
    Enumeration en = unaccessableSubTree.elements();
255
    while (en.hasMoreElements())
256
    {
257
      SubTree tree = (SubTree)en.nextElement();
258
      long start = tree.getStartNodeId();
259
      long stop  = tree.getEndNodeId();
260
      // nodeid in unaccessablesubtree, return false
261
      if ( nodeId >= start && nodeId <= stop)
262
      {
263
        flag = false;
264
        break;
265
      }
266
    }
267
    return flag;
268
  }
269
  /**
270
   * This method will return a hasTable of subtree which user doesn't has the 
271
   * permssion to access
272
   * @param user  the user name
273
   * @param groups  the groups which the use is in
274
   * @param myPermission  permission type to check for
275
   */
276
  public Hashtable hasUnaccessableSubTree(String user, String[] groups, 
277
                                       String myPermission) throws McdbException
278
  {
279
    Hashtable resultUnaccessableSubTree = new Hashtable();
280
    String [] principals=null;
281
    int permission =AccessControlList.intValue(myPermission);
282
    
283
    //for the commnad line invocation return null(no unaccessable subtree)
284
    if ((user==null) && (groups==null || groups.length==0))
285
    {
286
      return resultUnaccessableSubTree;
287
    }
288
    
289
    //create a userpackage including user, public and group member
290
    principals=createUsersPackage(user, groups);
291
    //for the document owner return null(no unaccessable subtree)
292
    try
293
    {
294
      if (containDocumentOwner(principals, docId))
295
      {
296
       return resultUnaccessableSubTree;
297
      }
298
    }
299
    catch (SQLException ee)
300
    {
301
      throw new McdbException(ee);
302
    }
303
    
304
    // go through every subtree which has access control
305
    for (int i = 0; i< subTreeList.size(); i++)
306
    {
307
      SubTree tree = (SubTree)subTreeList.elementAt(i);
308
      String subTreeId = (String)(tree.getSubTreeId());
309
     
310
      if (subTreeId != null)
311
      {
312
        try
313
        {
314
          if (isAllowFirst(principals, docId, subTreeId))
315
          {
316
           
317
            if (hasExplicitDenyRule(principals, docId, permission, subTreeId))
318
            {
319
             
320
             //if it is allowfirst and has deny rule
321
              // put the subtree into unaccessable vector
322
              if (!resultUnaccessableSubTree.containsKey(subTreeId))
323
              {
324
                resultUnaccessableSubTree.put(subTreeId, tree);
325
              }
326
            }//if
327
            else if ( hasAllowRule(principals, docId, permission, subTreeId))
328
            {
329
              //if it is allowfirst and hasn't deny rule and has allow rule
330
              //allow access do nothing
331
              
332
            }//else if
333
            else
334
            {
335
              //other situation deny access
336
              if (!resultUnaccessableSubTree.containsKey(subTreeId))
337
              {
338
                resultUnaccessableSubTree.put(subTreeId, tree);
339
              }
340
             
341
            }//else
342
          }//if isAllowFirst
343
          else //denyFirst
344
          {
345
            if (hasAllowRule(principals, docId, permission,subTreeId))
346
            {
347
              //if it is denyFirst and has allow rule, allow access, do nothing
348
           
349
            }
350
            else
351
            {
352
              //if it is denyfirst but no allow rule, deny access
353
              // add into vector
354
              if (!resultUnaccessableSubTree.containsKey(subTreeId))
355
              {
356
                resultUnaccessableSubTree.put(subTreeId, tree);
357
              }
358
            }
359
          }//else denyfirst
360
        }//try
361
        catch( Exception e)
362
        {
363
          MetaCatUtil.debugMessage("error in PermissionControl.has" +
364
                                   "UnaccessableSubTree "+e.getMessage(), 30);
365
          throw new McdbException(e);
366
        }
367
      }//if
368
    }//for
369
    // merge the subtree if a subtree is another subtree'subtree    
370
    resultUnaccessableSubTree = mergeEquivalentSubtree(resultUnaccessableSubTree);
371
    return resultUnaccessableSubTree;
372
  }//hasUnaccessableSubtree
373
  
374
  
375
  /* 
376
   * A method to merge nested subtree into bigger one. For example subtree b
377
   * is a subtree of subtree a. And user doesn't have read permission for both
378
   * so we only use subtree a is enough.
379
   */
380
  private Hashtable mergeEquivalentSubtree(Hashtable unAccessSubTree)
381
  {
382
    Hashtable newSubTreeHash = new Hashtable();
383
    boolean   needDelete = false;
384
    // check the parameters
385
    if (unAccessSubTree == null || unAccessSubTree.isEmpty())
386
    {
387
      return newSubTreeHash;
388
    }
389
    else
390
    {
391
      // look every subtree start point and stop point, to see if it is embedded
392
      // in another one. If embedded, they are equavelent and we can use bigger
393
      // one to replace smaller one
394
      Enumeration en = unAccessSubTree.elements();
395
      while (en.hasMoreElements())
396
      {
397
        SubTree tree    = (SubTree)en.nextElement();
398
        String  treeId  = tree.getSubTreeId();
399
        long    startId = tree.getStartNodeId();
400
        long    endId   = tree.getEndNodeId();
401
        
402
        Enumeration enu = unAccessSubTree.elements();
403
        while (enu.hasMoreElements())
404
        {
405
          SubTree subTree = (SubTree)enu.nextElement();
406
          String subTreeId= subTree.getSubTreeId();
407
          long   subTreeStartId = subTree.getStartNodeId();
408
          long   subTreeEndId   = subTree.getEndNodeId();
409
          //compare and if the first subtree is a subtree of the second
410
          // one, set neeDelete true
411
          if (startId > subTreeStartId && endId < subTreeEndId)
412
          {
413
            needDelete = true;
414
            MetaCatUtil.debugMessage("the subtree: "+ treeId + 
415
                                     " need to be get rid of from unaccessable"+
416
                                     " subtree list becuase it is a subtree of"+
417
                                     " another subtree in the list", 45);
418
            break;
419
          }//if
420
        }//while
421
        // if not need to delete, put the subtree into hash
422
        if (!needDelete)
423
        {
424
          newSubTreeHash.put(treeId, tree);
425
        }
426
        //reset needDelete
427
        needDelete = false;
428
      }//while
429
      return newSubTreeHash;
430
    }//else
431
  }
432
  
433
  /**
434
    * Check if a document id is a access document. Access document need user
435
    * has "all" permission to access it.
436
    * @param docId, the document id need to be checked
437
    */
438
    private boolean isAccessDocument(String docId) throws SQLException
439
    {
440
      //detele the rev number if docid contains it
441
      docId=MetaCatUtil.getDocIdFromString(docId);
442
      PreparedStatement pStmt=null;
443
      DBConnection conn = null;
444
      int serialNumber = -1;
445
      try
446
      {
447
        //check out DBConnection
448
        conn=DBConnectionPool.getDBConnection("PermissionControl.isAccessDoc");
449
        serialNumber=conn.getCheckOutSerialNumber();
450
        pStmt = conn.prepareStatement("select 'x' from xml_access where " +
451
                                      "accessfileid like '" + docId +  "'");
452
        pStmt.execute();
453
        ResultSet rs = pStmt.getResultSet();
454
        boolean hasRow = rs.next();
455
        pStmt.close();
456
        if(hasRow)
457
        {
458
          return true;
459
        }
460
      }
461
      catch(SQLException e)
462
      {
463
       
464
        throw new SQLException("PermissionControl.isAccessDocument " +
465
                     "Error checking" +
466
                     " on document " + docId + ". " + e.getMessage());
467
      }
468
      finally
469
      {
470
        try
471
        {
472
           pStmt.close();
473
        }
474
        finally
475
        {
476
          DBConnectionPool.returnDBConnection(conn, serialNumber);
477
        }
478
      }
479
      return false;
480
    }//isAccessDocument
481
     
482
  
483
  
484
  /**
485
    * Check if a stirng array contains a given documents' owner
486
    * @param principals, a string array storing the username, groups name and
487
    * public.
488
    * @param docid, the id of given documents 
489
    */ 
490
  private boolean containDocumentOwner( String[] principals, String docId)
491
                    throws SQLException
492
  {
493
    int lengthOfArray=principals.length;
494
    boolean hasRow; 
495
    PreparedStatement pStmt=null;
496
    DBConnection conn = null;
497
    int serialNumber = -1;
498
    
499
    try
500
    {
501
      //check out DBConnection
502
     conn=DBConnectionPool.getDBConnection("PermissionControl.containDocOnwer");
503
      serialNumber=conn.getCheckOutSerialNumber();
504
      pStmt = conn.prepareStatement(
505
                "SELECT 'x' FROM xml_documents " +
506
                "WHERE docid = ? AND user_owner = ?"); 
507
      //check every element in the string array too see if it conatains
508
      //the owner of document
509
      for (int i=0; i<lengthOfArray; i++)
510
      {
511
             
512
        // Bind the values to the query
513
        pStmt.setString(1, docId);
514
        pStmt.setString(2, principals[i]);
515

    
516
        pStmt.execute();
517
        ResultSet rs = pStmt.getResultSet();
518
        hasRow = rs.next();
519
        if (hasRow) 
520
        {
521
          pStmt.close();
522
          return true;
523
        }//if    
524
     
525
      }//for
526
    }//try
527
    catch (SQLException e) 
528
    {
529
        pStmt.close();
530
       
531
        throw new 
532
        SQLException("PermissionControl.hasPermission(). " +
533
                     "Error checking ownership for " + principals[0] +
534
                     " on document #" + docId + ". " + e.getMessage());
535
    }//catch
536
    finally
537
    {
538
      try
539
      {
540
        pStmt.close();
541
      }
542
      finally
543
      {
544
        DBConnectionPool.returnDBConnection(conn, serialNumber);
545
      }
546
    }
547
    return false; 
548
  }//containDocumentOwner
549
  
550
  /**
551
    * Check if the permission order for user at that documents is allowFirst
552
    * @param principals, list of names of principals to check for 
553
    * @param docid, document identifier to check for
554
    */
555
  private boolean isAllowFirst(String [] principals, String docId, 
556
                               String subTreeId)
557
                  throws SQLException, Exception
558
  {
559
    int lengthOfArray=principals.length;
560
    boolean hasRow;
561
    PreparedStatement pStmt = null;
562
    DBConnection conn = null;
563
    int serialNumber = -1;
564
    String sql = null;
565
    boolean topLever =false;
566
    if (subTreeId == null)
567
    {
568
      //top level
569
      topLever = true;
570
      sql = "SELECT perm_order FROM xml_access " +
571
            "WHERE principal_name= ? AND docid = ? AND subtreeid is NULL";
572
    }
573
    else
574
    {
575
      //sub tree level
576
      sql = "SELECT perm_order FROM xml_access " +
577
            "WHERE principal_name= ? AND docid = ? AND subtreeid = ?";
578
    }
579
    
580
    try
581
    {
582
      //check out DBConnection
583
      conn=DBConnectionPool.getDBConnection("AccessControlList.isAllowFirst");
584
      serialNumber=conn.getCheckOutSerialNumber();
585
    
586
      //select permission order from database
587
      pStmt = conn.prepareStatement(sql);
588
   
589
      //check every name in the array
590
      for (int i=0; i<lengthOfArray;i++)
591
      {
592
        //bind value
593
        pStmt.setString(1, principals[i]);//user name
594
        pStmt.setString(2, docId);//docid
595
        
596
        // if subtree, we need set subtree id 
597
        if (!topLever)
598
        {
599
          pStmt.setString(3, subTreeId);
600
        }
601
    
602
        pStmt.execute();
603
        ResultSet rs = pStmt.getResultSet();
604
        hasRow=rs.next();
605
        if (hasRow)
606
        {
607
          //get the permission order from data base
608
          String permissionOrder=rs.getString(1);
609
          //if the permission order is "allowFirst
610
          if (permissionOrder.equalsIgnoreCase(AccessControlInterface.ALLOWFIRST))
611
          {
612
            pStmt.close();
613
            return true;
614
          }
615
          else
616
          {
617
            pStmt.close();
618
            return false;
619
          }
620
        }//if
621
      }//for
622
    }//try
623
    catch (SQLException e)
624
    {
625
      throw e;
626
    }
627
    finally
628
    {
629
      try
630
      {
631
        pStmt.close();
632
      }
633
      finally
634
      {
635
        DBConnectionPool.returnDBConnection(conn, serialNumber);
636
      }
637
    }
638
    
639
    //if reach here, means there is no permssion record for given names and 
640
    //docid. So throw a exception.
641
    
642
    throw new Exception("There is no permission record for user"+principals[0]+
643
                        "at document "+docId);
644
        
645
  }//isAllowFirst
646
  
647
  /**
648
    * Check if the users array has allow rules for given users, docid and 
649
    * permission.
650
    * If it has permission rule and ticket count is greater than 0, the ticket
651
    * number will decrease one for every allow rule
652
    * @param principals, list of names of principals to check for 
653
    * @param docid, document identifier to check for
654
    * @param permission, the permssion need to check
655
    */
656
  private boolean hasAllowRule(String [] principals, String docId, 
657
                                  int permission, String subTreeId)
658
                  throws SQLException, Exception
659
 {
660
   int lengthOfArray=principals.length;
661
   boolean allow=false;//initial value is no allow rule
662
   ResultSet rs;
663
   PreparedStatement pStmt = null;
664
   int permissionValue=permission;
665
   int permissionValueInTable;
666
   int ticketCount;
667
   DBConnection conn = null;
668
   int serialNumber = -1;
669
   boolean topLever = false;
670
   String sql = null;
671
   if (subTreeId == null)
672
   {
673
     // for toplevel
674
     topLever = true;
675
     sql = "SELECT permission FROM xml_access WHERE docid = ? " +  
676
           "AND principal_name = ? AND perm_type = ? AND subtreeid is NULL";
677
   }
678
   else
679
   {
680
     topLever =false;
681
     sql = "SELECT permission FROM xml_access WHERE docid = ? " +  
682
           "AND principal_name = ? AND perm_type = ? AND subtreeid= ?";
683
   }
684
   try
685
   {
686
     //check out DBConnection
687
     conn=DBConnectionPool.getDBConnection("AccessControlList.hasAllowRule");
688
     serialNumber=conn.getCheckOutSerialNumber();
689
    //This sql statement will select entry with 
690
    //begin_time<=currentTime<=end_time in xml_access table
691
    //If begin_time or end_time is null in table, isnull(begin_time, sysdate)
692
    //function will assign begin_time=sysdate
693
    pStmt = conn.prepareStatement(sql);
694
    //bind docid, perm_type
695
    pStmt.setString(1, docId);
696
    pStmt.setString(3, AccessControlInterface.ALLOW);
697
    
698
    // if subtree lever, need to set subTreeId
699
    if (!topLever)
700
    {
701
      pStmt.setString(4, subTreeId);
702
    }
703
   
704
    //bind every elenment in user name array
705
    for (int i=0;i<lengthOfArray; i++)
706
    {
707
      pStmt.setString(2, principals[i]);
708
      pStmt.execute();
709
      rs=pStmt.getResultSet();
710
      while (rs.next())//check every entry for one user
711
      {
712
        permissionValueInTable=rs.getInt(1);
713
            
714
        //permission is ok  
715
        //the user have a permission to access the file
716
        if (( permissionValueInTable & permissionValue )== permissionValue )
717
        {
718
           allow=true;//has allow rule entry
719
        }//if
720
      }//while
721
    }//for
722
   }//try
723
   catch (SQLException sqlE)
724
   {
725
     throw sqlE;
726
   }
727
   catch (Exception e)
728
   {
729
     throw e;
730
   }
731
   finally
732
   {
733
     try
734
     {
735
       pStmt.close();
736
     }
737
     finally
738
     {
739
       DBConnectionPool.returnDBConnection(conn, serialNumber);
740
     }
741
   }
742
    return allow;
743
 }//hasAllowRule
744
 
745
 
746
   
747
   /**
748
    * Check if the users array has explicit deny rules for given users, docid 
749
    * and permission. That means the perm_type is deny and current time is
750
    * less than end_time and greater than begin time, or no time limit.
751
    * @param principals, list of names of principals to check for 
752
    * @param docid, document identifier to check for
753
    * @param permission, the permssion need to check
754
    */
755
  private boolean hasExplicitDenyRule(String [] principals, String docId, 
756
                                      int permission, String subTreeId)
757
                  throws SQLException
758
 {
759
   int lengthOfArray=principals.length;
760
   ResultSet rs;
761
   PreparedStatement pStmt = null;
762
   int permissionValue=permission;
763
   int permissionValueInTable;
764
   DBConnection conn = null;
765
   int serialNumber = -1;
766
   String sql = null;
767
   boolean topLevel = false;
768
   
769
   // decide top level or subtree level
770
   if (subTreeId == null)
771
   {
772
     topLevel = true;
773
     sql = "SELECT permission FROM xml_access WHERE docid = ? " + 
774
            "AND principal_name = ? AND perm_type = ? AND subtreeid is NULL";
775
   }
776
   else
777
   {
778
     topLevel = false;
779
     sql = "SELECT permission FROM xml_access WHERE docid = ? " + 
780
            "AND principal_name = ? AND perm_type = ? AND subtreeid = ?";
781
   }
782
   
783
   try
784
   {
785
     //check out DBConnection
786
     conn=DBConnectionPool.getDBConnection("PermissionControl.hasExplicitDeny");
787
     serialNumber=conn.getCheckOutSerialNumber();
788
   
789
     pStmt = conn.prepareStatement(sql);
790
    //bind docid, perm_type
791
    pStmt.setString(1, docId);
792
    pStmt.setString(3, AccessControlInterface.DENY);
793
    
794
    // subtree level need to set up subtreeid
795
    if (!topLevel)
796
    {
797
      pStmt.setString(4, subTreeId);
798
    }
799
   
800
    //bind every elenment in user name array
801
    for (int i=0;i<lengthOfArray; i++)
802
    {
803
      pStmt.setString(2, principals[i]);
804
      pStmt.execute();
805
      rs=pStmt.getResultSet();
806
      while (rs.next())//check every entry for one user
807
      {
808
        permissionValueInTable=rs.getInt(1);
809
        
810
        //permission is ok the user doesn't have permission to access the file
811
        if (( permissionValueInTable & permissionValue )== permissionValue )
812
             
813
        {
814
           pStmt.close();
815
           return true;
816
         }//if
817
      }//while
818
    }//for
819
   }//try
820
   catch (SQLException e)
821
   {
822
     throw e;
823
   }//catch
824
   finally
825
   {
826
     try
827
     {
828
       pStmt.close();
829
     }
830
     finally
831
     {
832
       DBConnectionPool.returnDBConnection(conn, serialNumber);
833
     }
834
   }//finally
835
   return false;//no deny rule
836
  }//hasExplicitDenyRule 
837
   
838

    
839
  /**
840
    * Creat a users pakages to check permssion rule, user itself, public and
841
    * the gourps the user belong will be include in this package
842
    * @param user, the name of user
843
    * @param groups, the string array of the groups that user belong to
844
    */
845
  private String[] createUsersPackage(String user, String [] groups)
846
  {
847
    String [] usersPackage=null;
848
    int lengthOfPackage;
849
    
850
    if (groups!=null)
851
    {
852
      //if gouprs is not null and user is not public, we should create a array 
853
      //to store the groups and user and public. 
854
      //So the length of userPackage is the length of group plus two
855
      if (!user.equalsIgnoreCase(AccessControlInterface.PUBLIC))
856
      {
857
        lengthOfPackage=(groups.length)+2;
858
        usersPackage=new String [lengthOfPackage];
859
        //the first two elements is user self and public
860
        usersPackage[0]=user;
861
        usersPackage[1]=AccessControlInterface.PUBLIC;
862
        //put groups element from index 0 to lengthOfPackage-3 into userPackage
863
        //from index 2 to lengthOfPackage-1
864
        for (int i=2; i<lengthOfPackage; i++)
865
        {
866
          usersPackage[i]=groups[i-2];
867
        } //for
868
      }//if user!=public
869
      else//use=public
870
      {
871
        lengthOfPackage=(groups.length)+1;
872
        usersPackage=new String [lengthOfPackage];
873
        //the first lements is public
874
        usersPackage[0]=AccessControlInterface.PUBLIC;
875
        //put groups element from index 0 to lengthOfPackage-2 into userPackage
876
        //from index 1 to lengthOfPackage-1
877
        for (int i=1; i<lengthOfPackage; i++)
878
        {
879
          usersPackage[i]=groups[i-1];
880
        } //for
881
      }//else user=public
882
       
883
    }//if groups!=null
884
    else
885
    {
886
      //because no groups, the userPackage only need two elements
887
      //one is for user, the other is for public
888
      if (!user.equalsIgnoreCase(AccessControlInterface.PUBLIC))
889
      {
890
        lengthOfPackage=2;
891
        usersPackage=new String [lengthOfPackage];
892
        usersPackage[0]=user;
893
        usersPackage[1]=AccessControlInterface.PUBLIC;
894
      }//if user!=public
895
      else //user==public
896
      {
897
        //only put public into array
898
        lengthOfPackage=1;
899
        usersPackage=new String [lengthOfPackage];
900
        usersPackage[0]=AccessControlInterface.PUBLIC;
901
      }
902
    }//else groups==null
903
    return usersPackage;
904
  }//createUsersPackage
905
 
906
  /**
907
    * This method will return a data set id for given access id.
908
    * @param accessDocId, the accessDocId which need to be found data set id
909
   */
910
  private String getDataSetId(String accessDocId) 
911
                              throws SQLException
912
  {
913
    String dataSetId=null;
914
    PreparedStatement pStmt=null;
915
    ResultSet rs=null;
916
    DBConnection conn=null;
917
    int serialNumber=-1;
918
    String query="SELECT docId from xml_relation where subject = ? or "
919
                                                +"object = ?";
920
    
921
    try
922
    {
923
      //check out DBConnection
924
      conn=DBConnectionPool.getDBConnection("PermissionControl.getDataSetId");
925
      serialNumber=conn.getCheckOutSerialNumber();
926
      
927
      pStmt=conn.prepareStatement(query);
928
      //bind the value to query
929
      pStmt.setString(1, accessDocId);
930
      pStmt.setString(2, accessDocId);
931
      //execute the query
932
      pStmt.execute();
933
      rs=pStmt.getResultSet();
934
      //process the result
935
      if (rs.next()) //There are some records for the data set id for access id
936
      {
937
        dataSetId=rs.getString(1);
938
      }
939
      else //No data set id for the given access id in xml_relation table
940
      {
941
        dataSetId=null;
942
      }
943
    }//try
944
    finally
945
    {
946
      try
947
      {
948
        pStmt.close();
949
      }
950
      finally
951
      {
952
        DBConnectionPool.returnDBConnection(conn, serialNumber);
953
      }
954
    }
955
    return dataSetId;
956
  }//getDataPackageId() 
957
  
958
  /**
959
    * To create a part of query: "docid like '" +str1+ "', " +"docid like '" 
960
    * +str2+"'" ... We need to check user, group and public together for the 
961
    * permission. So we need the principal in an array and according the array
962
    * to create a part of query which will be used in other methods
963
    * @param principals, a string array storing the username, groups name and
964
    * public.
965
    */
966
   private String partQueryAboutDocId( String [] principals)
967
   {
968
     String partQuery="";
969
     int lengthOfArray=principals.length;
970
     
971
     for (int i=0;i<(lengthOfArray-1);i++)
972
     {
973
        partQuery=partQuery+"docid like '"+principals[i]+"',";
974
     }
975
     
976
     //the last one dosen't has "'"
977
     partQuery=partQuery+"docid like '"+principals[(lengthOfArray-1)]+"'";
978
     return partQuery;
979
     
980
   }
981
}
(46-46/56)