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
 *    Release: @release@
9
 *
10
 *   '$Author$'
11
 *     '$Date$'
12
 * '$Revision$'
13 669 jones
 *
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 555 bojilova
 */
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 652 bojilova
import java.util.Hashtable;
36
import java.net.URL;
37
import java.net.MalformedURLException;
38 555 bojilova
39
import org.xml.sax.Attributes;
40
import org.xml.sax.InputSource;
41 598 bojilova
import org.xml.sax.ContentHandler;
42
import org.xml.sax.EntityResolver;
43
import org.xml.sax.ErrorHandler;
44 555 bojilova
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
57
  static final int ALL = 1;
58
  static final int WRITE = 2;
59
  static final int READ = 4;
60
61 570 bojilova
  private Connection conn;
62 555 bojilova
  private String parserName;
63
  private Stack elementStack;
64 645 bojilova
  private String server;
65 555 bojilova
66 598 bojilova
  private boolean	processingDTD;
67 645 bojilova
  private String  user;
68
  private String  group;
69 638 bojilova
  private String  aclid;
70 598 bojilova
  private String 	docname;
71
  private String 	doctype;
72
  private String 	systemid;
73
74 665 bojilova
  private String docurl;
75
  private Vector resourceURL;
76
  private Vector resourceID;
77 660 bojilova
  private Vector principal;
78 570 bojilova
  private int    permission;
79
  private String permType;
80
  private String permOrder;
81 672 bojilova
  private String publicAcc;
82 570 bojilova
  private String beginTime;
83
  private String endTime;
84
  private int    ticketCount;
85 638 bojilova
86 555 bojilova
  /**
87
   * Construct an instance of the AccessControlList class.
88 570 bojilova
   * It is used by the permission check up from DBQuery and DocumentImpl
89
   *
90
   * @param conn the JDBC connection where acl data are loaded
91
   */
92 607 bojilova
  public AccessControlList ( Connection conn ) throws SQLException
93 570 bojilova
  {
94 613 bojilova
    this.conn = conn;
95 570 bojilova
  }
96
97
  /**
98
   * Construct an instance of the AccessControlList class.
99 555 bojilova
   * It parse acl file and loads acl data into db connection.
100
   *
101
   * @param conn the JDBC connection where acl data are loaded
102
   * @param docid the Accession# of the document with the acl data
103 570 bojilova
   * @param acl the acl file containing acl data
104 555 bojilova
   */
105 645 bojilova
  public AccessControlList(Connection conn, String aclid, Reader acl,
106
                           String user, String group)
107 555 bojilova
                  throws SAXException, IOException, ClassNotFoundException
108
  {
109
    // Get an instance of the parser
110
    MetaCatUtil util = new MetaCatUtil();
111
    String parserName = util.getOption("saxparser");
112 645 bojilova
    this.server = util.getOption("server");
113 555 bojilova
114
    this.conn = conn;
115
    this.parserName = parserName;
116 598 bojilova
    this.processingDTD = false;
117 570 bojilova
    this.elementStack = new Stack();
118
119 645 bojilova
    this.user = user;
120
    this.group = group;
121 638 bojilova
    this.aclid = aclid;
122 665 bojilova
    this.resourceURL = new Vector();
123
    this.resourceID = new Vector();
124 660 bojilova
    this.principal = new Vector();
125 570 bojilova
    this.permission = 0;
126
    this.ticketCount = 0;
127 638 bojilova
128 555 bojilova
    // Initialize the parser and read the queryspec
129
    XMLReader parser = initializeParser();
130
    parser.parse(new InputSource(acl));
131
132
  }
133
134 570 bojilova
  /**
135
   * Construct an instance of the AccessControlList class.
136
   * It parse acl file and loads acl data into db connection.
137
   *
138
   * @param conn the JDBC connection where acl data are loaded
139
   * @param docid the Accession# of the document with the acl data
140
   * @param aclfilename the name of acl file containing acl data
141
   */
