Project

General

Profile

1 1425 tao
/**
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$'
12
 *     '$Date$'
13
 * '$Revision$'
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 1485 tao
import java.util.Enumeration;
33 1434 tao
import java.util.Hashtable;
34 1425 tao
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 1527 tao
   private long TOPLEVELSTARTNODEID = 0; //if start node is 0, means it is top
45
                                         //level document
46 1425 tao
47 1527 tao
48 1425 tao
   /**
49
    * Constructor for PermissionController
50
    * @param myDocid      the docid need to access
51
    */
52 1434 tao
   public PermissionController(String myDocid) throws McdbException
53 1425 tao
   {
54
     // Get rid of rev number
55 2045 tao
     docId = MetaCatUtil.getSmartDocId(myDocid);
56 1425 tao
     hasSubTreeAccessControl = checkSubTreeAccessControl();
57
   }
58
59 1485 tao
   /**
60
    * Return if a document has subtree access control
61
    */
62
   public boolean hasSubTreeAccessControl()
63
   {
64
     return hasSubTreeAccessControl;
65
   }
66
67 1425 tao
   /*
68
    * Go through the access table and find if has subtree access control
69
    * if has, store the subtree into list and return true. Otherwise,
70
    * return false
71
    */
72 1434 tao
  private boolean checkSubTreeAccessControl() throws McdbException
73 1425 tao
  {
74
    boolean flag = false;
75
    PreparedStatement pStmt=null;
76
    ResultSet rs=null;
77
    DBConnection conn=null;
78
    int serialNumber=-1;
79
    String query="SELECT subtreeid, startnodeid, endnodeid from xml_access " +
80
                 "where docid =? ";
81
82
    try
83
    {
84
      //check out DBConnection
85
      conn=DBConnectionPool.getDBConnection("PermissionController.hasSubTreeA");
86
      serialNumber=conn.getCheckOutSerialNumber();
87
88
      pStmt=conn.prepareStatement(query);
89
      //bind the value to query
90
      pStmt.setString(1, docId);
91
      //execute the query
92
      pStmt.execute();
93
      rs=pStmt.getResultSet();
94
      //process the result
95
      while (rs.next()) //
96
      {
97
        String subTreeId = rs.getString(1);
98 1474 tao
        MetaCatUtil.debugMessage("subtreeid: "+subTreeId, 35);
99 1425 tao
        long startNodeId = rs.getLong(2);
100 1474 tao
        MetaCatUtil.debugMessage("subtree startNodeId: "+startNodeId, 35);
101 1425 tao
        long endNodeId = rs.getLong(3);
102 1474 tao
        MetaCatUtil.debugMessage("subtree endNodeId: "+endNodeId, 35);
103 1425 tao
        // if startnodeid field in table is empty,startNodeId will be 0
104
        if (subTreeId != null && startNodeId != 0 && startNodeId != 0)
105
        {
106
          flag = true;// has subtree control
107
          SubTree tree = new SubTree();
108
          tree.setSubTreeId(subTreeId);
109
          tree.setStartNodeId(startNodeId);
110
          tree.setEndNodeId(endNodeId);
111
          subTreeList.add(tree);
112
         }
113
      }
114
    }//try
115 1434 tao
    catch (SQLException e)
116
    {
117
      throw new McdbException(e);
118
    }
119 1425 tao
    finally
120
    {
121
      try
122
      {
123
        pStmt.close();
124
      }
125 1434 tao
      catch(SQLException ee)
126
      {
127
        throw new McdbException(ee);
128
      }
129 1425 tao
      finally
130
      {
131
        DBConnectionPool.returnDBConnection(conn, serialNumber);
132
      }
133
    }
134
    return flag;
135
  }
136
137
  /**
138
    * Check from db connection if at least one of the list of @principals
139
    * @param user  the user name
140
    * @param groups  the groups which the use is in
141
    * @param myPermission  permission type to check for
142
    */
143
  public boolean hasPermission(String user, String[]groups, String myPermission)
144
                              throws SQLException, Exception
