Project

General

Profile

1 555 bojilova
/**
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
 *
9
 *   '$Author$'
10
 *     '$Date$'
11
 * '$Revision$'
12 669 jones
 *
13
 * This program is free software; you can redistribute it and/or modify
14
 * it under the terms of the GNU General Public License as published by
15
 * the Free Software Foundation; either version 2 of the License, or
16
 * (at your option) any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * You should have received a copy of the GNU General Public License
24
 * along with this program; if not, write to the Free Software
25
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 555 bojilova
 */
27
28
package edu.ucsb.nceas.metacat;
29
30
import java.io.*;
31
import java.sql.*;
32
import java.util.Stack;
33
import java.util.Vector;
34 652 bojilova
import java.util.Hashtable;
35
import java.net.URL;
36
import java.net.MalformedURLException;
37 555 bojilova
38
import org.xml.sax.Attributes;
39
import org.xml.sax.InputSource;
40 598 bojilova
import org.xml.sax.ContentHandler;
41
import org.xml.sax.EntityResolver;
42
import org.xml.sax.ErrorHandler;
43 555 bojilova
import org.xml.sax.SAXException;
44
import org.xml.sax.SAXParseException;
45
import org.xml.sax.XMLReader;
46
import org.xml.sax.helpers.XMLReaderFactory;
47
import org.xml.sax.helpers.DefaultHandler;
48
49
/**
50
 * A Class that loads eml-access.xml file containing ACL for a metadata
51
 * document into relational DB. It extends DefaultHandler class to handle
52
 * SAX parsing events when processing the XML stream.
53
 */
54 1368 tao
public class AccessControlList extends DefaultHandler
55
                               implements AccessControlInterface
