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: 2005-10-04 10:58:48 -0700 (Tue, 04 Oct 2005) $'
12
 * '$Revision: 2641 $'
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, int rev,//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+sep+rev);
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
            // the docid get here has revision number, so we need to 
332
            // remove it.
333
            //docid = MetaCatUtil.getDocIdFromAccessionNumber(docid);
334
            //System.out.println("The docid insert is!!!!!!!!!! "+ docid);
335
            insertPermissions(docid,leavingTagName);
336
          }
337
          
338
          // if acl is not in object list
339
          //should insert permission for aclid itself into database
340
          /*if (!aclObjects.contains(aclid))
341
          {
342
            DocumentIdentifier aclIdItself = new DocumentIdentifier(aclid);
343
            String aclIdString = aclIdItself.getIdentifier();
344
            insertPermissions(aclIdString,leavingTagName);
345
          }*/
346
          
347

    
348
        } catch (SQLException sqle) {
349
          throw new SAXException(sqle);
350
        } catch (Exception e) {
351
          throw new SAXException(e);
352
        }
353
      }
354

    
355
      // reset the allow/deny permission
356
      principal = new Vector();
357
      permission = 0;
358
      beginTime = null;
359
      endTime = null;
360
      ticketCount = 0;
361
    
362
    }
363

    
364
  }
365

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

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

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

    
399
  /**
400
   * Get the document name.
401
   */
402
  public String getDocname() {
403
    return docname;
404
  }
405

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

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

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

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

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

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

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

    
650
    return txtPerm.append("\"").toString();
651
  }
652

    
653
  /**
654
    * Get Access Control List information for document from db connetion.
655
    * User or Group should have permissions for reading
656
    * access control information for a document specified by @docid.
657
    * @param docid document identifier which acl info to get
658
    * @param user name of user connected to Metacat system
659
    * @param groups names of user's groups to which user belongs
660
    */
661
  public String getACL(String docid, String user, String[] groups) 
662
          throws SQLException, Exception