145
  {
146
    boolean hasPermission=false;
147
    String [] userPackage=null;
148
    int permission =AccessControlList.intValue(myPermission);
149 1434 tao
150 1425 tao
    //for the commnad line invocation
151
    if ((user==null) && (groups==null || groups.length==0))
152
    {
153
      return true;
154
    }
155
156
    //create a userpackage including user, public and group member
157
    userPackage=createUsersPackage(user, groups);
158
159
    //if the requested document is access documents and requested permission
160
    //is "write", the user should have "all" right
161 1541 tao
162 1425 tao
    if (isAccessDocument(docId) && (permission == AccessControlInterface.WRITE))
163
    {
164 1541 tao
165 1425 tao
      hasPermission = hasPermission(userPackage,docId, 7);// 7 is all permission
166
    }//if
167
    else //in other situation, just check the request permission
168
    {
169
170 1541 tao
171 1425 tao
      // Check for @permission on @docid for @user and/or @groups
172
      hasPermission = hasPermission(userPackage,docId, permission);
173
174
    }//else
175
176
    return hasPermission;
177
  }
178 1485 tao
179 1425 tao
180
  /**
181
    * Check from db connection if the users in String array @principals has
182
    * @permission on @docid*
183
    * @param principals, names in userPakcage need to check for @permission
184
    * @param docid, document identifier to check on
185
    * @param permission, permission (write or all...) to check for
186
    */
187
  private boolean hasPermission(String [] principals, String docId,
188
                                           int permission)
189
                         throws SQLException
190
  {
191 1527 tao
    long startId = TOPLEVELSTARTNODEID;// this is for top level, so startid is 0
192 1425 tao
    try
193
    {
194
      //first, if there is a docid owner in user package, return true
195
      //because doc owner has all permssion
196
      if (containDocumentOwner(principals, docId))
197
      {
198
199
          return true;
200
      }
201
202
      //If there is no owner in user package, checking the table
203
      //check perm_order
204 1527 tao
      if (isAllowFirst(principals, docId, startId))
205 1425 tao
      {
206
207 1527 tao
        if (hasExplicitDenyRule(principals, docId, permission, startId))
208 1425 tao
        {
209
          //if it is allowfirst and has deny rule(either explicit )
210
          //deny access
211 1541 tao
212 1425 tao
          return false;
213
        }//if
214 1527 tao
        else if ( hasAllowRule(principals, docId, permission, startId))
215 1425 tao
        {
216
          //if it is allowfirst and hasn't deny rule and has allow rule
217
          //allow access
218 1541 tao
219 1425 tao
          return true;
220
        }//else if
221
        else
222
        {
223
          //other situation deny access
224 1541 tao
225 1425 tao
          return false;
226
        }//else
227
     }//if isAllowFirst
228
     else //denyFirst
229
     {
230 1527 tao
       if (hasAllowRule(principals, docId, permission, startId))
231 1425 tao
       {
232
         //if it is denyFirst and has allow rule, allow access
233
         return true;
234
       }
235
       else
236
       {
237
         //if it is denyfirst but no allow rule, deny access
238
         return false;
239
       }
240
     }//else denyfirst
241
    }//try
242
    catch (Exception e)
243
    {
244
      MetaCatUtil.debugMessage("There is a exception in hasPermission method: "
245
                         +e.getMessage(), 50);
246
    }
247
248
    return false;
249
  }//hasPermission
250
251
  /**
252 1485 tao
   * The method to determine of a node can be access by a user just by subtree
253
   * access control
254
   */
255
  public boolean hasPermissionForSubTreeNode(String user, String[] groups,
256
                                             String myPermission, long nodeId)
257
                                             throws McdbException
258
  {
259 1492 tao
    boolean flag = true;
260 1485 tao
    // Get unaccessble subtree for this user
261
    Hashtable unaccessableSubTree = hasUnaccessableSubTree(user, groups,
262
                                                           myPermission);
263
    Enumeration en = unaccessableSubTree.elements();
264
    while (en.hasMoreElements())
265
    {
266
      SubTree tree = (SubTree)en.nextElement();
267
      long start = tree.getStartNodeId();
268
      long stop  = tree.getEndNodeId();
269 1492 tao
      // nodeid in unaccessablesubtree, return false
270 1485 tao
      if ( nodeId >= start && nodeId <= stop)
271
      {
272 1492 tao
        flag = false;
273 1485 tao
        break;
274
      }
275
    }
276
    return flag;
277
  }
278
  /**
279 1434 tao
   * This method will return a hasTable of subtree which user doesn't has the
280
   * permssion to access
281
   * @param user  the user name
282
   * @param groups  the groups which the use is in
283
   * @param myPermission  permission type to check for
284
   */