56
{
57 555 bojilova
58 1368 tao
59 774 bojilova
  private static String sysdate = MetaCatUtil.dbAdapter.getDateTimeFunction();
60
  private static String isnull = MetaCatUtil.dbAdapter.getIsNULLFunction();
61 961 tao
62 1214 tao
  private DBConnection connection;
63 555 bojilova
  private String parserName;
64
  private Stack elementStack;
65 645 bojilova
  private String server;
66 802 bojilova
  private String sep;
67 961 tao
68 598 bojilova
  private boolean	processingDTD;
69 645 bojilova
  private String  user;
70 802 bojilova
  private String[] groups;
71 638 bojilova
  private String  aclid;
72 802 bojilova
  private int     rev;
73 598 bojilova
  private String 	docname;
74
  private String 	doctype;
75
  private String 	systemid;
76
77 665 bojilova
  private String docurl;
78
  private Vector resourceURL;
79
  private Vector resourceID;
80 660 bojilova
  private Vector principal;
81 570 bojilova
  private int    permission;
82
  private String permType;
83
  private String permOrder;
84 802 bojilova
//  private String publicAcc;
85 570 bojilova
  private String beginTime;
86
  private String endTime;
87
  private int    ticketCount;
88 684 bojilova
  private int    serverCode = 1;
89 802 bojilova
90
  private Vector aclObjects = new Vector();
91 859 berkley
  private boolean instarttag = true;
92
  private String tagName = "";
93 555 bojilova
  /**
94
   * Construct an instance of the AccessControlList class.
95 688 bojilova
   * It is used by the permission check up from DBQuery or DocumentImpl
96
   * and from "getaccesscontrol" action
97 570 bojilova
   *
98 684 bojilova
   * @param conn the JDBC connection where acl info is get
99 570 bojilova
   */
100 1214 tao
  public AccessControlList(DBConnection conn) throws SQLException
101 570 bojilova
  {
102 1214 tao
    this.connection = conn;
103 570 bojilova
  }
104 1214 tao
105 570 bojilova
106 1214 tao
107
108 570 bojilova
  /**
109
   * Construct an instance of the AccessControlList class.
110 555 bojilova
   * It parse acl file and loads acl data into db connection.
111
   *
112
   * @param conn the JDBC connection where acl data are loaded
113 684 bojilova
   * @param aclid the Accession# of the document with the acl data
114 570 bojilova
   * @param acl the acl file containing acl data
115 684 bojilova
   * @param user the user connected to MetaCat servlet and owns the document
116 802 bojilova
   * @param groups the groups to which user belongs
117 684 bojilova
   * @param serverCode the serverid from xml_replication on which this document
118
   *        resides.
119 555 bojilova
   */
120 2641 tao
  public AccessControlList(DBConnection conn, String aclid, int rev,//Reader acl,
121 802 bojilova
                           String user, String[] groups, int serverCode)
122 819 bojilova
                  throws SAXException, IOException, McdbException
123 555 bojilova
  {
124 802 bojilova
    String parserName = MetaCatUtil.getOption("saxparser");
125
    this.server = MetaCatUtil.getOption("server");
126
    this.sep = MetaCatUtil.getOption("accNumSeparator");
127 555 bojilova
128 1214 tao
    this.connection = conn;
129 555 bojilova
    this.parserName = parserName;
130 598 bojilova
    this.processingDTD = false;
131 570 bojilova
    this.elementStack = new Stack();
132
133 645 bojilova
    this.user = user;
134 802 bojilova
    this.groups = groups;
135 638 bojilova
    this.aclid = aclid;
136 665 bojilova
    this.resourceURL = new Vector();
137
    this.resourceID = new Vector();
138 660 bojilova
    this.principal = new Vector();
139 570 bojilova
    this.permission = 0;
140
    this.ticketCount = 0;
141 802 bojilova
  //  this.publicAcc = null;
142 684 bojilova
    this.serverCode = serverCode;
143 638 bojilova
144 819 bojilova
    // read the access file from db connection
145 2641 tao
    DocumentImpl acldoc = new DocumentImpl(aclid+sep+rev);
146 819 bojilova
    String acl = acldoc.toString();
147
    this.rev = acldoc.getRev();
148
149
    // Initialize the parse
150 555 bojilova
    XMLReader parser = initializeParser();
151 819 bojilova
    // parse the access file and write the info to xml_access
152
    parser.parse(new InputSource(new StringReader(acl)));
153
154 555 bojilova
  }
155
156 819 bojilova
// NOT USED
157
//  /**
158
//   * Construct an instance of the AccessControlList class.
159
//   * It parses eml-access file and loads acl data into db connection.
160
//   * It is used from command line execution.
161
//   *
162
//   * @param conn the JDBC connection where acl data are loaded
163
//   * @param docid the Accession# of the document with the acl data
164
//   * @param aclfilename the name of acl file containing acl data
165
//   * @param user the user connected to MetaCat servlet and owns the document
166
//   * @param groups the groups to which user belongs
167
//   */
168
//  public AccessControlList( Connection conn, String aclid, String aclfilename,
169
//                           String user, String[] groups )
170
//                  throws SAXException, IOException, McdbException
171
//  {
172
//    this(conn, aclid, new FileReader(new File(aclfilename).toString()),
173
//         user, groups, 1);
174
//  }
175 638 bojilova
176 660 bojilova
  /* Set up the SAX parser for reading the XML serialized ACL */
177 555 bojilova
  private XMLReader initializeParser() throws SAXException
178
  {
179
    XMLReader parser = null;
180
181
    // Get an instance of the parser
182
    parser = XMLReaderFactory.createXMLReader(parserName);
183
184 598 bojilova
    // Turn off validation
185 638 bojilova
    parser.setFeature("http://xml.org/sax/features/validation", true);
186 598 bojilova
187
    // Set Handlers in the parser
188 555 bojilova
    // Set the ContentHandler to this instance
189 598 bojilova
    parser.setContentHandler((ContentHandler)this);
190 555 bojilova
191 598 bojilova
    // make a DBEntityResolver instance
192
    // Set the EntityReslover to DBEntityResolver instance
193 1214 tao
    EntityResolver eresolver = new DBEntityResolver(connection,this,null);
194 598 bojilova
    parser.setEntityResolver((EntityResolver)eresolver);
195
196 555 bojilova
    // Set the ErrorHandler to this instance
197 598 bojilova
    parser.setErrorHandler((ErrorHandler)this);
198 555 bojilova
199 862 berkley
    return parser;
200 555 bojilova
  }
201
202
  /**
203 688 bojilova
   * Callback method used by the SAX Parser when beginning of the document
204 645 bojilova
   */
205
  public void startDocument() throws SAXException
206
  {
207
    //delete all previously submitted permissions @ relations
208
    //this happens only on UPDATE of the access file
209
    try {
210 819 bojilova
      this.aclObjects = getACLObjects(aclid);
211 802 bojilova
212 819 bojilova
      //delete all permissions for resources related to @aclid if any
213 645 bojilova
      if ( aclid != null ) {
214
        deletePermissionsForRelatedResources(aclid);
215
      }
216
    } catch (SQLException sqle) {
217
      throw new SAXException(sqle);
218
    }
219
  }
220
221
  /**
222 688 bojilova
   * Callback method used by the SAX Parser when the start tag of an
223 555 bojilova
   * element is detected. Used in this context to parse and store
224
   * the acl information in class variables.
225
   */
226
  public void startElement (String uri, String localName,
227
                            String qName, Attributes atts)
228
         throws SAXException
229
  {
230 859 berkley
    instarttag = true;
231
    if(localName.equals("allow"))
232
    {
233
      tagName = "allow";
234
    }
235
    else if(localName.equals("deny"))
236
    {
237
      tagName = "deny";
238
    }
239 555 bojilova
    BasicNode currentNode = new BasicNode(localName);
240
    if (atts != null) {
241
      int len = atts.getLength();
242
      for (int i = 0; i < len; i++) {
243
        currentNode.setAttribute(atts.getLocalName(i), atts.getValue(i));
244
      }
245
    }
246 802 bojilova
    if ( currentNode.getTagName().equals("acl") ) {
247 570 bojilova
      permOrder = currentNode.getAttribute("order");
248 802 bojilova
    //  publicAcc = currentNode.getAttribute("public");
249 570 bojilova
    }
250 555 bojilova
    elementStack.push(currentNode);
251
  }
252
253
  /**
254 688 bojilova
   * Callback method used by the SAX Parser when the text sequences of an
255 555 bojilova
   * xml stream are detected. Used in this context to parse and store
256
   * the acl information in class variables.
257 859 berkley
   */
258 555 bojilova
  public void characters(char ch[], int start, int length)
259
         throws SAXException
260
  {
261 859 berkley
    if(!instarttag)
262
    {
263
      return;
264
    }
265 555 bojilova
    String inputString = new String(ch, start, length);
266 859 berkley
    inputString = inputString.trim();
267 862 berkley
    //System.out.println("==============inputString: " + inputString);
268 555 bojilova
    BasicNode currentNode = (BasicNode)elementStack.peek();
269
    String currentTag = currentNode.getTagName();
270
271 802 bojilova
      if (currentTag.equals("principal")) {
272 645 bojilova
273 802 bojilova
        principal.addElement(inputString);
274 645 bojilova
275 802 bojilova
      } else if (currentTag.equals("permission")) {
276 645 bojilova
277 802 bojilova
        if ( inputString.trim().toUpperCase().equals("READ") ) {
278
          permission = permission | READ;
279
        } else if ( inputString.trim().toUpperCase().equals("WRITE") ) {
280
          permission = permission | WRITE;
281 944 tao
        } else if ( inputString.trim().toUpperCase().equals("CHANGEPERMISSION"))
282
        {
283 862 berkley
          permission = permission | CHMOD;
284 802 bojilova
        } else if ( inputString.trim().toUpperCase().equals("ALL") ) {
285
          permission = permission | ALL;
286 862 berkley
        }/*else{
287 802 bojilova
          throw new SAXException("Unknown permission type: " + inputString);
288 859 berkley
        }*/
289 645 bojilova
290 802 bojilova
      } else if ( currentTag.equals("startDate") && beginTime == null ) {
291
        beginTime = inputString.trim();
292 645 bojilova
293 802 bojilova
      } else if ( currentTag.equals("stopDate") && endTime == null) {
294
        endTime = inputString.trim();
295 645 bojilova
296 802 bojilova
      } else if (currentTag.equals("ticketCount") && ticketCount == 0 ) {
297
        try {
298
          ticketCount = (new Integer(inputString.trim())).intValue();
299
        } catch (NumberFormatException nfe) {
300
          throw new SAXException("Wrong integer format for:" + inputString);
301
        }
302 555 bojilova
      }
303
  }
304
305
  /**
306 688 bojilova
   * Callback method used by the SAX Parser when the end tag of an
307 555 bojilova
   * element is detected. Used in this context to parse and store
308
   * the acl information in class variables.
309
   */
310
  public void endElement (String uri, String localName, String qName)
311
         throws SAXException
312
  {
313 859 berkley
    instarttag = false;
314 688 bojilova
    BasicNode leaving = (BasicNode)elementStack.pop();
315
    String leavingTagName = leaving.getTagName();
316
317 802 bojilova
    if ( leavingTagName.equals("allow") ||
318
         leavingTagName.equals("deny")    ) {
319 570 bojilova
320
      if ( permission > 0 ) {
321 555 bojilova
322 570 bojilova
        // insert into db calculated permission for the list of principals
323
        try {
324 802 bojilova
          // go through the objects in xml_relation about this acl doc
325
          for (int i=0; i < aclObjects.size(); i++) {
326
            // docid of the current object
327
            String docid = (String)aclObjects.elementAt(i);
328 2641 tao
            //DocumentIdentifier docID = new DocumentIdentifier(docid);
329
            //docid = docID.getIdentifier();
330
            // the docid get here has revision number, so we need to
331
            // remove it.
332
            //docid = MetaCatUtil.getDocIdFromAccessionNumber(docid);
333
            //System.out.println("The docid insert is!!!!!!!!!! "+ docid);
334 802 bojilova
            insertPermissions(docid,leavingTagName);
335
          }
336 968 tao
337 1330 tao
          // if acl is not in object list
338 968 tao
          //should insert permission for aclid itself into database
339 1336 tao
          /*if (!aclObjects.contains(aclid))
340 1330 tao
          {
341
            DocumentIdentifier aclIdItself = new DocumentIdentifier(aclid);
342
            String aclIdString = aclIdItself.getIdentifier();
343
            insertPermissions(aclIdString,leavingTagName);
344 1336 tao
          }*/
345 968 tao
346 802 bojilova
347 570 bojilova
        } catch (SQLException sqle) {
348
          throw new SAXException(sqle);
349 802 bojilova
        } catch (Exception e) {
350
          throw new SAXException(e);
351 570 bojilova
        }
352
      }
353
354 688 bojilova
      // reset the allow/deny permission
355 660 bojilova
      principal = new Vector();
356 555 bojilova
      permission = 0;
357 570 bojilova
      beginTime = null;
358
      endTime = null;
359
      ticketCount = 0;
360 555 bojilova
361 570 bojilova
    }
362 555 bojilova
363
  }
364 598 bojilova
365 688 bojilova
  /**
366
    * SAX Handler that receives notification of DOCTYPE. Sets the DTD.
367
    * @param name name of the DTD
368
    * @param publicId Public Identifier of the DTD
369
    * @param systemId System Identifier of the DTD
370
    */
371 598 bojilova
  public void startDTD(String name, String publicId, String systemId)
372
              throws SAXException {
373
    docname = name;
374
    doctype = publicId;
375
    systemid = systemId;
376
  }
377
378
  /**
379 688 bojilova
   * SAX Handler that receives notification of the start of entities.
380
   * @param name name of the entity
381 598 bojilova
   */
382
  public void startEntity(String name) throws SAXException {
383
    if (name.equals("[dtd]")) {
384
      processingDTD = true;
385
    }
386
  }
387
388
  /**
389 688 bojilova
   * SAX Handler that receives notification of the end of entities.
390
   * @param name name of the entity
391 598 bojilova
   */
392
  public void endEntity(String name) throws SAXException {
393
    if (name.equals("[dtd]")) {
394
      processingDTD = false;
395
    }
396
  }
397
398
  /**
399 688 bojilova
   * Get the document name.
400 598 bojilova
   */
401
  public String getDocname() {
402
    return docname;
403
  }
404
405
  /**
406 688 bojilova
   * Get the document processing state.
407 598 bojilova
   */
408
  public boolean processingDTD() {
409
    return processingDTD;
410
  }
411
412 802 bojilova
  /* Get all objects associated with @aclid from db.*/
413
  private Vector getACLObjects(String aclid)
414 638 bojilova
          throws SQLException
415
  {
416 802 bojilova
    Vector aclObjects = new Vector();
417 1214 tao
    DBConnection conn = null;
418
    int serialNumber = -1;
419
    PreparedStatement pstmt = null;
420
    try
421
    {
422
      //get connection from DBConnectionPool
423
      conn=DBConnectionPool.getDBConnection("AccessControlList.getACLObject");
424
      serialNumber=conn.getCheckOutSerialNumber();
425
426
      // delete all acl records for resources related to @aclid if any
427
      pstmt = conn.prepareStatement(
428 802 bojilova
                             "SELECT object FROM xml_relation " +
429 830 jones
                             "WHERE subject = ? ");
430 1214 tao
      pstmt.setString(1,aclid);
431
      pstmt.execute();
432
      ResultSet rs = pstmt.getResultSet();
433
      boolean hasRows = rs.next();
434
      while (hasRows) {
435 2641 tao
        String object = rs.getString(1);
436
        //System.out.println("add acl object into vector !!!!!!!!!!!!!!!!!"+object);
437
        aclObjects.addElement(object);
438 1214 tao
        hasRows = rs.next();
439
      }//whil
440 802 bojilova
    }
441 1214 tao
    catch (SQLException e)
442
    {
443
      throw e;
444
    }
445
    finally
446
    {
447
      try
448
      {
449
        pstmt.close();
450
      }
451
      finally
452
      {
453
        //retrun DBConnection
454
        DBConnectionPool.returnDBConnection(conn,serialNumber);
455
      }
456
    }
457 802 bojilova
458
    return aclObjects;
459 638 bojilova
  }
460
461 802 bojilova
  /* Delete from db all permission for resources related to @aclid if any.*/
462
  private void deletePermissionsForRelatedResources(String aclid)
463 638 bojilova
          throws SQLException
464
  {
465 1214 tao
    //DBConnection conn = null;
466
    //int serialNumber = -1;
467
    Statement stmt = null;
468
    try
469
    {
470
      //check out DBConenction
471
      //conn=DBConnectionPool.getDBConnection("AccessControlList.deltePerm");
472
      //serialNumber=conn.getCheckOutSerialNumber();
473
      // delete all acl records for resources related to @aclid if any
474
      stmt = connection.createStatement();
475
      // Increase DBConnection usage count
476
      connection.increaseUsageCount(1);
477
      stmt.execute("DELETE FROM xml_access WHERE accessfileid = '" + aclid
478
                                                                      + "'");
479
      //increase usageCount!!!!!!
480
      //conn.increaseUsageCount(1);
481
    }
482
    catch (SQLException e)
483
    {
484
      throw e;
485
    }
486
    finally
487
    {
488
      stmt.close();
489
      //retrun DBConnection
490
      //DBConnectionPool.returnDBConnection(conn,serialNumber);
491
    }
492 645 bojilova
  }
493
494 1214 tao
  /* Insert into db calculated permission for the list of principals
495
   * The DBConnection it is use is class field. Because we want to keep rollback
496
   * features and it need use same connection
497
  */
498
499 802 bojilova
  private void insertPermissions(String docid, String permType )
500 1214 tao
                                            throws SQLException
501 555 bojilova
  {
502 1214 tao
    PreparedStatement pstmt = null;
503
    //DBConnection conn = null;
504
    //int serialNumber = -1;
505 555 bojilova
    try {
506 1214 tao
      //Check out DBConnection
507
      //conn=DBConnectionPool.getDBConnection("AccessControlList.insertPerm");
508
      //serialNumber=conn.getCheckOutSerialNumber();
509
510
      pstmt = connection.prepareStatement(
511 555 bojilova
              "INSERT INTO xml_access " +
512 645 bojilova
              "(docid, principal_name, permission, perm_type, perm_order," +
513 1750 tao
              "ticket_count, accessfileid) VALUES " +
514
              "(?,?,?,?,?,?,?)");
515 1214 tao
      // Increase DBConnection usage count
516
      connection.increaseUsageCount(1);
517 555 bojilova
      // Bind the values to the query
518 802 bojilova
      pstmt.setString(1, docid);
519 570 bojilova
      pstmt.setInt(3, permission);
520
      pstmt.setString(4, permType);
521
      pstmt.setString(5, permOrder);
522 1750 tao
      pstmt.setString(7, aclid);
523 570 bojilova
      if ( ticketCount > 0 ) {
524 2604 tao
        pstmt.setInt(6, ticketCount);
525 570 bojilova
      } else {
526 2604 tao
        pstmt.setInt(6, 0);
527 570 bojilova
      }
528 1214 tao
529
      //incrase usagecount for DBConnection
530
      //conn.increaseUsageCount(1);
531 688 bojilova
      String prName;
532 802 bojilova
      for ( int j = 0; j < principal.size(); j++ ) {
533
        prName = (String)principal.elementAt(j);
534
        pstmt.setString(2, prName);
535
        pstmt.execute();
536
      /*
537
        // check if there are conflict with permission's order
538
        String permOrderOpos = permOrder;
539
        int perm = getPermissions(permission, prName, docid, permOrder);
540
        if (  perm != 0 ) {
541
          if ( permOrder.equals("allowFirst") ) {
542
            permOrderOpos = "denyFirst";
543
          } else if ( permOrder.equals("denyFirst") ) {
544
            permOrderOpos = "allowFirst";
545 688 bojilova
          }
546 802 bojilova
          throw new SQLException("Permission(s) " + txtValue(perm) +
547
                    " for \"" + prName + "\" on document #" + docid +
548
                    " has/have been used with \"" + permOrderOpos + "\"");
549 665 bojilova
        }
550 802 bojilova
      */
551 570 bojilova
      }
552 672 bojilova
      pstmt.close();
553 555 bojilova
554 570 bojilova
    } catch (SQLException e) {
555
      throw new
556
      SQLException("AccessControlList.insertPermissions(): " + e.getMessage());
557 672 bojilova
    }
558 1214 tao
    finally
559
    {
560
      pstmt.close();
561
      //return the DBConnection
562
      //DBConnectionPool.returnDBConnection(conn, serialNumber);
563
    }
564 672 bojilova
  }
565
566 688 bojilova
  /* Get permissions with permission order different than @permOrder. */
567
  private int getPermissions(int permission, String principal,
568
                             String docid, String permOrder)
569
          throws SQLException
570
  {
571 1214 tao
    PreparedStatement pstmt = null;
572
    DBConnection conn = null;
573
    int serialNumber = -1;
574
    try
575
    {
576
      //check out DBConnection
577
      conn=DBConnectionPool.getDBConnection("AccessControlList.getPermissions");
578
      serialNumber=conn.getCheckOutSerialNumber();
579
      pstmt = conn.prepareStatement(
580 688 bojilova
            "SELECT permission FROM xml_access " +
581 765 bojilova
            "WHERE docid = ? " +
582
            "AND principal_name = ? " +
583
            "AND perm_order NOT = ?");
584 1214 tao
      pstmt.setString(1, docid);
585
      pstmt.setString(2, principal);
586
      pstmt.setString(3, permOrder);
587
      pstmt.execute();
588
      ResultSet rs = pstmt.getResultSet();
589
      boolean hasRow = rs.next();
590
      int perm = 0;
591
      while ( hasRow ) {
592
        perm = rs.getInt(1);
593
        perm = permission & perm;
594
        if ( perm != 0 ) {
595
          pstmt.close();
596
          return perm;
597
        }
598
        hasRow = rs.next();
599
      }
600
    }//try
601
    catch (SQLException e)
602
    {
603
      throw e;
604
    }
605
    finally
606
    {
607
      try
608
      {
609 1139 tao
        pstmt.close();
610 688 bojilova
      }
611 1214 tao
      finally
612
      {
613
        DBConnectionPool.returnDBConnection(conn, serialNumber);
614
      }
615 688 bojilova
    }
616
    return 0;
617
  }
618
619
  /* Get the int value of READ, WRITE or ALL. */
620 1368 tao
  public static int intValue ( String permission )
621 688 bojilova
  {
622 1368 tao
    if ( permission.equalsIgnoreCase("READ") ) {
623 688 bojilova
      return READ;
624 1368 tao
    } else if ( permission.equalsIgnoreCase("WRITE") ) {
625 688 bojilova
      return WRITE;
626 1368 tao
    } else if ( permission.equalsIgnoreCase("ALL") ) {
627 688 bojilova
      return ALL;
628
    }
629
630
    return -1;
631
  }
632
633
  /* Get the text value of READ, WRITE or ALL. */
634
  private String txtValue ( int permission )
635
  {
636
    StringBuffer txtPerm = new StringBuffer("\"");
637
    if ( (permission & READ) != 0 ) {
638
      txtPerm.append("read");
639
    }
640
    if ( (permission & WRITE) != 0 ) {
641
      if ( txtPerm.length() > 0 ) txtPerm.append(",");
642
      txtPerm.append("write");
643
    }
644
    if ( (permission & ALL) != 0 ) {
645
      if ( txtPerm.length() > 0 ) txtPerm.append(",");
646
      txtPerm.append("all");
647
    }
648
649
    return txtPerm.append("\"").toString();
650
  }
651
652 802 bojilova
  /**
653 688 bojilova
    * Get Access Control List information for document from db connetion.
654
    * User or Group should have permissions for reading
655
    * access control information for a document specified by @docid.
656
    * @param docid document identifier which acl info to get
657
    * @param user name of user connected to Metacat system
658 802 bojilova
    * @param groups names of user's groups to which user belongs
659 688 bojilova
    */
660 802 bojilova
  public String getACL(String docid, String user, String[] groups)
661 959 tao
          throws SQLException, Exception
662 570 bojilova
  {
663 688 bojilova
    StringBuffer output = new StringBuffer();
664
    StringBuffer outTemp = new StringBuffer();
665
    MetaCatUtil util = new MetaCatUtil();
666
    String accDoctype = util.getOption("accessdoctype");
667
    String server = util.getOption("server");
668
    String docurl = "metacat://" + server + "/?docid=" + docid;
669
    String systemID;
670
    boolean isOwned = false;
671
    boolean hasPermission = false;
672
    String publicAcc;
673 570 bojilova
674 688 bojilova
    String acfid = "";
675
    String acfid_prev = "";
676
    String principal;
677
    Vector principalArr = new Vector();
678
    int permission;
679
    int perm_prev = -1;
680
    String permType;
681
    String permOrder = "";
682
    String permOrder_prev = "";
683
    String beginTime = "";
684
    String begin_prev = "";
685
    String endTime = "";
686
    String end_prev = "";
687
    int ticketCount = -1;
688
    int ticket_prev = -1;
689 1214 tao
    DBConnection conn = null;
690
    int serialNumber = -1;
691
    PreparedStatement pstmt = null;
692 638 bojilova
    try {
693 688 bojilova
694 1214 tao
      //check out DBConnection
695
      conn=DBConnectionPool.getDBConnection("AccessControlList.getACL");
696
      serialNumber=conn.getCheckOutSerialNumber();
697
698 688 bojilova
      isOwned = isOwned(docid, user);
699 944 tao
      systemID = getSystemID((String)MetaCatUtil.
700
                                      getOptionList(accDoctype).elementAt(0));
701 688 bojilova
      publicAcc = getPublicAccess(docid);
702
703
      output.append("<?xml version=\"1.0\"?>\n");
704
      output.append("<!DOCTYPE acl PUBLIC \"" + accDoctype + "\" \"" +
705
                    systemID + "\">\n");
706
      output.append("<acl authSystem=\"\">\n");
707
708 1214 tao
709 688 bojilova
      pstmt = conn.prepareStatement(
710
              "SELECT distinct accessfileid, principal_name, permission, " +
711
              "perm_type, perm_order, to_char(begin_time,'mm/dd/yyyy'), " +
712
              "to_char(end_time,'mm/dd/yyyy'), ticket_count " +
713 765 bojilova
              "FROM xml_access WHERE docid = ? " +
714 688 bojilova
              "ORDER BY accessfileid, perm_order, perm_type, permission");
715
      // Bind the values to the query
716
      pstmt.setString(1, docid);
717
      pstmt.execute();
718
      ResultSet rs = pstmt.getResultSet();
719
      boolean hasRows = rs.next();
720
      while (hasRows) {
721
722
        acfid = rs.getString(1);
723
        principal = rs.getString(2);
724
        permission = rs.getInt(3);
725
        permType = rs.getString(4);
726
        permOrder = rs.getString(5);
727
        beginTime = rs.getString(6);
728
        endTime = rs.getString(7);
729
        ticketCount = rs.getInt(8);
730
731
        // if @docid is not owned by @user, only ACL info from that
732 802 bojilova
        // access files to which @user/@groups has "read" permission
733 688 bojilova
        // is extracted
734
        if ( !isOwned ) {
735
          if ( !acfid.equals(acfid_prev) ) {
736
            acfid_prev = acfid;
737 1426 tao
            //hasPermission = this.hasPermission("READ",user,groups,acfid);
738
             PermissionController controller = new PermissionController(acfid);
739
             hasPermission = controller.hasPermission(user,groups,
740
                                            AccessControlInterface.READSTRING);
741 688 bojilova
          }
742
          if ( !hasPermission ) {
743
            rs.next();
744
            continue;
745
          }
746
        }
747
748
        // open <resource> tag
749
        if ( !permOrder.equals(permOrder_prev) ) {
750
          // close </resource> tag if any was opened
751
          output.append(outTemp.toString());
752
          outTemp = new StringBuffer();
753
          if ( !permOrder_prev.equals("") ) {
754
            output.append("  </resource>\n");
755
          }
756
          output.append("  <resource order=\"" + permOrder + "\" public=\"" +
757
                        publicAcc + "\">\n");
758
          output.append("    <resourceIdentifier>" + docurl +
759
                        "</resourceIdentifier>\n");
760
          permOrder_prev = permOrder;
761
        }
762
763
        // close </allow> or </deny> tag then open new one
764
        if ( permission != perm_prev ||
765
             (endTime == null) && (end_prev != null) ||
766
             (beginTime == null) && (begin_prev != null) ||
767
             endTime != null && !endTime.equals(end_prev)  ||
768
             beginTime != null && !beginTime.equals(begin_prev) ||
769
             ticketCount != ticket_prev )  {
770
          output.append(outTemp.toString());
771
          outTemp = new StringBuffer();
772
          principalArr.removeAllElements();
773
          output.append("    <" + permType + ">\n");
774
        }
775
776
        // put all principals here for the same
777
        // permission, duration and ticket_count
778
        if ( !principalArr.contains(principal) ) {
779
          principalArr.addElement(principal);
780
          output.append("      <principal>" + principal + "</principal>\n");
781
        }
782
783
        // prepare <permission> tags, <duration> and <ticketCount>
784
        // if any to put within <allow> (<deny>) by next cicle
785
        if ( permission != perm_prev ||
786
             (endTime == null) && (end_prev != null) ||
787
             (beginTime == null) && (begin_prev != null) ||
788
             endTime != null && !endTime.equals(end_prev)  ||
789
             beginTime != null && !beginTime.equals(begin_prev) ||
790
             ticketCount != ticket_prev )  {
791
          if ( (permission & READ) != 0 ) {
792
            outTemp.append("      <permission>read</permission>\n");
793
          }
794
          if ( (permission & WRITE) != 0 ) {
795
            outTemp.append("      <permission>write</permission>\n");
796
          }
797
          if ( (permission & ALL) != 0 ) {
798
            outTemp.append("      <permission>all</permission>\n");
799
          }
800
          if ( (beginTime != null) || (endTime != null) ) {
801
            outTemp.append("      <duration>" + beginTime + " " + endTime +
802
                          "</duration>\n");
803
          }
804
          if ( ticketCount > 0 ) {
805
            outTemp.append("      <ticketCount>" + ticketCount +
806
                          "</ticketCount>\n");
807
          }
808
          outTemp.append("    </" + permType + ">\n");
809
          perm_prev = permission;
810
          ticket_prev = ticketCount;
811
          begin_prev = beginTime;
812
          end_prev = endTime;
813
        }
814
815
        hasRows = rs.next();
816 652 bojilova
      }
817 688 bojilova
818
      // close <allow> or <deny> if anything left in outTemp var
819
      output.append(outTemp.toString());
820
821
      // If there are no any acl info for @docid accessible by @user/@group,
822
      // extract only the following information
823
      if ( permOrder.equals("") ) {
824
        output.append("  <resource public=\"" + publicAcc + "\">\n");
825
        output.append("    <resourceIdentifier>" + docurl +
826
                      "</resourceIdentifier>\n");
827
      }
828
829
      // always close them
830
      output.append("  </resource>\n");
831
      output.append("</acl>\n");
832
833
      pstmt.close();
834
835
      return output.toString();
836
837
    } catch (SQLException e) {
838
      throw new
839
      SQLException("AccessControlList.getACL(). " + e.getMessage());
840 638 bojilova
    }
841 1214 tao
    finally
842
    {
843
      try
844
      {
845
        pstmt.close();
846
      }
847
      finally
848
      {
849
        DBConnectionPool.returnDBConnection(conn, serialNumber);
850
      }
851
    }
852 688 bojilova
  }
853
854
  /* Check if @user is owner of @docid from db conn. */
855
  private boolean isOwned(String docid, String user) throws SQLException {
856
857 1214 tao
    PreparedStatement pstmt = null;
858
    DBConnection conn = null;
859
    int serialNumber = -1;
860
    try
861
    {
862
      //check out DBConnection
863
      conn=DBConnectionPool.getDBConnection("AccessControlList.isOwned");
864
      serialNumber=conn.getCheckOutSerialNumber();
865
      pstmt = conn.prepareStatement("SELECT 'x' FROM xml_documents " +
866 765 bojilova
                                  "WHERE docid = ? " +
867
                                  "AND user_owner = ?");
868 1214 tao
      pstmt.setString(1, docid);
869
      pstmt.setString(2, user);
870
      pstmt.execute();
871
      ResultSet rs = pstmt.getResultSet();
872
      boolean hasRow = rs.next();
873
      return hasRow;
874
    }
875
    finally
876
    {
877
      try
878
      {
879
        pstmt.close();
880
      }
881
      finally
882
      {
883
        DBConnectionPool.returnDBConnection(conn, serialNumber);
884
      }
885
    }
886 688 bojilova
  }
887 652 bojilova
888 688 bojilova
  /* Get the flag for public "read" access for @docid from db conn. */
889
  private String getPublicAccess(String docid) throws SQLException {
890
891
    int publicAcc = 0;
892 1214 tao
    PreparedStatement pstmt = null;
893
    DBConnection conn = null;
894
    int serialNumber = -1;
895
    try
896
    {
897
      //check out DBConnection
898
      conn=DBConnectionPool.getDBConnection("AccessControlList.getPublicAcces");
899
      serialNumber=conn.getCheckOutSerialNumber();
900
      pstmt = conn.prepareStatement("SELECT public_access FROM xml_documents " +
901 765 bojilova
                                  "WHERE docid = ?");
902 1214 tao
      pstmt.setString(1, docid);
903
      pstmt.execute();
904
      ResultSet rs = pstmt.getResultSet();
905
      boolean hasRow = rs.next();
906
      if ( hasRow ) {
907
        publicAcc = rs.getInt(1);
908
      }
909
910
      return (publicAcc == 1) ? "yes" : "no";
911 1139 tao
    }
912 1214 tao
    finally
913
    {
914
      try
915
      {
916
        pstmt.close();
917
      }
918
      finally
919
      {
920
        DBConnectionPool.returnDBConnection(conn, serialNumber);
921
      }
922
    }
923 688 bojilova
  }
924
925
  /* Get SystemID for @publicID from Metacat DB Catalog. */
926
  private String getSystemID(String publicID) throws SQLException {
927
928
    String systemID = "";
929 1214 tao
    PreparedStatement pstmt = null;
930
    DBConnection conn = null;
931
    int serialNumber = -1;
932
933
    try
934
    {
935
      //check out DBConnection
936
      conn=DBConnectionPool.getDBConnection("AccessControlList.getSystemID");
937
      serialNumber=conn.getCheckOutSerialNumber();
938
939
      pstmt = conn.prepareStatement("SELECT system_id FROM xml_catalog " +
940 688 bojilova
                                  "WHERE entry_type = 'DTD' " +
941 765 bojilova
                                  "AND public_id = ?");
942 1214 tao
      pstmt.setString(1, publicID);
943
      pstmt.execute();
944
      ResultSet rs = pstmt.getResultSet();
945
      boolean hasRow = rs.next();
946
      if ( hasRow ) {
947
        systemID = rs.getString(1);
948
      }
949 688 bojilova
950 1214 tao
      return systemID;
951
    }//try
952
    finally
953
    {
954
955
      try
956
      {
957
        pstmt.close();
958
      }
959
      finally
960
      {
961
        DBConnectionPool.returnDBConnection(conn, serialNumber);
962
      }
963
    }//finally
964 688 bojilova
  }
965
966 555 bojilova
}