142 645 bojilova
  public AccessControlList( Connection conn, String aclid, String aclfilename,
143
                           String user, String group )
144 555 bojilova
                  throws SAXException, IOException, ClassNotFoundException
145
  {
146 645 bojilova
    this(conn, aclid, new FileReader(new File(aclfilename).toString()),
147
         user, group);
148 555 bojilova
  }
149 638 bojilova
150 660 bojilova
  /* Set up the SAX parser for reading the XML serialized ACL */
151 555 bojilova
  private XMLReader initializeParser() throws SAXException
152
  {
153
    XMLReader parser = null;
154
155
    // Get an instance of the parser
156
    parser = XMLReaderFactory.createXMLReader(parserName);
157
158 598 bojilova
    // Turn off validation
159 638 bojilova
    parser.setFeature("http://xml.org/sax/features/validation", true);
160 598 bojilova
161
    // Set Handlers in the parser
162 555 bojilova
    // Set the ContentHandler to this instance
163 598 bojilova
    parser.setContentHandler((ContentHandler)this);
164 555 bojilova
165 598 bojilova
    // make a DBEntityResolver instance
166
    // Set the EntityReslover to DBEntityResolver instance
167
    EntityResolver eresolver = new DBEntityResolver(conn,this,null);
168
    parser.setEntityResolver((EntityResolver)eresolver);
169
170 555 bojilova
    // Set the ErrorHandler to this instance
171 598 bojilova
    parser.setErrorHandler((ErrorHandler)this);
172 555 bojilova
173
    return parser;
174
  }
175
176
  /**
177 645 bojilova
   * callback method used by the SAX Parser when beginning of the document
178
   */
179
  public void startDocument() throws SAXException
180
  {
181
    //delete all previously submitted permissions @ relations
182
    //this happens only on UPDATE of the access file
183
    try {
184
      if ( aclid != null ) {
185
        //first delete all permissions for resources related to @aclid if any
186
        deletePermissionsForRelatedResources(aclid);
187
        //then delete all relations with docid of @aclid if any
188
        deleteRelations(aclid);
189
      }
190
    } catch (SQLException sqle) {
191
      throw new SAXException(sqle);
192
    }
193
  }
194
195
  /**
196 555 bojilova
   * callback method used by the SAX Parser when the start tag of an
197
   * element is detected. Used in this context to parse and store
198
   * the acl information in class variables.
199
   */
200
  public void startElement (String uri, String localName,
201
                            String qName, Attributes atts)
202
         throws SAXException
203
  {
204
    BasicNode currentNode = new BasicNode(localName);
205
    if (atts != null) {
206
      int len = atts.getLength();
207
      for (int i = 0; i < len; i++) {
208
        currentNode.setAttribute(atts.getLocalName(i), atts.getValue(i));
209
      }
210
    }
211 570 bojilova
    if ( currentNode.getTagName().equals("resource") ) {
212
      permOrder = currentNode.getAttribute("order");
213 672 bojilova
      publicAcc = currentNode.getAttribute("public");
214 570 bojilova
    }
215 555 bojilova
    elementStack.push(currentNode);
216
  }
217
218
  /**
219
   * callback method used by the SAX Parser when the text sequences of an
220
   * xml stream are detected. Used in this context to parse and store
221
   * the acl information in class variables.
222
   */
223
  public void characters(char ch[], int start, int length)
224
         throws SAXException