285
  public Hashtable hasUnaccessableSubTree(String user, String[] groups,
286
                                       String myPermission) throws McdbException
287
  {
288
    Hashtable resultUnaccessableSubTree = new Hashtable();
289
    String [] principals=null;
290
    int permission =AccessControlList.intValue(myPermission);
291
292
    //for the commnad line invocation return null(no unaccessable subtree)
293
    if ((user==null) && (groups==null || groups.length==0))
294
    {
295
      return resultUnaccessableSubTree;
296
    }
297
298
    //create a userpackage including user, public and group member
299
    principals=createUsersPackage(user, groups);
300
    //for the document owner return null(no unaccessable subtree)
301
    try
302
    {
303
      if (containDocumentOwner(principals, docId))
304
      {
305
       return resultUnaccessableSubTree;
306
      }
307
    }
308
    catch (SQLException ee)
309
    {
310
      throw new McdbException(ee);
311
    }
312
313
    // go through every subtree which has access control
314
    for (int i = 0; i< subTreeList.size(); i++)
315
    {
316
      SubTree tree = (SubTree)subTreeList.elementAt(i);
317 1527 tao
      long startId = tree.getStartNodeId();
318 1434 tao
319 1527 tao
320 1434 tao
        try
321
        {
322 1527 tao
          if (isAllowFirst(principals, docId, startId))
323 1434 tao
          {
324
325 1527 tao
            if (hasExplicitDenyRule(principals, docId, permission, startId ))
326 1434 tao
            {
327
328
             //if it is allowfirst and has deny rule
329
              // put the subtree into unaccessable vector
330 1527 tao
              if (!resultUnaccessableSubTree.containsKey(new Long(startId)))
331 1434 tao
              {
332 1527 tao
                resultUnaccessableSubTree.put(new Long(startId), tree);
333 1434 tao
              }
334
            }//if
335 1527 tao
            else if ( hasAllowRule(principals, docId, permission, startId))
336 1434 tao
            {
337
              //if it is allowfirst and hasn't deny rule and has allow rule
338
              //allow access do nothing
339
340
            }//else if
341
            else
342
            {
343
              //other situation deny access
344 1527 tao
              if (!resultUnaccessableSubTree.containsKey(new Long(startId)))
345 1434 tao
              {
346 1527 tao
                resultUnaccessableSubTree.put(new Long(startId), tree);
347 1434 tao
              }
348
349
            }//else
350
          }//if isAllowFirst
351
          else //denyFirst
352
          {
353 1527 tao
            if (hasAllowRule(principals, docId, permission,startId))
354 1434 tao
            {
355
              //if it is denyFirst and has allow rule, allow access, do nothing
356
357
            }
358
            else
359
            {
360
              //if it is denyfirst but no allow rule, deny access
361
              // add into vector
362 1527 tao
              if (!resultUnaccessableSubTree.containsKey(new Long(startId)))
363 1434 tao
              {
364 1527 tao
                resultUnaccessableSubTree.put(new Long(startId), tree);
365 1434 tao
              }
366
            }
367
          }//else denyfirst
368
        }//try
369
        catch( Exception e)
370
        {
371
          MetaCatUtil.debugMessage("error in PermissionControl.has" +
372
                                   "UnaccessableSubTree "+e.getMessage(), 30);
373
          throw new McdbException(e);
374
        }
375 1527 tao
376 1434 tao
    }//for
377 1513 tao
    // merge the subtree if a subtree is another subtree'subtree
378 1521 tao
    resultUnaccessableSubTree = mergeEquivalentSubtree(resultUnaccessableSubTree);
379 1434 tao
    return resultUnaccessableSubTree;
380
  }//hasUnaccessableSubtree
381
382 1513 tao
383
  /*
384
   * A method to merge nested subtree into bigger one. For example subtree b
385
   * is a subtree of subtree a. And user doesn't have read permission for both
386
   * so we only use subtree a is enough.
387
   */
388 1521 tao
  private Hashtable mergeEquivalentSubtree(Hashtable unAccessSubTree)
