Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *    Purpose: A Class that loads eml-access.xml file containing ACL 
4
 *             for a metadata document into relational DB
5
 *  Copyright: 2000 Regents of the University of California and the
6
 *             National Center for Ecological Analysis and Synthesis
7
 *    Authors: Jivka Bojilova
8
 *    Release: @release@
9
 *
10
 *   '$Author: tao $'
11
 *     '$Date: 2003-02-26 11:29:28 -0800 (Wed, 26 Feb 2003) $'
12
 * '$Revision: 1424 $'
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22
 * GNU General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27
 */
28

    
29
package edu.ucsb.nceas.metacat;
30

    
31
import java.io.*;
32
import java.sql.*;
33
import java.util.Stack;
34
import java.util.Vector;
35
import java.util.Hashtable;
36
import java.net.URL;
37
import java.net.MalformedURLException;
38

    
39
import org.xml.sax.Attributes;
40
import org.xml.sax.InputSource;
41
import org.xml.sax.ContentHandler;
42
import org.xml.sax.EntityResolver;
43
import org.xml.sax.ErrorHandler;
44
import org.xml.sax.SAXException;
45
import org.xml.sax.SAXParseException;
46
import org.xml.sax.XMLReader;
47
import org.xml.sax.helpers.XMLReaderFactory;
48
import org.xml.sax.helpers.DefaultHandler;
49

    
50
/** 
51
 * A Class that loads eml-access.xml file containing ACL for a metadata
52
 * document into relational DB. It extends DefaultHandler class to handle
53
 * SAX parsing events when processing the XML stream.
54
 */
55
public class AccessControlList extends DefaultHandler 
56
                               implements AccessControlInterface 