663
  {
664
    StringBuffer output = new StringBuffer();
665
    StringBuffer outTemp = new StringBuffer();
666
    MetaCatUtil util = new MetaCatUtil();
667
    String accDoctype = util.getOption("accessdoctype");
668
    String server = util.getOption("server");
669
    String docurl = "metacat://" + server + "/?docid=" + docid;
670
    String systemID;
671
    boolean isOwned = false;
672
    boolean hasPermission = false;
673
    String publicAcc;
674
    
675
    String acfid = "";
676
    String acfid_prev = "";
677
    String principal;
678
    Vector principalArr = new Vector();
679
    int permission;
680
    int perm_prev = -1;
681
    String permType;
682
    String permOrder = "";
683
    String permOrder_prev = "";
684
    String beginTime = "";
685
    String begin_prev = "";
686
    String endTime = "";
687
    String end_prev = "";
688
    int ticketCount = -1;
689
    int ticket_prev = -1;
690
    DBConnection conn = null;
691
    int serialNumber = -1;
692
    PreparedStatement pstmt = null;
693
    try {
694
      
695
      //check out DBConnection
696
      conn=DBConnectionPool.getDBConnection("AccessControlList.getACL");
697
      serialNumber=conn.getCheckOutSerialNumber();
698
      
699
      isOwned = isOwned(docid, user);
700
      systemID = getSystemID((String)MetaCatUtil.
701
                                      getOptionList(accDoctype).elementAt(0));
702
      publicAcc = getPublicAccess(docid);
703
        
704
      output.append("<?xml version=\"1.0\"?>\n");
705
      output.append("<!DOCTYPE acl PUBLIC \"" + accDoctype + "\" \"" +
706
                    systemID + "\">\n");
707
      output.append("<acl authSystem=\"\">\n");
708

    
709
      
710
      pstmt = conn.prepareStatement(
711
              "SELECT distinct accessfileid, principal_name, permission, " +
712
              "perm_type, perm_order, to_char(begin_time,'mm/dd/yyyy'), " +
713
              "to_char(end_time,'mm/dd/yyyy'), ticket_count " +
714
              "FROM xml_access WHERE docid = ? " +
715
              "ORDER BY accessfileid, perm_order, perm_type, permission");
716
      // Bind the values to the query
717
      pstmt.setString(1, docid);
718
      pstmt.execute();
719
      ResultSet rs = pstmt.getResultSet();
720
      boolean hasRows = rs.next();
721
      while (hasRows) {
722

    
723
        acfid = rs.getString(1);
724
        principal = rs.getString(2);
725
        permission = rs.getInt(3);
726
        permType = rs.getString(4);
727
        permOrder = rs.getString(5);
728
        beginTime = rs.getString(6);
729
        endTime = rs.getString(7);
730
        ticketCount = rs.getInt(8);
731

    
732
        // if @docid is not owned by @user, only ACL info from that
733
        // access files to which @user/@groups has "read" permission
734
        // is extracted
735
        if ( !isOwned ) {
736
          if ( !acfid.equals(acfid_prev) ) {
737
            acfid_prev = acfid;
738
            //hasPermission = this.hasPermission("READ",user,groups,acfid);
739
             PermissionController controller = new PermissionController(acfid);
740
             hasPermission = controller.hasPermission(user,groups,
741
                                            AccessControlInterface.READSTRING);
742
          }
743
          if ( !hasPermission ) {
744
            rs.next();
745
            continue;
746
          }
747
        }
748
        
749
        // open <resource> tag
750
        if ( !permOrder.equals(permOrder_prev) ) {
751
          // close </resource> tag if any was opened 
752
          output.append(outTemp.toString());
753
          outTemp = new StringBuffer();
754
          if ( !permOrder_prev.equals("") ) {
755
            output.append("  </resource>\n");
756
          }
757
          output.append("  <resource order=\"" + permOrder + "\" public=\"" +
758
                        publicAcc + "\">\n");
759
          output.append("    <resourceIdentifier>" + docurl + 
760
                        "</resourceIdentifier>\n");
761
          permOrder_prev = permOrder;
762
        }
763
        
764
        // close </allow> or </deny> tag then open new one
765
        if ( permission != perm_prev ||
766
             (endTime == null) && (end_prev != null) ||
767
             (beginTime == null) && (begin_prev != null) ||
768
             endTime != null && !endTime.equals(end_prev)  ||
769
             beginTime != null && !beginTime.equals(begin_prev) ||
770
             ticketCount != ticket_prev )  {
771
          output.append(outTemp.toString());
772
          outTemp = new StringBuffer();
773
          principalArr.removeAllElements();
774
          output.append("    <" + permType + ">\n");
775
        }
776
        
777
        // put all principals here for the same 
778
        // permission, duration and ticket_count
779
        if ( !principalArr.contains(principal) ) {
780
          principalArr.addElement(principal);
781
          output.append("      <principal>" + principal + "</principal>\n");
782
        } 
783
        
784
        // prepare <permission> tags, <duration> and <ticketCount>
785
        // if any to put within <allow> (<deny>) by next cicle
786
        if ( permission != perm_prev || 
787
             (endTime == null) && (end_prev != null) ||
788
             (beginTime == null) && (begin_prev != null) ||
789
             endTime != null && !endTime.equals(end_prev)  ||
790
             beginTime != null && !beginTime.equals(begin_prev) ||
791
             ticketCount != ticket_prev )  {
792
          if ( (permission & READ) != 0 ) {
793
            outTemp.append("      <permission>read</permission>\n");
794
          }
795
          if ( (permission & WRITE) != 0 ) {
796
            outTemp.append("      <permission>write</permission>\n");
797
          }
798
          if ( (permission & ALL) != 0 ) {
799
            outTemp.append("      <permission>all</permission>\n");
800
          }
801
          if ( (beginTime != null) || (endTime != null) ) {
802
            outTemp.append("      <duration>" + beginTime + " " + endTime +
803
                          "</duration>\n");
804
          }
805
          if ( ticketCount > 0 ) {
806
            outTemp.append("      <ticketCount>" + ticketCount + 
807
                          "</ticketCount>\n");
808
          }
809
          outTemp.append("    </" + permType + ">\n");
810
          perm_prev = permission;
811
          ticket_prev = ticketCount;
812
          begin_prev = beginTime;
813
          end_prev = endTime;
814
        }
815
        
816
        hasRows = rs.next();
817
      }
818

    
819
      // close <allow> or <deny> if anything left in outTemp var
820
      output.append(outTemp.toString());
821

    
822
      // If there are no any acl info for @docid accessible by @user/@group,
823
      // extract only the following information
824
      if ( permOrder.equals("") ) {
825
        output.append("  <resource public=\"" + publicAcc + "\">\n");
826
        output.append("    <resourceIdentifier>" + docurl + 
827
                      "</resourceIdentifier>\n");
828
      }
829
      
830
      // always close them
831
      output.append("  </resource>\n");
832
      output.append("</acl>\n");
833
      
834
      pstmt.close();
835

    
836
      return output.toString();
837

    
838
    } catch (SQLException e) {
839
      throw new 
840
      SQLException("AccessControlList.getACL(). " + e.getMessage());
841
    }
842
    finally
843
    {
844
      try
845
      {
846
        pstmt.close();
847
      }
848
      finally
849
      {
850
        DBConnectionPool.returnDBConnection(conn, serialNumber);
851
      }
852
    }
853
  }