389 1513 tao
  {
390
    Hashtable newSubTreeHash = new Hashtable();
391
    boolean   needDelete = false;
392
    // check the parameters
393
    if (unAccessSubTree == null || unAccessSubTree.isEmpty())
394
    {
395
      return newSubTreeHash;
396
    }
397
    else
398
    {
399
      // look every subtree start point and stop point, to see if it is embedded
400
      // in another one. If embedded, they are equavelent and we can use bigger
401
      // one to replace smaller one
402
      Enumeration en = unAccessSubTree.elements();
403
      while (en.hasMoreElements())
404
      {
405
        SubTree tree    = (SubTree)en.nextElement();
406
        String  treeId  = tree.getSubTreeId();
407
        long    startId = tree.getStartNodeId();
408
        long    endId   = tree.getEndNodeId();
409
410
        Enumeration enu = unAccessSubTree.elements();
411
        while (enu.hasMoreElements())
412
        {
413
          SubTree subTree = (SubTree)enu.nextElement();
414
          String subTreeId= subTree.getSubTreeId();
415
          long   subTreeStartId = subTree.getStartNodeId();
416
          long   subTreeEndId   = subTree.getEndNodeId();
417
          //compare and if the first subtree is a subtree of the second
418
          // one, set neeDelete true
419
          if (startId > subTreeStartId && endId < subTreeEndId)
420
          {
421
            needDelete = true;
422
            MetaCatUtil.debugMessage("the subtree: "+ treeId +
423
                                     " need to be get rid of from unaccessable"+
424
                                     " subtree list becuase it is a subtree of"+
425
                                     " another subtree in the list", 45);
426
            break;
427
          }//if
428
        }//while
429
        // if not need to delete, put the subtree into hash
430
        if (!needDelete)
431
        {
432 1527 tao
          newSubTreeHash.put(new Long(startId), tree);
433 1513 tao
        }
434
        //reset needDelete
435
        needDelete = false;
436
      }//while
437
      return newSubTreeHash;
438
    }//else
439
  }
440
441 1434 tao
  /**
442 1425 tao
    * Check if a document id is a access document. Access document need user
443
    * has "all" permission to access it.
444
    * @param docId, the document id need to be checked
445
    */
446
    private boolean isAccessDocument(String docId) throws SQLException
447
    {
448
      //detele the rev number if docid contains it
449
      docId=MetaCatUtil.getDocIdFromString(docId);
450
      PreparedStatement pStmt=null;
451
      DBConnection conn = null;
452
      int serialNumber = -1;
453
      try
454
      {
455
        //check out DBConnection
456 1434 tao
        conn=DBConnectionPool.getDBConnection("PermissionControl.isAccessDoc");
457 1425 tao
        serialNumber=conn.getCheckOutSerialNumber();
458 1541 tao
        pStmt = conn.prepareStatement("select doctype from xml_documents where " +
459
                                      "docid like '" + docId +  "'");
460 1425 tao
        pStmt.execute();
461
        ResultSet rs = pStmt.getResultSet();
462
        boolean hasRow = rs.next();
463 1541 tao
        String doctype = null;
464
        if (hasRow)
465
        {
466
          doctype = rs.getString(1);
467
468
        }
469 1425 tao
        pStmt.close();
470 1541 tao
471
        // if it is an access document
472
        if (doctype != null && ((MetaCatUtil.getOptionList(MetaCatUtil.
473
           getOption("accessdoctype")).contains(doctype))))
474 1425 tao
        {
475 1541 tao
476 1425 tao
          return true;
477
        }
478 1541 tao
479 1425 tao
      }
480
      catch(SQLException e)
481
      {
482
483 1434 tao
        throw new SQLException("PermissionControl.isAccessDocument " +
484 1425 tao
                     "Error checking" +
485
                     " on document " + docId + ". " + e.getMessage());
486
      }
487
      finally
488
      {
489
        try
490
        {
491
           pStmt.close();
492
        }
493
        finally
494
        {
495
          DBConnectionPool.returnDBConnection(conn, serialNumber);
496
        }
497
      }
498 1541 tao
499 1425 tao
      return false;
500
    }//isAccessDocument
501
502
503
504
  /**
505
    * Check if a stirng array contains a given documents' owner
506
    * @param principals, a string array storing the username, groups name and
507
    * public.
508
    * @param docid, the id of given documents
509
    */
510 1434 tao
  private boolean containDocumentOwner( String[] principals, String docId)
511 1425 tao
                    throws SQLException