57
{
58

    
59
 
60
  private static String sysdate = MetaCatUtil.dbAdapter.getDateTimeFunction();
61
  private static String isnull = MetaCatUtil.dbAdapter.getIsNULLFunction();
62
  
63
  private DBConnection connection;
64
  private String parserName;
65
  private Stack elementStack;
66
  private String server;
67
  private String sep;
68
 
69
  private boolean	processingDTD;
70
  private String  user;
71
  private String[] groups;
72
  private String  aclid;
73
  private int     rev;
74
  private String 	docname;
75
  private String 	doctype;
76
  private String 	systemid;
77

    
78
  private String docurl;
79
  private Vector resourceURL;
80
  private Vector resourceID;
81
  private Vector principal;
82
  private int    permission;
83
  private String permType;
84
  private String permOrder;
85
//  private String publicAcc;
86
  private String beginTime;
87
  private String endTime;
88
  private int    ticketCount;
89
  private int    serverCode = 1;
90

    
91
  private Vector aclObjects = new Vector();
92
  private boolean instarttag = true;
93
  private String tagName = "";
94
  /**
95
   * Construct an instance of the AccessControlList class.
96
   * It is used by the permission check up from DBQuery or DocumentImpl
97
   * and from "getaccesscontrol" action
98
   *
99
   * @param conn the JDBC connection where acl info is get
100
   */
101
  public AccessControlList(DBConnection conn) throws SQLException
102
  {
103
    this.connection = conn;
104
  }
105
  
106

    
107
  
108

    
109
  /**
110
   * Construct an instance of the AccessControlList class.
111
   * It parse acl file and loads acl data into db connection.
112
   *
113
   * @param conn the JDBC connection where acl data are loaded
114
   * @param aclid the Accession# of the document with the acl data
115
   * @param acl the acl file containing acl data
116
   * @param user the user connected to MetaCat servlet and owns the document
117
   * @param groups the groups to which user belongs
118
   * @param serverCode the serverid from xml_replication on which this document
119
   *        resides.
120
   */
121
  public AccessControlList(DBConnection conn, String aclid, //Reader acl,
122
                           String user, String[] groups, int serverCode)
123
                  throws SAXException, IOException, McdbException
124
  {
125
    String parserName = MetaCatUtil.getOption("saxparser");
126
    this.server = MetaCatUtil.getOption("server");
127
    this.sep = MetaCatUtil.getOption("accNumSeparator");
128

    
129
    this.connection = conn;
130
    this.parserName = parserName;
131
    this.processingDTD = false;
132
    this.elementStack = new Stack();
133
    
134
    this.user = user;
135
    this.groups = groups;
136
    this.aclid = aclid;
137
    this.resourceURL = new Vector();
138
    this.resourceID = new Vector();
139
    this.principal = new Vector();
140
    this.permission = 0;
141
    this.ticketCount = 0;
142
  //  this.publicAcc = null;
143
    this.serverCode = serverCode;
144
    
145
    // read the access file from db connection
146
    DocumentImpl acldoc = new DocumentImpl(aclid);
147
    String acl = acldoc.toString();
148
    this.rev = acldoc.getRev();
149

    
150
    // Initialize the parse
151
    XMLReader parser = initializeParser();
152
    // parse the access file and write the info to xml_access
153
    parser.parse(new InputSource(new StringReader(acl)));
154
    
155
  }
156

    
157
// NOT USED
158
//  /**
159
//   * Construct an instance of the AccessControlList class.
160
//   * It parses eml-access file and loads acl data into db connection.
161
//   * It is used from command line execution.
162
//   *
163
//   * @param conn the JDBC connection where acl data are loaded
164
//   * @param docid the Accession# of the document with the acl data
165
//   * @param aclfilename the name of acl file containing acl data
166
//   * @param user the user connected to MetaCat servlet and owns the document
167
//   * @param groups the groups to which user belongs
168
//   */
169
//  public AccessControlList( Connection conn, String aclid, String aclfilename,
170
//                           String user, String[] groups )
171
//                  throws SAXException, IOException, McdbException
172
//  {
173
//    this(conn, aclid, new FileReader(new File(aclfilename).toString()), 
174
//         user, groups, 1);
175
//  }
176
  
177
  /* Set up the SAX parser for reading the XML serialized ACL */
178
  private XMLReader initializeParser() throws SAXException 
179
  {
180
    XMLReader parser = null;
181

    
182
    // Get an instance of the parser
183
    parser = XMLReaderFactory.createXMLReader(parserName);
184

    
185
    // Turn off validation
186
    parser.setFeature("http://xml.org/sax/features/validation", true);
187
      
188
    // Set Handlers in the parser
189
    // Set the ContentHandler to this instance
190
    parser.setContentHandler((ContentHandler)this);
191

    
192
    // make a DBEntityResolver instance
193
    // Set the EntityReslover to DBEntityResolver instance
194
    EntityResolver eresolver = new DBEntityResolver(connection,this,null);
195
    parser.setEntityResolver((EntityResolver)eresolver);
196

    
197
    // Set the ErrorHandler to this instance
198
    parser.setErrorHandler((ErrorHandler)this);
199

    
200
    return parser; 
201
  }
202
  
203
  /**
204
   * Callback method used by the SAX Parser when beginning of the document
205
   */
206
  public void startDocument() throws SAXException 
207
  {
208
    //delete all previously submitted permissions @ relations
209
    //this happens only on UPDATE of the access file
210
    try {
211
      this.aclObjects = getACLObjects(aclid);
212

    
213
      //delete all permissions for resources related to @aclid if any
214
      if ( aclid != null ) {
215
        deletePermissionsForRelatedResources(aclid);
216
      }
217
    } catch (SQLException sqle) {
218
      throw new SAXException(sqle);
219
    }
220
  }
221
  
222
  /**
223
   * Callback method used by the SAX Parser when the start tag of an 
224
   * element is detected. Used in this context to parse and store
225
   * the acl information in class variables.
226
   */
227
  public void startElement (String uri, String localName, 
228
                            String qName, Attributes atts) 
229
         throws SAXException 
230
  {
231
    instarttag = true;
232
    if(localName.equals("allow"))
233
    {
234
      tagName = "allow";
235
    }
236
    else if(localName.equals("deny"))
237
    {
238
      tagName = "deny";
239
    }
240
    BasicNode currentNode = new BasicNode(localName);
241
    if (atts != null) {
242
      int len = atts.getLength();
243
      for (int i = 0; i < len; i++) {
244
        currentNode.setAttribute(atts.getLocalName(i), atts.getValue(i));
245
      }
246
    }
247
    if ( currentNode.getTagName().equals("acl") ) {
248
      permOrder = currentNode.getAttribute("order");
249
    //  publicAcc = currentNode.getAttribute("public");
250
    }
251
    elementStack.push(currentNode); 
252
  }
253

    
254
  /**
255
   * Callback method used by the SAX Parser when the text sequences of an 
256
   * xml stream are detected. Used in this context to parse and store
257
   * the acl information in class variables.
258
   */ 
259
  public void characters(char ch[], int start, int length)
260
         throws SAXException 
261
  {
262
    if(!instarttag)
263
    {
264
      return;
265
    }
266
    String inputString = new String(ch, start, length);
267
    inputString = inputString.trim(); 
268
    //System.out.println("==============inputString: " + inputString);
269
    BasicNode currentNode = (BasicNode)elementStack.peek(); 
270
    String currentTag = currentNode.getTagName();
271

    
272
      if (currentTag.equals("principal")) {
273

    
274
        principal.addElement(inputString);
275

    
276
      } else if (currentTag.equals("permission")) {
277

    
278
        if ( inputString.trim().toUpperCase().equals("READ") ) {
279
          permission = permission | READ;
280
        } else if ( inputString.trim().toUpperCase().equals("WRITE") ) {
281
          permission = permission | WRITE;
282
        } else if ( inputString.trim().toUpperCase().equals("CHANGEPERMISSION")) 
283
        {
284
          permission = permission | CHMOD;
285
        } else if ( inputString.trim().toUpperCase().equals("ALL") ) {
286
          permission = permission | ALL;
287
        }/*else{
288
          throw new SAXException("Unknown permission type: " + inputString);
289
        }*/
290

    
291
      } else if ( currentTag.equals("startDate") && beginTime == null ) {
292
        beginTime = inputString.trim();
293

    
294
      } else if ( currentTag.equals("stopDate") && endTime == null) {
295
        endTime = inputString.trim();
296

    
297
      } else if (currentTag.equals("ticketCount") && ticketCount == 0 ) {
298
        try {
299
          ticketCount = (new Integer(inputString.trim())).intValue();
300
        } catch (NumberFormatException nfe) {
301
          throw new SAXException("Wrong integer format for:" + inputString);
302
        }
303
      }
304
  }
305

    
306
  /**
307
   * Callback method used by the SAX Parser when the end tag of an 
308
   * element is detected. Used in this context to parse and store
309
   * the acl information in class variables.
310
   */
311
  public void endElement (String uri, String localName, String qName)
312
         throws SAXException 
313
  {
314
    instarttag = false;
315
    BasicNode leaving = (BasicNode)elementStack.pop();
316
    String leavingTagName = leaving.getTagName();
317

    
318
    if ( leavingTagName.equals("allow") ||
319
         leavingTagName.equals("deny")    ) {
320
      
321
      if ( permission > 0 ) {
322

    
323
        // insert into db calculated permission for the list of principals
324
        try {
325
          // go through the objects in xml_relation about this acl doc
326
          for (int i=0; i < aclObjects.size(); i++) {
327
            // docid of the current object
328
            String docid = (String)aclObjects.elementAt(i); 
329
            DocumentIdentifier docID = new DocumentIdentifier(docid);
330
            docid = docID.getIdentifier();
331
            insertPermissions(docid,leavingTagName);
332
          }
333
          
334
          // if acl is not in object list
335
          //should insert permission for aclid itself into database
336
          /*if (!aclObjects.contains(aclid))
337
          {
338
            DocumentIdentifier aclIdItself = new DocumentIdentifier(aclid);
339
            String aclIdString = aclIdItself.getIdentifier();
340
            insertPermissions(aclIdString,leavingTagName);
341
          }*/
342
          
343

    
344
        } catch (SQLException sqle) {
345
          throw new SAXException(sqle);
346
        } catch (Exception e) {
347
          throw new SAXException(e);
348
        }
349
      }
350

    
351
      // reset the allow/deny permission
352
      principal = new Vector();
353
      permission = 0;
354
      beginTime = null;
355
      endTime = null;
356
      ticketCount = 0;
357
    
358
    }
359

    
360
  }
361

    
362
  /** 
363
    * SAX Handler that receives notification of DOCTYPE. Sets the DTD.
364
    * @param name name of the DTD
365
    * @param publicId Public Identifier of the DTD
366
    * @param systemId System Identifier of the DTD
367
    */
368
  public void startDTD(String name, String publicId, String systemId) 
369
              throws SAXException {
370
    docname = name;
371
    doctype = publicId;
372
    systemid = systemId;
373
  }
374

    
375
  /** 
376
   * SAX Handler that receives notification of the start of entities.
377
   * @param name name of the entity
378
   */
379
  public void startEntity(String name) throws SAXException {
380
    if (name.equals("[dtd]")) {
381
      processingDTD = true;
382
    }
383
  }
384

    
385
  /** 
386
   * SAX Handler that receives notification of the end of entities.
387
   * @param name name of the entity
388
   */
389
  public void endEntity(String name) throws SAXException {
390
    if (name.equals("[dtd]")) {
391
      processingDTD = false;
392
    }
393
  }
394

    
395
  /**
396
   * Get the document name.
397
   */
398
  public String getDocname() {
399
    return docname;
400
  }
401

    
402
  /**
403
   * Get the document processing state.
404
   */
405
  public boolean processingDTD() {
406
    return processingDTD;
407
  }
408
  
409
  /* Get all objects associated with @aclid from db.*/
410
  private Vector getACLObjects(String aclid) 
411
          throws SQLException 
412
  {
413
    Vector aclObjects = new Vector();
414
    DBConnection conn = null;
415
    int serialNumber = -1;
416
    PreparedStatement pstmt = null;
417
    try
418
    {
419
      //get connection from DBConnectionPool
420
      conn=DBConnectionPool.getDBConnection("AccessControlList.getACLObject");
421
      serialNumber=conn.getCheckOutSerialNumber();
422
      
423
      // delete all acl records for resources related to @aclid if any
424
      pstmt = conn.prepareStatement(
425
                             "SELECT object FROM xml_relation " +
426
                             "WHERE subject = ? ");
427
      pstmt.setString(1,aclid);
428
      pstmt.execute();
429
      ResultSet rs = pstmt.getResultSet();
430
      boolean hasRows = rs.next();
431
      while (hasRows) {
432
        aclObjects.addElement(rs.getString(1));
433
        hasRows = rs.next();
434
      }//whil
435
    }
436
    catch (SQLException e)
437
    {
438
      throw e;
439
    }
440
    finally
441
    {
442
      try
443
      {
444
        pstmt.close();
445
      }
446
      finally
447
      {
448
        //retrun DBConnection
449
        DBConnectionPool.returnDBConnection(conn,serialNumber);
450
      }
451
    }
452
    
453
    return aclObjects;
454
  }
455

    
456
  /* Delete from db all permission for resources related to @aclid if any.*/
457
  private void deletePermissionsForRelatedResources(String aclid) 
458
          throws SQLException 
459
  {
460
    //DBConnection conn = null;
461
    //int serialNumber = -1;
462
    Statement stmt = null;
463
    try
464
    {
465
      //check out DBConenction
466
      //conn=DBConnectionPool.getDBConnection("AccessControlList.deltePerm");
467
      //serialNumber=conn.getCheckOutSerialNumber();
468
      // delete all acl records for resources related to @aclid if any
469
      stmt = connection.createStatement();
470
      // Increase DBConnection usage count
471
      connection.increaseUsageCount(1);
472
      stmt.execute("DELETE FROM xml_access WHERE accessfileid = '" + aclid 
473
                                                                      + "'");
474
      //increase usageCount!!!!!!
475
      //conn.increaseUsageCount(1);
476
    }
477
    catch (SQLException e)
478
    {
479
      throw e;
480
    }
481
    finally
482
    {
483
      stmt.close();
484
      //retrun DBConnection
485
      //DBConnectionPool.returnDBConnection(conn,serialNumber);
486
    }
487
  }
488

    
489
  /* Insert into db calculated permission for the list of principals 
490
   * The DBConnection it is use is class field. Because we want to keep rollback
491
   * features and it need use same connection
492
  */
493
  
494
  private void insertPermissions(String docid, String permType ) 
495
                                            throws SQLException 
496
  {
497
    PreparedStatement pstmt = null;
498
    //DBConnection conn = null;
499
    //int serialNumber = -1;
500
    try {
501
      //Check out DBConnection
502
      //conn=DBConnectionPool.getDBConnection("AccessControlList.insertPerm");
503
      //serialNumber=conn.getCheckOutSerialNumber();
504
      
505
      pstmt = connection.prepareStatement(
506
              "INSERT INTO xml_access " + 
507
              "(docid, principal_name, permission, perm_type, perm_order," +
508
              "begin_time,end_time,ticket_count, accessfileid) VALUES " +
509
              "(?,?,?,?,?,to_date(?,'mm/dd/yy'),to_date(?,'mm/dd/yy'),?,?)");
510
      // Increase DBConnection usage count
511
      connection.increaseUsageCount(1);
512
      // Bind the values to the query
513
      pstmt.setString(1, docid);
514
      pstmt.setInt(3, permission);
515
      pstmt.setString(4, permType);
516
      pstmt.setString(5, permOrder);
517
      pstmt.setString(6, beginTime);
518
      pstmt.setString(7, endTime);
519
      pstmt.setString(9, aclid);
520
      if ( ticketCount > 0 ) {
521
        pstmt.setString(8, "" + ticketCount);
522
      } else {
523
        pstmt.setString(8, null);
524
      }
525
      
526
      //incrase usagecount for DBConnection
527
      //conn.increaseUsageCount(1);
528
      String prName;
529
      for ( int j = 0; j < principal.size(); j++ ) {
530
        prName = (String)principal.elementAt(j);
531
        pstmt.setString(2, prName);
532
        pstmt.execute();
533
      /*    
534
        // check if there are conflict with permission's order
535
        String permOrderOpos = permOrder;
536
        int perm = getPermissions(permission, prName, docid, permOrder);
537
        if (  perm != 0 ) {
538
          if ( permOrder.equals("allowFirst") ) {
539
            permOrderOpos = "denyFirst";
540
          } else if ( permOrder.equals("denyFirst") ) {
541
            permOrderOpos = "allowFirst";
542
          }
543
          throw new SQLException("Permission(s) " + txtValue(perm) + 
544
                    " for \"" + prName + "\" on document #" + docid +
545
                    " has/have been used with \"" + permOrderOpos + "\"");
546
        }
547
      */
548
      }
549
      pstmt.close();
550

    
551
    } catch (SQLException e) {
552
      throw new 
553
      SQLException("AccessControlList.insertPermissions(): " + e.getMessage());
554
    }
555
    finally
556
    {
557
      pstmt.close();
558
      //return the DBConnection
559
      //DBConnectionPool.returnDBConnection(conn, serialNumber);
560
    }
561
  }
562

    
563
  /* Get permissions with permission order different than @permOrder. */
564
  private int getPermissions(int permission, String principal,
565
                             String docid, String permOrder)
566
          throws SQLException 
567
  {
568
    PreparedStatement pstmt = null;
569
    DBConnection conn = null;
570
    int serialNumber = -1;
571
    try
572
    {
573
      //check out DBConnection
574
      conn=DBConnectionPool.getDBConnection("AccessControlList.getPermissions");
575
      serialNumber=conn.getCheckOutSerialNumber();
576
      pstmt = conn.prepareStatement(
577
            "SELECT permission FROM xml_access " +
578
            "WHERE docid = ? " +
579
            "AND principal_name = ? " +
580
            "AND perm_order NOT = ?");
581
      pstmt.setString(1, docid);
582
      pstmt.setString(2, principal);
583
      pstmt.setString(3, permOrder);
584
      pstmt.execute();
585
      ResultSet rs = pstmt.getResultSet();
586
      boolean hasRow = rs.next();
587
      int perm = 0;
588
      while ( hasRow ) {
589
        perm = rs.getInt(1);
590
        perm = permission & perm;
591
        if ( perm != 0 ) {
592
          pstmt.close();
593
          return perm;
594
        }
595
        hasRow = rs.next();
596
      }
597
    }//try
598
    catch (SQLException e)
599
    {
600
      throw e;
601
    }
602
    finally
603
    {
604
      try
605
      {
606
        pstmt.close();
607
      }
608
      finally
609
      {
610
        DBConnectionPool.returnDBConnection(conn, serialNumber);
611
      }
612
    }
613
    return 0;
614
  }
615

    
616
  /* Get the int value of READ, WRITE or ALL. */
617
  public static int intValue ( String permission )
618
  {
619
    if ( permission.equalsIgnoreCase("READ") ) {
620
      return READ;
621
    } else if ( permission.equalsIgnoreCase("WRITE") ) {
622
      return WRITE;
623
    } else if ( permission.equalsIgnoreCase("ALL") ) {
624
      return ALL;
625
    }
626
    
627
    return -1;
628
  }
629

    
630
  /* Get the text value of READ, WRITE or ALL. */
631
  private String txtValue ( int permission )
632
  {
633
    StringBuffer txtPerm = new StringBuffer("\"");
634
    if ( (permission & READ) != 0 ) {
635
      txtPerm.append("read");
636
    } 
637
    if ( (permission & WRITE) != 0 ) {
638
      if ( txtPerm.length() > 0 ) txtPerm.append(",");
639
      txtPerm.append("write");
640
    }
641
    if ( (permission & ALL) != 0 ) {
642
      if ( txtPerm.length() > 0 ) txtPerm.append(",");
643
      txtPerm.append("all");
644
    }
645

    
646
    return txtPerm.append("\"").toString();
647
  }
648

    
649
  
650
  /**
651
    * Check if a document id is a access document. Access document need user
652
    * has "all" permission to access it.
653
    * @param docId, the document id need to be checked
654
    */
655
    private static boolean isAccessDocument(String docId) throws SQLException
656
    {
657
      //detele the rev number if docid contains it
658
      docId=MetaCatUtil.getDocIdFromString(docId);
659
      PreparedStatement pStmt=null;
660
      DBConnection conn = null;
661
      int serialNumber = -1;
662
      try
663
      {
664
        //check out DBConnection
665
        conn=DBConnectionPool.getDBConnection("AccessControlList.isAccessDoc");
666
        serialNumber=conn.getCheckOutSerialNumber();
667
        pStmt = conn.prepareStatement("select 'x' from xml_access where " +
668
                                      "accessfileid like '" + docId +  "'");
669
        pStmt.execute();
670
        ResultSet rs = pStmt.getResultSet();
671
        boolean hasRow = rs.next();
672
        pStmt.close();
673
        if(hasRow)
674
        {
675
          return true;
676
        }
677
      }
678
      catch(SQLException e)
679
      {
680
       
681
        throw new SQLException("AccessControlList.isAccessDocument " +
682
                     "Error checking" +
683
                     " on document " + docId + ". " + e.getMessage());
684
      }
685
      finally
686
      {
687
        try
688
        {
689
           pStmt.close();
690
        }
691
        finally
692
        {
693
          DBConnectionPool.returnDBConnection(conn, serialNumber);
694
        }
695
      }
696
      return false;
697
    }//isAccessDocument
698
     
699
  /**
700
    * To create a part of query: "docid like '" +str1+ "', " +"docid like '" 
701
    * +str2+"'" ... We need to check user, group and public together for the 
702
    * permission. So we need the principal in an array and according the array
703
    * to create a part of query which will be used in other methods
704
    * @param principals, a string array storing the username, groups name and
705
    * public.
706
    */
707
   private String partQueryAboutDocId( String [] principals)
708
   {
709
     String partQuery="";
710
     int lengthOfArray=principals.length;
711
     
712
     for (int i=0;i<(lengthOfArray-1);i++)
713
     {
714
        partQuery=partQuery+"docid like '"+principals[i]+"',";
715
     }
716
     
717
     //the last one dosen't has "'"
718
     partQuery=partQuery+"docid like '"+principals[(lengthOfArray-1)]+"'";
719
     return partQuery;
720
     
721
   }
722
  
723
  /**
724
    * Check if a stirng array contains a given documents' owner
725
    * @param principals, a string array storing the username, groups name and
726
    * public.
727
    * @param docid, the id of given documents 
728
    */ 
729
  private static boolean containDocumentOwner( String [] principals, 
730
                                                              String docId)
731
                    throws SQLException
732
  {
733
    int lengthOfArray=principals.length;
734
    boolean hasRow; 
735
    PreparedStatement pStmt=null;
736
    DBConnection conn = null;
737
    int serialNumber = -1;
738
    
739
    try
740
    {
741
      //check out DBConnection
742
     conn=DBConnectionPool.getDBConnection("AccessControlList.containDocOnwer");
743
      serialNumber=conn.getCheckOutSerialNumber();
744
      pStmt = conn.prepareStatement(
745
                "SELECT 'x' FROM xml_documents " +
746
                "WHERE docid = ? AND user_owner = ?"); 
747
      //check every element in the string array too see if it conatains
748
      //the owner of document
749
      for (int i=0; i<lengthOfArray; i++)
750
      {
751
             
752
        // Bind the values to the query
753
        pStmt.setString(1, docId);
754
        pStmt.setString(2, principals[i]);
755

    
756
        pStmt.execute();
757
        ResultSet rs = pStmt.getResultSet();
758
        hasRow = rs.next();
759
        if (hasRow) 
760
        {
761
          pStmt.close();
762
          return true;
763
        }//if    
764
     
765
      }//for
766
    }//try
767
    catch (SQLException e) 
768
    {
769
        pStmt.close();
770
       
771
        throw new 
772
        SQLException("AccessControlList.hasPermission(). " +
773
                     "Error checking ownership for " + principals[0] +
774
                     " on document #" + docId + ". " + e.getMessage());
775
    }//catch
776
    finally
777
    {
778
      try
779
      {
780
        pStmt.close();
781
      }
782
      finally
783
      {
784
        DBConnectionPool.returnDBConnection(conn, serialNumber);
785
      }
786
    }
787
    return false; 
788
  }//containDocumentOwner
789
  
790
  /**
791
    * Check if the permission order for user at that documents is allowFirst
792
    * @param principals, list of names of principals to check for 
793
    * @param docid, document identifier to check for
794
    */
795
  private static boolean isAllowFirst(String [] principals, String docId)
796
                  throws SQLException, Exception
797
  {
798
    int lengthOfArray=principals.length;
799
    boolean hasRow;
800
    PreparedStatement pStmt = null;
801
    DBConnection conn = null;
802
    int serialNumber = -1;
803
    try
804
    {
805
      //check out DBConnection
806
      conn=DBConnectionPool.getDBConnection("AccessControlList.isAllowFirst");
807
      serialNumber=conn.getCheckOutSerialNumber();
808
    
809
      //select permission order from database
810
      pStmt = conn.prepareStatement(
811
                "SELECT perm_order FROM xml_access " +
812
                "WHERE principal_name= ? AND docid = ?");
813
   
814
      //check every name in the array
815
      for (int i=0; i<lengthOfArray;i++)
816
      {
817
        //bind value
818
        pStmt.setString(1, principals[i]);//user name
819
        pStmt.setString(2, docId);//docid
820
    
821
        pStmt.execute();
822
        ResultSet rs = pStmt.getResultSet();
823
        hasRow=rs.next();
824
        if (hasRow)
825
        {
826
          //get the permission order from data base
827
          String permissionOrder=rs.getString(1);
828
          //if the permission order is "allowFirst
829
          if (permissionOrder.equalsIgnoreCase(ALLOWFIRST))
830
          {
831
            pStmt.close();
832
            return true;
833
          }
834
          else
835
          {
836
            pStmt.close();
837
            return false;
838
          }
839
        }//if
840
      }//for
841
    }//try
842
    catch (SQLException e)
843
    {
844
      throw e;
845
    }
846
    finally
847
    {
848
      try
849
      {
850
        pStmt.close();
851
      }
852
      finally
853
      {
854
        DBConnectionPool.returnDBConnection(conn, serialNumber);
855
      }
856
    }
857
    
858
    //if reach here, means there is no permssion record for given names and 
859
    //docid. So throw a exception.
860
    
861
    throw new Exception("There is no permission record for user"+principals[0]+
862
                        "at document "+docId);
863
        
864
  }//isAllowFirst
865
  
866
  /**
867
    * Check if the users array has allow rules for given users, docid and 
868
    * permission.
869
    * If it has permission rule and ticket count is greater than 0, the ticket
870
    * number will decrease one for every allow rule
871
    * @param principals, list of names of principals to check for 
872
    * @param docid, document identifier to check for
873
    * @param permission, the permssion need to check
874
    */
875
  private static boolean hasAllowRule(String [] principals, String docId, 
876
                                  String permission)
877
                  throws SQLException, Exception
878
 {
879
   int lengthOfArray=principals.length;
880
   boolean allow=false;//initial value is no allow rule
881
   ResultSet rs;
882
   PreparedStatement pStmt = null;
883
   int permissionValue=intValue(permission);
884
   int permissionValueInTable;
885
   int ticketCount;
886
   DBConnection conn = null;
887
   int serialNumber = -1;
888
   try
889
   {
890
     //check out DBConnection
891
     conn=DBConnectionPool.getDBConnection("AccessControlList.hasAllowRule");
892
     serialNumber=conn.getCheckOutSerialNumber();
893
    //This sql statement will select entry with 
894
    //begin_time<=currentTime<=end_time in xml_access table
895
    //If begin_time or end_time is null in table, isnull(begin_time, sysdate)
896
    //function will assign begin_time=sysdate
897
    pStmt = conn.prepareStatement(
898
                "SELECT permission " +
899
                "FROM xml_access " +
900
                "WHERE docid = ? " + 
901
                "AND principal_name = ? " +
902
                "AND perm_type = ? ");
903
    //bind docid, perm_type
904
    pStmt.setString(1, docId);
905
    pStmt.setString(3, ALLOW);
906
   
907
    //bind every elenment in user name array
908
    for (int i=0;i<lengthOfArray; i++)
909
    {
910
      pStmt.setString(2, principals[i]);
911
      pStmt.execute();
912
      rs=pStmt.getResultSet();
913
      while (rs.next())//check every entry for one user
914
      {
915
        permissionValueInTable=rs.getInt(1);
916
            
917
        //permission is ok  
918
        //the user have a permission to access the file
919
        if (( permissionValueInTable & permissionValue )== permissionValue )
920
        {
921
           allow=true;//has allow rule entry
922
        }//if
923
      }//while
924
    }//for
925
   }//try
926
   catch (SQLException sqlE)
927
   {
928
     throw sqlE;
929
   }
930
   catch (Exception e)
931
   {
932
     throw e;
933
   }
934
   finally
935
   {
936
     try
937
     {
938
       pStmt.close();
939
     }
940
     finally
941
     {
942
       DBConnectionPool.returnDBConnection(conn, serialNumber);
943
     }
944
   }
945
    return allow;
946
 }//hasAllowRule
947
 
948
 
949
   
950
   /**
951
    * Check if the users array has explicit deny rules for given users, docid 
952
    * and permission. That means the perm_type is deny and current time is
953
    * less than end_time and greater than begin time, or no time limit.
954
    * @param principals, list of names of principals to check for 
955
    * @param docid, document identifier to check for
956
    * @param permission, the permssion need to check
957
    */
958
  private static boolean hasExplicitDenyRule(String [] principals, String docId, 
959
                                  String permission)
960
                  throws SQLException
961
 {
962
   int lengthOfArray=principals.length;
963
   ResultSet rs;
964
   PreparedStatement pStmt = null;
965
   int permissionValue=intValue(permission);
966
   int permissionValueInTable;
967
   DBConnection conn = null;
968
   int serialNumber = -1;
969
   
970
   try
971
   {
972
     //check out DBConnection
973
     conn=DBConnectionPool.getDBConnection("AccessControlList.hasExplicitDeny");
974
     serialNumber=conn.getCheckOutSerialNumber();
975
   
976
     pStmt = conn.prepareStatement(
977
                "SELECT permission " +
978
                "FROM xml_access " +
979
                "WHERE docid = ? " + 
980
                "AND principal_name = ? " +
981
                "AND perm_type = ? ");
982
    //bind docid, perm_type
983
    pStmt.setString(1, docId);
984
    pStmt.setString(3, DENY);
985
   
986
    //bind every elenment in user name array
987
    for (int i=0;i<lengthOfArray; i++)
988
    {
989
      pStmt.setString(2, principals[i]);
990
      pStmt.execute();
991
      rs=pStmt.getResultSet();
992
      while (rs.next())//check every entry for one user
993
      {
994
        permissionValueInTable=rs.getInt(1);
995
        
996
        //permission is ok the user doesn't have permission to access the file
997
        if (( permissionValueInTable & permissionValue )== permissionValue )
998
             
999
        {
1000
           pStmt.close();
1001
           return true;
1002
         }//if
1003
      }//while
1004
    }//for
1005
   }//try
1006
   catch (SQLException e)
1007
   {
1008
     throw e;
1009
   }//catch
1010
   finally
1011
   {
1012
     try
1013
     {
1014
       pStmt.close();
1015
     }
1016
     finally
1017
     {
1018
       DBConnectionPool.returnDBConnection(conn, serialNumber);
1019
     }
1020
   }//finally
1021
   return false;//no deny rule
1022
  }//hasExplicitDenyRule 
1023
   
1024

    
1025
  /**
1026
    * Creat a users pakages to check permssion rule, user itself, public and
1027
    * the gourps the user belong will be include in this package
1028
    * @param user, the name of user
1029
    * @param groups, the string array of the groups that user belong to
1030
    */
1031
  private static String [] createUsersPackage(String user, String [] groups)
1032
  {
1033
    String [] usersPackage=null;
1034
    int lengthOfPackage;
1035
    
1036
    if (groups!=null)
1037
    {
1038
      //if gouprs is not null and user is not public, we should create a array 
1039
      //to store the groups and user and public. 
1040
      //So the length of userPackage is the length of group plus two
1041
      if (!user.equalsIgnoreCase(PUBLIC))
1042
      {
1043
        lengthOfPackage=(groups.length)+2;
1044
        usersPackage=new String [lengthOfPackage];
1045
        //the first two elements is user self and public
1046
        usersPackage[0]=user;
1047
        usersPackage[1]=PUBLIC;
1048
        //put groups element from index 0 to lengthOfPackage-3 into userPackage
1049
        //from index 2 to lengthOfPackage-1
1050
        for (int i=2; i<lengthOfPackage; i++)
1051
        {
1052
          usersPackage[i]=groups[i-2];
1053
        } //for
1054
      }//if user!=public
1055
      else//use=public
1056
      {
1057
        lengthOfPackage=(groups.length)+1;
1058
        usersPackage=new String [lengthOfPackage];
1059
        //the first lements is public
1060
        usersPackage[0]=PUBLIC;
1061
        //put groups element from index 0 to lengthOfPackage-2 into userPackage
1062
        //from index 1 to lengthOfPackage-1
1063
        for (int i=1; i<lengthOfPackage; i++)
1064
        {
1065
          usersPackage[i]=groups[i-1];
1066
        } //for
1067
      }//else user=public
1068
       
1069
    }//if groups!=null
1070
    else
1071
    {
1072
      //because no groups, the userPackage only need two elements
1073
      //one is for user, the other is for public
1074
      if (!user.equalsIgnoreCase(PUBLIC))
1075
      {
1076
        lengthOfPackage=2;
1077
        usersPackage=new String [lengthOfPackage];
1078
        usersPackage[0]=user;
1079
        usersPackage[1]=PUBLIC;
1080
      }//if user!=public
1081
      else //user==public
1082
      {
1083
        //only put public into array
1084
        lengthOfPackage=1;
1085
        usersPackage=new String [lengthOfPackage];
1086
        usersPackage[0]=PUBLIC;
1087
      }
1088
    }//else groups==null
1089
    return usersPackage;
1090
  }//createUsersPackage
1091
 
1092
  /**
1093
    * This method will return a data set id for given access id.
1094
    * @param accessDocId, the accessDocId which need to be found data set id
1095
   */
1096
  private static String getDataSetId(String accessDocId) 
1097
                              throws SQLException
1098
  {
1099
    String dataSetId=null;
1100
    PreparedStatement pStmt=null;
1101
    ResultSet rs=null;
1102
    DBConnection conn=null;
1103
    int serialNumber=-1;
1104
    String query="SELECT docId from xml_relation where subject = ? or "
1105
                                                +"object = ?";
1106
    
1107
    try
1108
    {
1109
      //check out DBConnection
1110
      conn=DBConnectionPool.getDBConnection("AccessControlList.getDataSetId");
1111
      serialNumber=conn.getCheckOutSerialNumber();
1112
      
1113
      pStmt=conn.prepareStatement(query);
1114
      //bind the value to query
1115
      pStmt.setString(1, accessDocId);
1116
      pStmt.setString(2, accessDocId);
1117
      //execute the query
1118
      pStmt.execute();
1119
      rs=pStmt.getResultSet();
1120
      //process the result
1121
      if (rs.next()) //There are some records for the data set id for access id
1122
      {
1123
        dataSetId=rs.getString(1);
1124
      }
1125
      else //No data set id for the given access id in xml_relation table
1126
      {
1127
        dataSetId=null;
1128
      }
1129
    }//try
1130
    finally
1131
    {
1132
      try
1133
      {
1134
        pStmt.close();
1135
      }
1136
      finally
1137
      {
1138
        DBConnectionPool.returnDBConnection(conn, serialNumber);
1139
      }
1140
    }
1141
    return dataSetId;
1142
  }//getDataPackageId() 
1143
  
1144
  /**
1145
    * Check from db connection if at least one of the list of @principals
1146
    * has @permission on @docid.
1147
    * @param permission permission type to check for
1148
    * @param principals list of names of principals to check for @permission
1149
    * @param docid document identifier to check on
1150
    */
1151
  public static boolean hasPermission(String permission, String user,
1152
                               String[] groups, String docId )
1153
                 throws SQLException, Exception
1154
  {
1155
    //detele the rev number if docid contains it
1156
    docId=MetaCatUtil.getDocIdFromString(docId);
1157
    boolean hasPermission=false;
1158
    String [] userPackage=null;
1159
    //for the commnad line invocation
1160
    if ((user==null) && (groups==null || groups.length==0))
1161
    {
1162
      return true;
1163
    }
1164
   
1165
    //create a userpackage including user, public and group member
1166
    userPackage=createUsersPackage(user, groups);
1167
    
1168
    //if the requested document is access documents and requested permission
1169
    //is "write", the user should have "all" right
1170
    if (isAccessDocument(docId) && (intValue(permission)==WRITE))
1171
    {
1172
      hasPermission = hasPermission(userPackage,docId, "ALL");
1173
    }//if
1174
    else //in other situation, just check the request permission
1175
    {
1176
    
1177
      // Check for @permission on @docid for @user and/or @groups
1178
      hasPermission = hasPermission(userPackage,docId, permission);
1179
     
1180
    }//else
1181
    
1182
    return hasPermission;
1183
  }
1184
 
1185
  /**
1186
    * Check from db connection if the users in String array @principals has
1187
    * @permission on @docid* 
1188
    * @param principals, names in userPakcage need to check for @permission
1189
    * @param docid, document identifier to check on
1190
    * @param permission, permission (write or all...) to check for 
1191
    */
1192
  private static boolean hasPermission(String [] principals, String docId,
1193
                                            String permission)
1194
                         throws SQLException
1195
  {
1196
    try 
1197
    {
1198
      //first, if there is a docid owner in user package, return true
1199
      //because doc owner has all permssion 
1200
      if (containDocumentOwner(principals, docId))
1201
      {
1202
          
1203
          return true;
1204
      }
1205
      
1206
      //If there is no owner in user package, checking the table
1207
      //check perm_order
1208
      if (isAllowFirst(principals, docId))
1209
      {
1210
        
1211
        if (hasExplicitDenyRule(principals, docId, permission))
1212
        {
1213
          //if it is allowfirst and has deny rule(either explicit )
1214
          //deny access
1215
          return false;
1216
        }//if
1217
        else if ( hasAllowRule(principals, docId, permission))
1218
        {
1219
          //if it is allowfirst and hasn't deny rule and has allow rule
1220
          //allow access
1221
          return true;
1222
        }//else if
1223
        else
1224
        {
1225
          //other situation deny access
1226
          return false;
1227
        }//else
1228
     }//if isAllowFirst
1229
     else //denyFirst
1230
     {
1231
       if (hasAllowRule(principals, docId, permission))
1232
       {
1233
         //if it is denyFirst and has allow rule, allow access
1234
         return true;
1235
       }
1236
       else
1237
       {
1238
         //if it is denyfirst but no allow rule, deny access
1239
         return false;
1240
       }
1241
     }//else denyfirst
1242
    }//try
1243
    catch (Exception e)
1244
    {
1245
      MetaCatUtil.debugMessage("There is a exception in hasPermission method: "
1246
                         +e.getMessage(), 50);
1247
    }
1248
   
1249
    return false;
1250
  }//hasPermission
1251
 
1252

    
1253
 
1254
 
1255
  /**
1256
    * Get Access Control List information for document from db connetion.
1257
    * User or Group should have permissions for reading
1258
    * access control information for a document specified by @docid.
1259
    * @param docid document identifier which acl info to get
1260
    * @param user name of user connected to Metacat system
1261
    * @param groups names of user's groups to which user belongs
1262
    */
1263
  public String getACL(String docid, String user, String[] groups) 
1264
          throws SQLException, Exception
1265
  {
1266
    StringBuffer output = new StringBuffer();
1267
    StringBuffer outTemp = new StringBuffer();
1268
    MetaCatUtil util = new MetaCatUtil();
1269
    String accDoctype = util.getOption("accessdoctype");
1270
    String server = util.getOption("server");
1271
    String docurl = "metacat://" + server + "/?docid=" + docid;
1272
    String systemID;
1273
    boolean isOwned = false;
1274
    boolean hasPermission = false;
1275
    String publicAcc;
1276
    
1277
    String acfid = "";
1278
    String acfid_prev = "";
1279
    String principal;
1280
    Vector principalArr = new Vector();
1281
    int permission;
1282
    int perm_prev = -1;
1283
    String permType;
1284
    String permOrder = "";
1285
    String permOrder_prev = "";
1286
    String beginTime = "";
1287
    String begin_prev = "";
1288
    String endTime = "";
1289
    String end_prev = "";
1290
    int ticketCount = -1;
1291
    int ticket_prev = -1;
1292
    DBConnection conn = null;
1293
    int serialNumber = -1;
1294
    PreparedStatement pstmt = null;
1295
    try {
1296
      
1297
      //check out DBConnection
1298
      conn=DBConnectionPool.getDBConnection("AccessControlList.getACL");
1299
      serialNumber=conn.getCheckOutSerialNumber();
1300
      
1301
      isOwned = isOwned(docid, user);
1302
      systemID = getSystemID((String)MetaCatUtil.
1303
                                      getOptionList(accDoctype).elementAt(0));
1304
      publicAcc = getPublicAccess(docid);
1305
        
1306
      output.append("<?xml version=\"1.0\"?>\n");
1307
      output.append("<!DOCTYPE acl PUBLIC \"" + accDoctype + "\" \"" +
1308
                    systemID + "\">\n");
1309
      output.append("<acl authSystem=\"\">\n");
1310

    
1311
      
1312
      pstmt = conn.prepareStatement(
1313
              "SELECT distinct accessfileid, principal_name, permission, " +
1314
              "perm_type, perm_order, to_char(begin_time,'mm/dd/yyyy'), " +
1315
              "to_char(end_time,'mm/dd/yyyy'), ticket_count " +
1316
              "FROM xml_access WHERE docid = ? " +
1317
              "ORDER BY accessfileid, perm_order, perm_type, permission");
1318
      // Bind the values to the query
1319
      pstmt.setString(1, docid);
1320
      pstmt.execute();
1321
      ResultSet rs = pstmt.getResultSet();
1322
      boolean hasRows = rs.next();
1323
      while (hasRows) {
1324

    
1325
        acfid = rs.getString(1);
1326
        principal = rs.getString(2);
1327
        permission = rs.getInt(3);
1328
        permType = rs.getString(4);
1329
        permOrder = rs.getString(5);
1330
        beginTime = rs.getString(6);
1331
        endTime = rs.getString(7);
1332
        ticketCount = rs.getInt(8);
1333

    
1334
        // if @docid is not owned by @user, only ACL info from that
1335
        // access files to which @user/@groups has "read" permission
1336
        // is extracted
1337
        if ( !isOwned ) {
1338
          if ( !acfid.equals(acfid_prev) ) {
1339
            acfid_prev = acfid;
1340
            hasPermission = this.hasPermission("READ",user,groups,acfid);
1341
          }
1342
          if ( !hasPermission ) {
1343
            rs.next();
1344
            continue;
1345
          }
1346
        }
1347
        
1348
        // open <resource> tag
1349
        if ( !permOrder.equals(permOrder_prev) ) {
1350
          // close </resource> tag if any was opened 
1351
          output.append(outTemp.toString());
1352
          outTemp = new StringBuffer();
1353
          if ( !permOrder_prev.equals("") ) {
1354
            output.append("  </resource>\n");
1355
          }
1356
          output.append("  <resource order=\"" + permOrder + "\" public=\"" +
1357
                        publicAcc + "\">\n");
1358
          output.append("    <resourceIdentifier>" + docurl + 
1359
                        "</resourceIdentifier>\n");
1360
          permOrder_prev = permOrder;
1361
        }
1362
        
1363
        // close </allow> or </deny> tag then open new one
1364
        if ( permission != perm_prev ||
1365
             (endTime == null) && (end_prev != null) ||
1366
             (beginTime == null) && (begin_prev != null) ||
1367
             endTime != null && !endTime.equals(end_prev)  ||
1368
             beginTime != null && !beginTime.equals(begin_prev) ||
1369
             ticketCount != ticket_prev )  {
1370
          output.append(outTemp.toString());
1371
          outTemp = new StringBuffer();
1372
          principalArr.removeAllElements();
1373
          output.append("    <" + permType + ">\n");
1374
        }
1375
        
1376
        // put all principals here for the same 
1377
        // permission, duration and ticket_count
1378
        if ( !principalArr.contains(principal) ) {
1379
          principalArr.addElement(principal);
1380
          output.append("      <principal>" + principal + "</principal>\n");
1381
        } 
1382
        
1383
        // prepare <permission> tags, <duration> and <ticketCount>
1384
        // if any to put within <allow> (<deny>) by next cicle
1385
        if ( permission != perm_prev || 
1386
             (endTime == null) && (end_prev != null) ||
1387
             (beginTime == null) && (begin_prev != null) ||
1388
             endTime != null && !endTime.equals(end_prev)  ||
1389
             beginTime != null && !beginTime.equals(begin_prev) ||
1390
             ticketCount != ticket_prev )  {
1391
          if ( (permission & READ) != 0 ) {
1392
            outTemp.append("      <permission>read</permission>\n");
1393
          }
1394
          if ( (permission & WRITE) != 0 ) {
1395
            outTemp.append("      <permission>write</permission>\n");
1396
          }
1397
          if ( (permission & ALL) != 0 ) {
1398
            outTemp.append("      <permission>all</permission>\n");
1399
          }
1400
          if ( (beginTime != null) || (endTime != null) ) {
1401
            outTemp.append("      <duration>" + beginTime + " " + endTime +
1402
                          "</duration>\n");
1403
          }
1404
          if ( ticketCount > 0 ) {
1405
            outTemp.append("      <ticketCount>" + ticketCount + 
1406
                          "</ticketCount>\n");
1407
          }
1408
          outTemp.append("    </" + permType + ">\n");
1409
          perm_prev = permission;
1410
          ticket_prev = ticketCount;
1411
          begin_prev = beginTime;
1412
          end_prev = endTime;
1413
        }
1414
        
1415
        hasRows = rs.next();
1416
      }
1417

    
1418
      // close <allow> or <deny> if anything left in outTemp var
1419
      output.append(outTemp.toString());
1420

    
1421
      // If there are no any acl info for @docid accessible by @user/@group,
1422
      // extract only the following information
1423
      if ( permOrder.equals("") ) {
1424
        output.append("  <resource public=\"" + publicAcc + "\">\n");
1425
        output.append("    <resourceIdentifier>" + docurl + 
1426
                      "</resourceIdentifier>\n");
1427
      }
1428
      
1429
      // always close them
1430
      output.append("  </resource>\n");
1431
      output.append("</acl>\n");
1432
      
1433
      pstmt.close();
1434

    
1435
      return output.toString();
1436

    
1437
    } catch (SQLException e) {
1438
      throw new 
1439
      SQLException("AccessControlList.getACL(). " + e.getMessage());
1440
    }
1441
    finally
1442
    {
1443
      try
1444
      {
1445
        pstmt.close();
1446
      }
1447
      finally
1448
      {
1449
        DBConnectionPool.returnDBConnection(conn, serialNumber);
1450
      }
1451
    }
1452
  }
1453
  
1454
  /* Check if @user is owner of @docid from db conn. */
1455
  private boolean isOwned(String docid, String user) throws SQLException {
1456
    
1457
    PreparedStatement pstmt = null;
1458
    DBConnection conn = null;
1459
    int serialNumber = -1;
1460
    try
1461
    {
1462
      //check out DBConnection
1463
      conn=DBConnectionPool.getDBConnection("AccessControlList.isOwned");
1464
      serialNumber=conn.getCheckOutSerialNumber();
1465
      pstmt = conn.prepareStatement("SELECT 'x' FROM xml_documents " +
1466
                                  "WHERE docid = ? " + 
1467
                                  "AND user_owner = ?");
1468
      pstmt.setString(1, docid);
1469
      pstmt.setString(2, user);
1470
      pstmt.execute();
1471
      ResultSet rs = pstmt.getResultSet();
1472
      boolean hasRow = rs.next();
1473
      return hasRow;
1474
    }
1475
    finally
1476
    {
1477
      try
1478
      {
1479
        pstmt.close();
1480
      }
1481
      finally
1482
      {
1483
        DBConnectionPool.returnDBConnection(conn, serialNumber);
1484
      }
1485
    }
1486
  }
1487

    
1488
  /* Get the flag for public "read" access for @docid from db conn. */
1489
  private String getPublicAccess(String docid) throws SQLException {
1490
    
1491
    int publicAcc = 0;
1492
    PreparedStatement pstmt = null;
1493
    DBConnection conn = null;
1494
    int serialNumber = -1;
1495
    try
1496
    {
1497
      //check out DBConnection
1498
      conn=DBConnectionPool.getDBConnection("AccessControlList.getPublicAcces");
1499
      serialNumber=conn.getCheckOutSerialNumber();
1500
      pstmt = conn.prepareStatement("SELECT public_access FROM xml_documents " +
1501
                                  "WHERE docid = ?");
1502
      pstmt.setString(1, docid);
1503
      pstmt.execute();
1504
      ResultSet rs = pstmt.getResultSet();
1505
      boolean hasRow = rs.next();
1506
      if ( hasRow ) {
1507
        publicAcc = rs.getInt(1);
1508
      }
1509
    
1510
      return (publicAcc == 1) ? "yes" : "no";
1511
    }
1512
    finally
1513
    {
1514
      try
1515
      {
1516
        pstmt.close();
1517
      }
1518
      finally
1519
      {
1520
        DBConnectionPool.returnDBConnection(conn, serialNumber);
1521
      }
1522
    }
1523
  }
1524

    
1525
  /* Get SystemID for @publicID from Metacat DB Catalog. */
1526
  private String getSystemID(String publicID) throws SQLException {
1527
    
1528
    String systemID = "";
1529
    PreparedStatement pstmt = null;
1530
    DBConnection conn = null;
1531
    int serialNumber = -1;
1532
    
1533
    try
1534
    {
1535
      //check out DBConnection
1536
      conn=DBConnectionPool.getDBConnection("AccessControlList.getSystemID");
1537
      serialNumber=conn.getCheckOutSerialNumber();
1538
    
1539
      pstmt = conn.prepareStatement("SELECT system_id FROM xml_catalog " +
1540
                                  "WHERE entry_type = 'DTD' " + 
1541
                                  "AND public_id = ?");
1542
      pstmt.setString(1, publicID);
1543
      pstmt.execute();
1544
      ResultSet rs = pstmt.getResultSet();
1545
      boolean hasRow = rs.next();
1546
      if ( hasRow ) {
1547
        systemID = rs.getString(1);
1548
      }
1549
    
1550
      return systemID;
1551
    }//try
1552
    finally
1553
    {
1554
      
1555
      try
1556
      {
1557
        pstmt.close();
1558
      }
1559
      finally
1560
      {
1561
        DBConnectionPool.returnDBConnection(conn, serialNumber);
1562
      }
1563
    }//finally
1564
  }
1565

    
1566
}
(3-3/53)