225
  {
226
    String inputString = new String(ch, start, length);
227
    BasicNode currentNode = (BasicNode)elementStack.peek();
228
    String currentTag = currentNode.getTagName();
229
230 570 bojilova
    if (currentTag.equals("resourceIdentifier")) {
231 645 bojilova
232 665 bojilova
      // docid of the current resource
233
      String docid = getDocid(inputString);
234
      // URL string of the current resource
235
      // docurl is declared in the class
236
      try {
237
        docurl = (new URL(inputString)).toString();
238
      } catch (MalformedURLException murle) {
239
        throw new SAXException(murle.getMessage());
240
      }
241
      // collect them in Vector variables
242
      resourceID.addElement(docid);
243
      resourceURL.addElement(docurl);
244
      // check permissions for @user on the current resource first
245
      // @user must have permission "all" on it(docid)
246 645 bojilova
      boolean hasPermission = false;
247
      try {
248 665 bojilova
        hasPermission = hasPermission("ALL",user,docid);
249 645 bojilova
        if ( !hasPermission && group != null ) {
250 665 bojilova
          hasPermission = hasPermission("ALL",group,docid);
251 645 bojilova
        }
252
      } catch (SQLException e) {
253
        throw new SAXException(e.getMessage());
254 638 bojilova
      }
255 645 bojilova
      if ( !hasPermission ) {
256
        throw new SAXException(
257 665 bojilova
         "Permission denied for setting access control on " + docid);
258 645 bojilova
      }
259 665 bojilova
      // end of check for "all" perm on docid
260 645 bojilova
261 660 bojilova
    } else if (currentTag.equals("principal")) {
262 645 bojilova
263 665 bojilova
      principal.addElement(inputString);
264 645 bojilova
265 555 bojilova
    } else if (currentTag.equals("permission")) {
266 645 bojilova
267 555 bojilova
      if ( inputString.trim().toUpperCase().equals("READ") ) {
268
        permission = permission | READ;
269
      } else if ( inputString.trim().toUpperCase().equals("WRITE") ) {
270
        permission = permission | WRITE;
271
      } else if ( inputString.trim().toUpperCase().equals("ALL") ) {
272
        permission = permission | ALL;
273 665 bojilova
      } else {
274
        throw new SAXException("Unknown permission type: " + inputString);
275 555 bojilova
      }
276 645 bojilova
277 555 bojilova
    } else if (currentTag.equals("duration") &&
278 570 bojilova
               beginTime == null && endTime == null ) {
279 555 bojilova
      try {
280 570 bojilova
        beginTime = inputString.substring(0, inputString.indexOf(" "));
281
        endTime = inputString.substring(inputString.indexOf(" ")+1);
282 555 bojilova
      } catch (StringIndexOutOfBoundsException se) {
283 570 bojilova
        beginTime = inputString;
284 555 bojilova
      }
285 645 bojilova
286 570 bojilova
    } else if (currentTag.equals("ticketCount") && ticketCount == 0 ) {
287 665 bojilova
      try {
288
        ticketCount = (new Integer(inputString.trim())).intValue();
289
      } catch (NumberFormatException nfe) {
290
        throw new SAXException("Wrong integer format for:" + inputString);
291
      }
292 555 bojilova
    }
293
  }
294
295
  /**
296
   * callback method used by the SAX Parser when the end tag of an
297
   * element is detected. Used in this context to parse and store
298
   * the acl information in class variables.
299
   */
300
  public void endElement (String uri, String localName, String qName)
301
         throws SAXException