512
  {
513
    int lengthOfArray=principals.length;
514
    boolean hasRow;
515
    PreparedStatement pStmt=null;
516
    DBConnection conn = null;
517
    int serialNumber = -1;
518
519
    try
520
    {
521
      //check out DBConnection
522 1434 tao
     conn=DBConnectionPool.getDBConnection("PermissionControl.containDocOnwer");
523 1425 tao
      serialNumber=conn.getCheckOutSerialNumber();
524
      pStmt = conn.prepareStatement(
525
                "SELECT 'x' FROM xml_documents " +
526 2045 tao
                "WHERE docid = ? AND lower(user_owner) = ?");
527 1425 tao
      //check every element in the string array too see if it conatains
528
      //the owner of document
529
      for (int i=0; i<lengthOfArray; i++)
530
      {
531
532
        // Bind the values to the query
533
        pStmt.setString(1, docId);
534
        pStmt.setString(2, principals[i]);
535 2045 tao
        MetaCatUtil.debugMessage("the principle stack is : " +
536
                                  principals[i], 40);
537 1425 tao
538
        pStmt.execute();
539
        ResultSet rs = pStmt.getResultSet();
540
        hasRow = rs.next();
541
        if (hasRow)
542
        {
543
          pStmt.close();
544 2045 tao
           MetaCatUtil.debugMessage("find the owner", 40);
545 1425 tao
          return true;
546
        }//if
547
548
      }//for
549
    }//try
550
    catch (SQLException e)
551
    {
552
        pStmt.close();
553
554
        throw new
555 1434 tao
        SQLException("PermissionControl.hasPermission(). " +
556 1425 tao
                     "Error checking ownership for " + principals[0] +
557
                     " on document #" + docId + ". " + e.getMessage());
558
    }//catch
559
    finally
560
    {
561
      try
562
      {
563
        pStmt.close();
564
      }
565
      finally
566
      {
567
        DBConnectionPool.returnDBConnection(conn, serialNumber);
568
      }
569
    }
570
    return false;
571
  }//containDocumentOwner
572
573
  /**
574
    * Check if the permission order for user at that documents is allowFirst
575
    * @param principals, list of names of principals to check for
576
    * @param docid, document identifier to check for
577
    */
578 1434 tao
  private boolean isAllowFirst(String [] principals, String docId,
579 1527 tao
                               long startId)
580 1425 tao
                  throws SQLException, Exception
581
  {
582
    int lengthOfArray=principals.length;
583
    boolean hasRow;
584
    PreparedStatement pStmt = null;
585
    DBConnection conn = null;
586
    int serialNumber = -1;
587 1434 tao
    String sql = null;
588
    boolean topLever =false;
589 1527 tao
    if (startId == TOPLEVELSTARTNODEID)
590 1434 tao
    {
591
      //top level
592
      topLever = true;
593
      sql = "SELECT perm_order FROM xml_access " +
594 2045 tao
    "WHERE lower(principal_name) = ? AND docid = ? AND startnodeid is NULL";
595 1434 tao
    }
596
    else
597
    {
598
      //sub tree level
599
      sql = "SELECT perm_order FROM xml_access " +
600 2045 tao
        "WHERE lower(principal_name)= ? AND docid = ? AND startnodeid = ?";
601 1434 tao
    }
602
603 1425 tao
    try
604
    {
605
      //check out DBConnection
606
      conn=DBConnectionPool.getDBConnection("AccessControlList.isAllowFirst");
607
      serialNumber=conn.getCheckOutSerialNumber();
608
609
      //select permission order from database
610 1434 tao
      pStmt = conn.prepareStatement(sql);
611 1425 tao
612
      //check every name in the array
613
      for (int i=0; i<lengthOfArray;i++)
614
      {
615
        //bind value
616
        pStmt.setString(1, principals[i]);//user name
617
        pStmt.setString(2, docId);//docid
618 1434 tao
619
        // if subtree, we need set subtree id
620
        if (!topLever)
621
        {
622 1527 tao
          pStmt.setLong(3, startId);
623 1434 tao
        }
624 1425 tao
625
        pStmt.execute();
626
        ResultSet rs = pStmt.getResultSet();
627
        hasRow=rs.next();
628
        if (hasRow)
629
        {
630
          //get the permission order from data base
631
          String permissionOrder=rs.getString(1);
632
          //if the permission order is "allowFirst
633
          if (permissionOrder.equalsIgnoreCase(AccessControlInterface.ALLOWFIRST))
634
          {
635
            pStmt.close();
636
            return true;
637
          }
638
          else
639
          {
640
            pStmt.close();
641
            return false;
642
          }
643
        }//if
644
      }//for
645
    }//try
646
    catch (SQLException e)
647
    {
648
      throw e;
649
    }
650
    finally
651
    {
652
      try
653
      {
654
        pStmt.close();
655
      }
656
      finally
657
      {
658
        DBConnectionPool.returnDBConnection(conn, serialNumber);
659
      }
660
    }
661
662
    //if reach here, means there is no permssion record for given names and
663
    //docid. So throw a exception.
664
665
    throw new Exception("There is no permission record for user"+principals[0]+
666
                        "at document "+docId);
667
668
  }//isAllowFirst
