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-07-23 18:11:37 -0700 (Wed, 23 Jul 2003) $'
12
 * '$Revision: 1754 $'
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
              "ticket_count, accessfileid) VALUES " +
509
              "(?,?,?,?,?,?,?)");
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(7, aclid);
518
      if ( ticketCount > 0 ) {
519
        pstmt.setString(6, "" + ticketCount);
520
      } else {
521
        pstmt.setString(6, null);
522
      }
523
      
524
      //incrase usagecount for DBConnection
525
      //conn.increaseUsageCount(1);
526
      String prName;
527
      for ( int j = 0; j < principal.size(); j++ ) {
528
        prName = (String)principal.elementAt(j);
529
        pstmt.setString(2, prName);
530
        pstmt.execute();
531
      /*    
532
        // check if there are conflict with permission's order
533
        String permOrderOpos = permOrder;
534
        int perm = getPermissions(permission, prName, docid, permOrder);
535
        if (  perm != 0 ) {
536
          if ( permOrder.equals("allowFirst") ) {
537
            permOrderOpos = "denyFirst";
538
          } else if ( permOrder.equals("denyFirst") ) {
539
            permOrderOpos = "allowFirst";
540
          }
541
          throw new SQLException("Permission(s) " + txtValue(perm) + 
542
                    " for \"" + prName + "\" on document #" + docid +
543
                    " has/have been used with \"" + permOrderOpos + "\"");
544
        }
545
      */
546
      }
547
      pstmt.close();
548

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

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

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

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

    
644
    return txtPerm.append("\"").toString();
645
  }
646

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

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

    
717
        acfid = rs.getString(1);
718
        principal = rs.getString(2);
719
        permission = rs.getInt(3);
720
        permType = rs.getString(4);
721
        permOrder = rs.getString(5);
722
        beginTime = rs.getString(6);
723
        endTime = rs.getString(7);
724
        ticketCount = rs.getInt(8);
725

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

    
813
      // close <allow> or <deny> if anything left in outTemp var
814
      output.append(outTemp.toString());
815

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

    
830
      return output.toString();
831

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

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

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

    
961
}
(3-3/63)