302
  {
303
    BasicNode leaving = (BasicNode)elementStack.pop();
304 638 bojilova
    if ( leaving.getTagName().equals("resourceIdentifier") ) {
305 570 bojilova
306 638 bojilova
      try {
307 665 bojilova
        // make a relationship for @aclid on the current resource(docurl)
308 638 bojilova
        if ( aclid != null ) {
309 665 bojilova
          insertRelation(aclid, docurl);
310 638 bojilova
        }
311
      } catch (SQLException sqle) {
312
        throw new SAXException(sqle);
313
      }
314
315
    } else if ( leaving.getTagName().equals("allow") ) {
316
317 570 bojilova
      if ( permission > 0 ) {
318 555 bojilova
319 570 bojilova
        // insert into db calculated permission for the list of principals
320
        try {
321
          insertPermissions("allowed");
322
        } catch (SQLException sqle) {
323
          throw new SAXException(sqle);
324
        }
325
      }
326
327 555 bojilova
      // reset the allowed permission
328 660 bojilova
      principal = new Vector();
329 555 bojilova
      permission = 0;
330 570 bojilova
      beginTime = null;
331
      endTime = null;
332
      ticketCount = 0;
333 555 bojilova
334 570 bojilova
    } else if ( leaving.getTagName().equals("deny") ) {
335
336
      if ( permission > 0 ) {
337 555 bojilova
338 570 bojilova
        // insert into db calculated permission for the list of principals
339
        try {
340
          insertPermissions("denied");
341
        } catch (SQLException sqle) {
342
          throw new SAXException(sqle);
343 555 bojilova
        }
344
      }
345
346 570 bojilova
      // reset the denied permission
347 660 bojilova
      principal = new Vector();
348 570 bojilova
      permission = 0;
349
      beginTime = null;
350
      endTime = null;
351
      ticketCount = 0;
352 555 bojilova
353 570 bojilova
    } else if ( leaving.getTagName().equals("resource") ) {
354 672 bojilova
355
      // update public access for the list of resources
356
      try {
357
        updatePublicAccess(publicAcc);
358
      } catch (SQLException sqle) {
359
        throw new SAXException(sqle);
360
      }
361
362
      // reset the resource
363 665 bojilova
      resourceID = new Vector();
364
      resourceURL = new Vector();
365 570 bojilova
      permOrder = null;
366 672 bojilova
      publicAcc = null;
367 570 bojilova
    }
368 555 bojilova
369
  }
370 598 bojilova
371
  /** SAX Handler that receives notification of DOCTYPE. Sets the DTD */
372
  public void startDTD(String name, String publicId, String systemId)
373
              throws SAXException {
374
    docname = name;
375
    doctype = publicId;
376
    systemid = systemId;
377
//    processingDTD = true;
378
  }
379
380
  /**
381
   * SAX Handler that receives notification of the start of entities
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
   */
392
  public void endEntity(String name) throws SAXException {
393
    if (name.equals("[dtd]")) {
394
      processingDTD = false;
395
    }
396
  }
397
398
  /**
399
   * get the document name
400
   */
401
  public String getDocname() {
402
    return docname;
403
  }
404
405
  /**
406
   * get the document processing state
407
   */
408
  public boolean processingDTD() {
409
    return processingDTD;
410
  }
411
412 645 bojilova
  /** Delete from db all permission for resources related to @aclid if any */
413
  private void deletePermissionsForRelatedResources(String aclid)
414 638 bojilova
          throws SQLException
415
  {
416 645 bojilova
    // delete all acl records for resources related to @aclid if any
417 638 bojilova
    Statement stmt = conn.createStatement();
418 645 bojilova
    stmt.execute("DELETE FROM xml_access WHERE accessfileid = '" + aclid + "'");
419 638 bojilova
    stmt.close();
420
  }
421
422 645 bojilova
  /**
423
   * Deletes all of the relations with a docid of @docid.
424
   * @param docid the docid to delete.
425
   */
426
  public void deleteRelations(String docid)
427 638 bojilova
          throws SQLException
428
  {
429 645 bojilova
    Statement stmt = conn.createStatement();
430
    stmt.execute("DELETE FROM xml_relation WHERE docid='" + docid + "'");
431
    stmt.close();
432
  }
433
434
  /** Insert relationship into db for @aclid on @resourceURL  */
435
  private void insertRelation(String aclid, String resourceURL)
436
          throws SQLException