669
670
  /**
671
    * Check if the users array has allow rules for given users, docid and
672
    * permission.
673
    * If it has permission rule and ticket count is greater than 0, the ticket
674
    * number will decrease one for every allow rule
675
    * @param principals, list of names of principals to check for
676
    * @param docid, document identifier to check for
677
    * @param permission, the permssion need to check
678
    */
679
  private boolean hasAllowRule(String [] principals, String docId,
680 1527 tao
                                  int permission, long startId)
681 1425 tao
                  throws SQLException, Exception
682
 {
683
   int lengthOfArray=principals.length;
684
   boolean allow=false;//initial value is no allow rule
685
   ResultSet rs;
686
   PreparedStatement pStmt = null;
687
   int permissionValue=permission;
688
   int permissionValueInTable;
689
   int ticketCount;
690
   DBConnection conn = null;
691
   int serialNumber = -1;
692 1434 tao
   boolean topLever = false;
693
   String sql = null;
694 1527 tao
   if (startId == TOPLEVELSTARTNODEID)
695 1434 tao
   {
696
     // for toplevel
697
     topLever = true;
698
     sql = "SELECT permission FROM xml_access WHERE docid = ? " +
699 2045 tao
   "AND lower(principal_name) = ? AND perm_type = ? AND startnodeid is NULL";
700 1434 tao
   }
701
   else
702
   {
703
     topLever =false;
704
     sql = "SELECT permission FROM xml_access WHERE docid = ? " +
705 2045 tao
      "AND lower(principal_name) = ? AND perm_type = ? AND startnodeid = ?";
706 1434 tao
   }
707 1425 tao
   try
708
   {
709
     //check out DBConnection
710
     conn=DBConnectionPool.getDBConnection("AccessControlList.hasAllowRule");
711
     serialNumber=conn.getCheckOutSerialNumber();
712
    //This sql statement will select entry with
713
    //begin_time<=currentTime<=end_time in xml_access table
714
    //If begin_time or end_time is null in table, isnull(begin_time, sysdate)
715
    //function will assign begin_time=sysdate
716 1434 tao
    pStmt = conn.prepareStatement(sql);
717 1425 tao
    //bind docid, perm_type
718
    pStmt.setString(1, docId);
719
    pStmt.setString(3, AccessControlInterface.ALLOW);
720 1434 tao
721
    // if subtree lever, need to set subTreeId
722
    if (!topLever)
723
    {
724 1527 tao
      pStmt.setLong(4, startId);
725 1434 tao
    }
726 1425 tao
727
    //bind every elenment in user name array
728
    for (int i=0;i<lengthOfArray; i++)
729
    {
730
      pStmt.setString(2, principals[i]);
731
      pStmt.execute();
732
      rs=pStmt.getResultSet();
733
      while (rs.next())//check every entry for one user
734
      {
735
        permissionValueInTable=rs.getInt(1);
736 1541 tao
737 1425 tao
        //permission is ok
738
        //the user have a permission to access the file
739
        if (( permissionValueInTable & permissionValue )== permissionValue )
740
        {
741 1541 tao
742 1425 tao
           allow=true;//has allow rule entry
743
        }//if
744
      }//while
745
    }//for
746
   }//try
747
   catch (SQLException sqlE)
748
   {
749
     throw sqlE;
750
   }
751
   catch (Exception e)
752
   {
753
     throw e;
754
   }
755
   finally
756
   {
757
     try
758
     {
759
       pStmt.close();
760
     }
761
     finally
762
     {
763
       DBConnectionPool.returnDBConnection(conn, serialNumber);
764
     }
765
   }
766
    return allow;
767
 }//hasAllowRule