854
  
855
  /* Check if @user is owner of @docid from db conn. */
856
  private boolean isOwned(String docid, String user) throws SQLException {
857
    
858
    PreparedStatement pstmt = null;
859
    DBConnection conn = null;
860
    int serialNumber = -1;
861
    try
862
    {
863
      //check out DBConnection
864
      conn=DBConnectionPool.getDBConnection("AccessControlList.isOwned");
865
      serialNumber=conn.getCheckOutSerialNumber();
866
      pstmt = conn.prepareStatement("SELECT 'x' FROM xml_documents " +
867
                                  "WHERE docid = ? " + 
868
                                  "AND user_owner = ?");
869
      pstmt.setString(1, docid);
870
      pstmt.setString(2, user);
871
      pstmt.execute();
872
      ResultSet rs = pstmt.getResultSet();
873
      boolean hasRow = rs.next();
874
      return hasRow;
875
    }
876
    finally
877
    {
878
      try
879
      {
880
        pstmt.close();
881
      }
882
      finally
883
      {
884
        DBConnectionPool.returnDBConnection(conn, serialNumber);
885
      }
886
    }
887
  }
888

    
889
  /* Get the flag for public "read" access for @docid from db conn. */
890
  private String getPublicAccess(String docid) throws SQLException {
891
    
892
    int publicAcc = 0;
893
    PreparedStatement pstmt = null;
894
    DBConnection conn = null;
895
    int serialNumber = -1;
896
    try
897
    {
898
      //check out DBConnection
899
      conn=DBConnectionPool.getDBConnection("AccessControlList.getPublicAcces");
900
      serialNumber=conn.getCheckOutSerialNumber();
901
      pstmt = conn.prepareStatement("SELECT public_access FROM xml_documents " +
902
                                  "WHERE docid = ?");
903
      pstmt.setString(1, docid);
904
      pstmt.execute();
905
      ResultSet rs = pstmt.getResultSet();
906
      boolean hasRow = rs.next();
907
      if ( hasRow ) {
908
        publicAcc = rs.getInt(1);
909
      }
910
    
911
      return (publicAcc == 1) ? "yes" : "no";
912
    }
913
    finally
914
    {
915
      try
916
      {
917
        pstmt.close();
918
      }
919
      finally
920
      {
921
        DBConnectionPool.returnDBConnection(conn, serialNumber);
922
      }
923
    }
924
  }
925

    
926
  /* Get SystemID for @publicID from Metacat DB Catalog. */
927
  private String getSystemID(String publicID) throws SQLException {
928
    
929
    String systemID = "";
930
    PreparedStatement pstmt = null;
931
    DBConnection conn = null;
932
    int serialNumber = -1;
933
    
934
    try
935
    {
936
      //check out DBConnection
937
      conn=DBConnectionPool.getDBConnection("AccessControlList.getSystemID");
938
      serialNumber=conn.getCheckOutSerialNumber();
939
    
940
      pstmt = conn.prepareStatement("SELECT system_id FROM xml_catalog " +
941
                                  "WHERE entry_type = 'DTD' " + 
942
                                  "AND public_id = ?");
943
      pstmt.setString(1, publicID);
944
      pstmt.execute();
945
      ResultSet rs = pstmt.getResultSet();
946
      boolean hasRow = rs.next();
947
      if ( hasRow ) {
948
        systemID = rs.getString(1);
949
      }
950
    
951
      return systemID;
952
    }//try
953
    finally
954
    {
955
      
956
      try
957
      {
958
        pstmt.close();
959
      }
960
      finally
961
      {
962
        DBConnectionPool.returnDBConnection(conn, serialNumber);
963
      }
964
    }//finally
965
  }
966

    
967
}
(3-3/63)