437
  {
438
    String aclURL = "metacat://" + server + "/?docid=" + aclid;
439 638 bojilova
440
    // insert relationship
441
    PreparedStatement pstmt;
442
    pstmt = conn.prepareStatement(
443
            "INSERT INTO xml_relation (docid,subject,relationship,object) " +
444
            "VALUES (?, ?, ?, ?)");
445
    pstmt.setString(1, aclid);
446
    pstmt.setString(2, aclURL);
447
    pstmt.setString(3, "isaclfor");
448
    pstmt.setString(4, resourceURL);
449
450
    pstmt.execute();
451
    pstmt.close();
452
  }
453
454 570 bojilova
  /** Insert into db calculated permission for the list of principals */
455
  private void insertPermissions( String permType )
456 555 bojilova
          throws SQLException
457
  {
458 672 bojilova
    PreparedStatement pstmt;
459 638 bojilova
460 555 bojilova
    try {
461
      pstmt = conn.prepareStatement(
462
              "INSERT INTO xml_access " +
463 645 bojilova
              "(docid, principal_name, permission, perm_type, perm_order," +
464
              "begin_time,end_time,ticket_count, accessfileid) VALUES " +
465
              "(?,?,?,?,?,to_date(?,'mm/dd/yy'),to_date(?,'mm/dd/yy'),?,?)");
466 555 bojilova
      // Bind the values to the query
467 570 bojilova
      pstmt.setInt(3, permission);
468
      pstmt.setString(4, permType);
469
      pstmt.setString(5, permOrder);
470
      pstmt.setString(6, beginTime);
471
      pstmt.setString(7, endTime);
472 645 bojilova
      pstmt.setString(9, aclid);
473 570 bojilova
      if ( ticketCount > 0 ) {
474
        pstmt.setString(8, "" + ticketCount);
475
      } else {
476 555 bojilova
        pstmt.setString(8, "");
477 570 bojilova
      }
478 665 bojilova
      for ( int i = 0; i < resourceID.size(); i++ ) {
479
        pstmt.setString(1, (String)resourceID.elementAt(i));
480
        for ( int j = 0; j < principal.size(); j++ ) {
481
          pstmt.setString(2, (String)principal.elementAt(j));
482
          pstmt.execute();
483
        }
484 570 bojilova
      }
485 672 bojilova
      pstmt.close();
486 555 bojilova
487 570 bojilova
    } catch (SQLException e) {
488
      throw new
489
      SQLException("AccessControlList.insertPermissions(): " + e.getMessage());
490 672 bojilova
    }
491
  }
492
493
  /** Update into db public read access for the list of resources */
494
  private void updatePublicAccess(String publicAcc)
495
          throws SQLException
496
  {
497
    try {
498
      PreparedStatement pstmt;
499
      pstmt = conn.prepareStatement(
500
              "UPDATE xml_documents SET public_access = ?" +
501
              " WHERE docid LIKE ?");
502
      // Bind the values to the query
503
      if ( publicAcc.toUpperCase().equals("YES") ) {
504
        pstmt.setInt(1, 1);
505
      } else {
506
        pstmt.setInt(1, 0);
507
      }
508
      for ( int i = 0; i < resourceID.size(); i++ ) {
509
        pstmt.setString(2, (String)resourceID.elementAt(i));
510
        pstmt.execute();
511
      }
512 667 berkley
      pstmt.close();
513 672 bojilova
514
    } catch (SQLException e) {
515
      throw new
516
      SQLException("AccessControlList.updatePublicAccess(): " + e.getMessage());
517 570 bojilova
    }
518
  }
519
520 665 bojilova
  /** Check for @permission for @principal on @resourceID from db connection */
521 607 bojilova
  public boolean hasPermission ( String permission,
522 665 bojilova
                                 String principal, String resourceID )
523 570 bojilova
                 throws SQLException