768
769
770
771
   /**
772
    * Check if the users array has explicit deny rules for given users, docid
773
    * and permission. That means the perm_type is deny and current time is
774
    * less than end_time and greater than begin time, or no time limit.
775
    * @param principals, list of names of principals to check for
776
    * @param docid, document identifier to check for
777
    * @param permission, the permssion need to check
778
    */
779
  private boolean hasExplicitDenyRule(String [] principals, String docId,
780 1527 tao
                                      int permission, long startId)
781 1425 tao
                  throws SQLException
782
 {
783
   int lengthOfArray=principals.length;
784
   ResultSet rs;
785
   PreparedStatement pStmt = null;
786
   int permissionValue=permission;
787
   int permissionValueInTable;
788
   DBConnection conn = null;
789
   int serialNumber = -1;
790 1434 tao
   String sql = null;
791
   boolean topLevel = false;
792 1425 tao
793 1434 tao
   // decide top level or subtree level
794 1527 tao
   if (startId == TOPLEVELSTARTNODEID)
795 1434 tao
   {
796
     topLevel = true;
797
     sql = "SELECT permission FROM xml_access WHERE docid = ? " +
798 2045 tao
    "AND lower(principal_name) = ? AND perm_type = ? AND startnodeid is NULL";
799 1434 tao
   }
800
   else
801
   {
802
     topLevel = false;
803
     sql = "SELECT permission FROM xml_access WHERE docid = ? " +
804 2045 tao
     "AND lower(principal_name) = ? AND perm_type = ? AND startnodeid = ?";
805 1434 tao
   }
806
807 1425 tao
   try
808
   {
809
     //check out DBConnection
810 1434 tao
     conn=DBConnectionPool.getDBConnection("PermissionControl.hasExplicitDeny");
811 1425 tao
     serialNumber=conn.getCheckOutSerialNumber();
812
813 1434 tao
     pStmt = conn.prepareStatement(sql);
814 1425 tao
    //bind docid, perm_type
815
    pStmt.setString(1, docId);
816
    pStmt.setString(3, AccessControlInterface.DENY);
817 1434 tao
818
    // subtree level need to set up subtreeid
819
    if (!topLevel)
820
    {
821 1527 tao
      pStmt.setLong(4, startId);
822 1434 tao
    }
823 1425 tao
824
    //bind every elenment in user name array
825
    for (int i=0;i<lengthOfArray; i++)
826
    {
827
      pStmt.setString(2, principals[i]);
828
      pStmt.execute();
829
      rs=pStmt.getResultSet();
830
      while (rs.next())//check every entry for one user
831
      {
832
        permissionValueInTable=rs.getInt(1);
833
834
        //permission is ok the user doesn't have permission to access the file
835
        if (( permissionValueInTable & permissionValue )== permissionValue )
836
837
        {
838
           pStmt.close();
839
           return true;
840
         }//if
841
      }//while
842
    }//for
843
   }//try
844
   catch (SQLException e)
845
   {
846
     throw e;
847
   }//catch
848
   finally
849
   {
850
     try
851
     {
852
       pStmt.close();
853
     }
854
     finally
855
     {
856
       DBConnectionPool.returnDBConnection(conn, serialNumber);
857
     }
858
   }//finally
859
   return false;//no deny rule
860
  }//hasExplicitDenyRule
861
862
863
  /**
864
    * Creat a users pakages to check permssion rule, user itself, public and
865
    * the gourps the user belong will be include in this package
866
    * @param user, the name of user
867
    * @param groups, the string array of the groups that user belong to
868
    */
869
  private String[] createUsersPackage(String user, String [] groups)
870
  {
871
    String [] usersPackage=null;
872
    int lengthOfPackage;
873
874
    if (groups!=null)
875
    {
876
      //if gouprs is not null and user is not public, we should create a array
877
      //to store the groups and user and public.
878
      //So the length of userPackage is the length of group plus two
879
      if (!user.equalsIgnoreCase(AccessControlInterface.PUBLIC))
880
      {
881
        lengthOfPackage=(groups.length)+2;
882
        usersPackage=new String [lengthOfPackage];
883
        //the first two elements is user self and public
884 2045 tao
        //in order to ignore case sensitive, we transfer user to lower case
885
        if (user != null)
886
        {
887
          usersPackage[0]= user.toLowerCase();
888
          MetaCatUtil.debugMessage("after transfer to lower case(not null): "+
889
                                     usersPackage[0], 45);
890
        }
891
        else
892
        {
893
          usersPackage[0] = user;
894
          usersPackage[0]= user.toLowerCase();
895
          MetaCatUtil.debugMessage("after transfer to lower case(null): "+
896
                                     usersPackage[0], 45);
897
        }
898 1425 tao
        usersPackage[1]=AccessControlInterface.PUBLIC;
899
        //put groups element from index 0 to lengthOfPackage-3 into userPackage
900
        //from index 2 to lengthOfPackage-1
901
        for (int i=2; i<lengthOfPackage; i++)
902
        {
903 2045 tao
          //tansfer group to lower case too
904
          if (groups[i-2] != null)
905
          {
906
            usersPackage[i]=groups[i-2].toLowerCase();
907
          }
908 1425 tao
        } //for
909
      }//if user!=public
910
      else//use=public
911
      {
912
        lengthOfPackage=(groups.length)+1;
913
        usersPackage=new String [lengthOfPackage];
914
        //the first lements is public
915
        usersPackage[0]=AccessControlInterface.PUBLIC;
916
        //put groups element from index 0 to lengthOfPackage-2 into userPackage
917
        //from index 1 to lengthOfPackage-1
918
        for (int i=1; i<lengthOfPackage; i++)
919
        {
920 2045 tao
          if (groups[i-1] != null)
921
          {
922
            usersPackage[i]=groups[i-1].toLowerCase();
923
          }
924 1425 tao
        } //for
925
      }//else user=public
926
927
    }//if groups!=null
928
    else
929
    {
930
      //because no groups, the userPackage only need two elements
931
      //one is for user, the other is for public
932
      if (!user.equalsIgnoreCase(AccessControlInterface.PUBLIC))
933
      {
934
        lengthOfPackage=2;
935
        usersPackage=new String [lengthOfPackage];
936 2045 tao
        if (user != null)
937
        {
938
          usersPackage[0]=user.toLowerCase();
939
        }
940
        else
941
        {
942
          usersPackage[0]=user;
943
        }
944 1425 tao
        usersPackage[1]=AccessControlInterface.PUBLIC;
945
      }//if user!=public
946
      else //user==public
947
      {
948
        //only put public into array
949
        lengthOfPackage=1;
950
        usersPackage=new String [lengthOfPackage];
951
        usersPackage[0]=AccessControlInterface.PUBLIC;
952
      }
953
    }//else groups==null
954
    return usersPackage;
955
  }//createUsersPackage
956
957
  /**
958
    * This method will return a data set id for given access id.
959
    * @param accessDocId, the accessDocId which need to be found data set id
960
   */
961
  private String getDataSetId(String accessDocId)
962
                              throws SQLException
963
  {
964
    String dataSetId=null;
965
    PreparedStatement pStmt=null;
966
    ResultSet rs=null;
967
    DBConnection conn=null;
968
    int serialNumber=-1;
969
    String query="SELECT docId from xml_relation where subject = ? or "
970
                                                +"object = ?";
971
972
    try
973
    {
974
      //check out DBConnection
975 1434 tao
      conn=DBConnectionPool.getDBConnection("PermissionControl.getDataSetId");
976 1425 tao
      serialNumber=conn.getCheckOutSerialNumber();
977
978
      pStmt=conn.prepareStatement(query);
979
      //bind the value to query
980
      pStmt.setString(1, accessDocId);
981
      pStmt.setString(2, accessDocId);
982
      //execute the query
983
      pStmt.execute();
984
      rs=pStmt.getResultSet();
985
      //process the result
986
      if (rs.next()) //There are some records for the data set id for access id
987
      {
988
        dataSetId=rs.getString(1);
989
      }
990
      else //No data set id for the given access id in xml_relation table
991
      {
992
        dataSetId=null;
993
      }
994
    }//try
995
    finally
996
    {
997
      try
998
      {
999
        pStmt.close();
1000
      }
1001
      finally
1002
      {
1003
        DBConnectionPool.returnDBConnection(conn, serialNumber);
1004
      }
1005
    }
1006
    return dataSetId;
1007
  }//getDataPackageId()
1008
1009 2045 tao
1010 1425 tao
}