524
  {
525
    PreparedStatement pstmt;
526 665 bojilova
    // check public access to @resourceID from xml_documents table
527 570 bojilova
    if ( permission.equals("READ") ) {
528
      try {
529 607 bojilova
        pstmt = conn.prepareStatement(
530 570 bojilova
                "SELECT 'x' FROM xml_documents " +
531
                "WHERE docid LIKE ? AND public_access = 1");
532
        // Bind the values to the query
533 665 bojilova
        pstmt.setString(1, resourceID);
534 570 bojilova
535 555 bojilova
        pstmt.execute();
536 570 bojilova
        ResultSet rs = pstmt.getResultSet();
537
        boolean hasRow = rs.next();
538
        pstmt.close();
539
        if (hasRow) {
540
          return true;
541
        }
542
//System.out.println("Passed the check for public access");
543
544
      } catch (SQLException e) {
545
        throw new
546
        SQLException("Error checking document's public access: "
547
                      + e.getMessage());
548 555 bojilova
      }
549 570 bojilova
    }
550
551
    // since owner of resource has all permission on it,
552 665 bojilova
    // check if @principal is owner of @resourceID in xml_documents table
553 570 bojilova
    if ( principal != null ) {
554
      try {
555 607 bojilova
        pstmt = conn.prepareStatement(
556 570 bojilova
                "SELECT 'x' FROM xml_documents " +
557
                "WHERE docid LIKE ? AND user_owner LIKE ?");
558
        // Bind the values to the query
559 665 bojilova
        pstmt.setString(1, resourceID);
560 570 bojilova
        pstmt.setString(2, principal);
561 555 bojilova
562 570 bojilova
        pstmt.execute();
563
        ResultSet rs = pstmt.getResultSet();
564
        boolean hasRow = rs.next();
565
        pstmt.close();
566
        if (hasRow) {
567
          return true;
568 555 bojilova
        }
569 570 bojilova
//System.out.println("Passed the check for ownership");
570
571
      } catch (SQLException e) {
572
        throw new
573
        SQLException("AccessControlList.hasPermission(): " +
574
                     "Error checking document's ownership. " + e.getMessage());
575
      }
576
577 665 bojilova
      // check @principal's @permission on @resourceID from xml_access table
578 570 bojilova
      int accessValue = 0;
579
      int ticketCount = 0;
580
      String permOrder = "";
581
      try {
582 607 bojilova
        pstmt = conn.prepareStatement(
583 570 bojilova
                "SELECT permission, perm_order, ticket_count " +
584
                "FROM xml_access " +
585
                "WHERE docid LIKE ? " +
586
                "AND principal_name LIKE ? " +
587
                "AND sysdate BETWEEN nvl(begin_time,sysdate) " +
588
                                "AND nvl(end_time,sysdate) " +
589
                "AND perm_type LIKE ?");
590
        // check if it is "denied" first
591
        // Bind the values to the query
592 665 bojilova
        pstmt.setString(1, resourceID);
593 570 bojilova
        pstmt.setString(2, principal);
594
        pstmt.setString(3, "denied");
595
596
        pstmt.execute();
597
        ResultSet rs = pstmt.getResultSet();
598
        boolean hasRows = rs.next();
599
        while ( hasRows ) {
600
          accessValue = rs.getInt(1);
601
          permOrder = rs.getString(2);
602
          ticketCount = rs.getInt(3);
603
          if ( ( accessValue & intValue(permission) ) == intValue(permission) &&
604 638 bojilova
               ( permOrder.equals("allowFirst") ) &&
605 570 bojilova
               ( rs.wasNull() || ticketCount > 0 ) ) {
606
            if ( !rs.wasNull() && ticketCount > 0 ) {
607 665 bojilova
              decreaseNumberOfAccess(accessValue,principal,resourceID,"denied");
608 570 bojilova
            }
609
            pstmt.close();
610
            return false;
611
          }
612
          hasRows = rs.next();
613 555 bojilova
        }
614 570 bojilova
//System.out.println("Passed the check for denied access");
615 555 bojilova
616 570 bojilova
        // it is not denied then check if it is "allowed"
617
        // Bind the values to the query
618 665 bojilova
        pstmt.setString(1, resourceID);
619 570 bojilova
        pstmt.setString(2, principal);
620
        pstmt.setString(3, "allowed");
621
622 555 bojilova
        pstmt.execute();
623 570 bojilova
        rs = pstmt.getResultSet();
624
        hasRows = rs.next();
625
        while ( hasRows ) {
626
          accessValue = rs.getInt(1);
627
          ticketCount = rs.getInt(3);
628
          if ( ( accessValue & intValue(permission) )==intValue(permission) &&
629
               ( rs.wasNull() || ticketCount > 0 ) ) {
630
            if ( !rs.wasNull() && ticketCount > 0 ) {
631 665 bojilova
              decreaseNumberOfAccess(accessValue,principal,resourceID,"allowed");
632 570 bojilova
            }
633
            pstmt.close();
634
            return true;
635
          }
636
          hasRows = rs.next();
637
        }
638
//System.out.println("Passed the check for allowed access");
639
640
        // ???
641
        // here there could be a check for the group's permission like
642
        // selfrecursive call to hasPermission(conn,permission,group,recourceId)
643
        //
644
645
        pstmt.close();
646
        return false;
647
648
      } catch (SQLException e) {
649
        throw new
650
        SQLException("AccessControlList.hasPermission(): " +
651
                     "Error checking document's permission. " + e.getMessage());
652 555 bojilova
      }
653 570 bojilova
    }
654
655
    return false;
656
  }
657 555 bojilova
658 665 bojilova
  /** decrease the number of access to @resourceID for @principal */
659 570 bojilova
  private void decreaseNumberOfAccess(int permission, String principal,
660 665 bojilova
                                      String resourceID, String permType)
661 570 bojilova
               throws SQLException
662
  {
663
    PreparedStatement pstmt;
664
    pstmt = conn.prepareStatement(
665
            "UPDATE xml_access SET ticket_count = ticket_count - 1 " +
666
            "WHERE docid LIKE ? " +
667
            "AND principal_name LIKE ? " +
668
            "AND permission LIKE ? " +
669
            "AND sysdate BETWEEN nvl(begin_time,sysdate) " +
670
                            "AND nvl(end_time,sysdate) " +
671
            "AND perm_type LIKE ?");
672
    // Bind the values to the query
673 665 bojilova
    pstmt.setString(1, resourceID);
674 570 bojilova
    pstmt.setString(2, principal);
675
    pstmt.setInt(3, permission);
676
    pstmt.setString(4, permType);
677
678
    pstmt.execute();
679
    pstmt.close();
680
  }
681
682
  // get the int value of READ, WRITE or ALL
683
  private int intValue ( String permission )
684
  {
685
    if ( permission.equals("READ") ) {
686
      return READ;
687
    } else if ( permission.equals("WRITE") ) {
688
      return WRITE;
689
    } else if ( permission.equals("ALL") ) {
690
      return ALL;
691 555 bojilova
    }
692 570 bojilova
693
    return -1;
694 555 bojilova
  }
695 638 bojilova
696 652 bojilova
  // get docid from @url
697
  private String getDocid ( String url ) throws SAXException
698 638 bojilova
  {
699 652 bojilova
    MetaCatUtil util = new MetaCatUtil();
700 638 bojilova
    try {
701 652 bojilova
      URL urlobj = new URL(url);
702
      Hashtable urlParams = util.parseQuery(urlobj.getQuery());
703
      if ( urlParams.containsKey("docid") ) {
704
        return (String)urlParams.get("docid"); // return the docid value
705
      } else {
706
        throw new
707
        SAXException("\"docid\" not specified within " + url);
708
      }
709
    } catch (MalformedURLException e) {
710 638 bojilova
      throw new SAXException(e.getMessage());
711
    }
712
  }
713 652 bojilova
714 555 bojilova
}