Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2010 Regents of the University of California and the
4
 *             National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: jones $'
7
 *     '$Date: 2010-02-03 17:58:12 -0900 (Wed, 03 Feb 2010) $'
8
 * '$Revision: 5211 $'
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, write to the Free Software
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 */
24

    
25
package edu.ucsb.nceas.metacat;
26

    
27
import java.sql.PreparedStatement;
28
import java.sql.ResultSet;
29
import java.sql.SQLException;
30
import java.sql.Timestamp;
31
import java.util.ArrayList;
32
import java.util.Date;
33
import java.util.Hashtable;
34
import java.util.List;
35
import java.util.Vector;
36

    
37
import org.apache.log4j.Logger;
38
import org.dataone.client.ObjectFormatCache;
39
import org.dataone.service.exceptions.NotFound;
40
import org.dataone.service.types.v1.AccessPolicy;
41
import org.dataone.service.types.v1.AccessRule;
42
import org.dataone.service.types.v1.Checksum;
43
import org.dataone.service.types.v1.ChecksumAlgorithm;
44
import org.dataone.service.types.v1.Identifier;
45
import org.dataone.service.types.v1.NodeReference;
46
import org.dataone.service.types.v1.ObjectFormat;
47
import org.dataone.service.types.v1.ObjectFormatIdentifier;
48
import org.dataone.service.types.v1.ObjectInfo;
49
import org.dataone.service.types.v1.ObjectList;
50
import org.dataone.service.types.v1.Permission;
51
import org.dataone.service.types.v1.Replica;
52
import org.dataone.service.types.v1.ReplicationPolicy;
53
import org.dataone.service.types.v1.ReplicationStatus;
54
import org.dataone.service.types.v1.Subject;
55
import org.dataone.service.types.v1.SystemMetadata;
56

    
57
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlInterface;
58
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
59
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
60
import edu.ucsb.nceas.metacat.database.DBConnection;
61
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
62
import edu.ucsb.nceas.metacat.properties.PropertyService;
63
import edu.ucsb.nceas.metacat.shared.AccessException;
64
import edu.ucsb.nceas.metacat.shared.ServiceException;
65
import edu.ucsb.nceas.metacat.util.DocumentUtil;
66
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
67

    
68
/**
69
 * Manage the relationship between Metacat local identifiers (LocalIDs) that are
70
 * codified as the (docid, rev) pair with globally unique string identifiers
71
 * (GUIDs) that are opaque strings.  This class provides methods to manage these
72
 * identifiers, and to search for and look up LocalIDs based on their GUID and
73
 * vice versa. IdentifierManager is a singleton.
74
 * 
75
 * @author Matthew Jones
76
 */
77
public class IdentifierManager {
78
    
79
    public static final String TYPE_SYSTEM_METADATA = "systemmetadata";
80
    public static final String TYPE_IDENTIFIER = "identifier";
81
  
82
    /**
83
     * The single instance of the manager that is always returned.
84
     */
85
    private static IdentifierManager self = null;
86
    private Logger logMetacat = Logger.getLogger(IdentifierManager.class);
87

    
88
    /**
89
     * A private constructor that initializes the class when getInstance() is
90
     * called.
91
     */
92
    private IdentifierManager() {}
93

    
94
    /**
95
     * Return the single instance of the manager after initializing it if it
96
     * wasn't previously initialized.
97
     * 
98
     * @return the single IdentifierManager instance
99
     */
100
    public static IdentifierManager getInstance()
101
    {
102
        if (self == null) {
103
            self = new IdentifierManager();
104
        }
105
        return self;
106
    }
107
    
108
    public SystemMetadata asSystemMetadata(Date dateUploaded, String rightsHolder,
109
            String checksum, String checksumAlgorithm, String originMemberNode,
110
            String authoritativeMemberNode, Date dateModified, String submitter, 
111
            String guid, String fmtidStr, long size) {
112
        SystemMetadata sysMeta = new SystemMetadata();
113

    
114
        Identifier sysMetaId = new Identifier();
115
        sysMetaId.setValue(guid);
116
        sysMeta.setIdentifier(sysMetaId);
117
        sysMeta.setDateUploaded(dateUploaded);
118
        Subject rightsHolderSubject = new Subject();
119
        rightsHolderSubject.setValue(rightsHolder);
120
        sysMeta.setRightsHolder(rightsHolderSubject);
121
        Checksum checksumObject = new Checksum();
122
        checksumObject.setValue(checksum);
123
        checksumObject.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
124
        sysMeta.setChecksum(checksumObject);
125
        NodeReference omn = new NodeReference();
126
        omn.setValue(originMemberNode);
127
        sysMeta.setOriginMemberNode(omn);
128
        NodeReference amn = new NodeReference();
129
        amn.setValue(authoritativeMemberNode);
130
        sysMeta.setAuthoritativeMemberNode(amn);
131
        sysMeta.setDateSysMetadataModified(dateModified);
132
        Subject submitterSubject = new Subject();
133
        submitterSubject.setValue(submitter);
134
        sysMeta.setSubmitter(submitterSubject);
135
        try {
136
	        sysMeta.setObjectFormat(ObjectFormatCache.getInstance().getFormat(fmtidStr));
137
        } catch (NotFound nfe) {
138
          logMetacat.error("The objectFormat " + fmtidStr +
139
          	" is not registered. Setting the default format.");
140
          ObjectFormat of = new ObjectFormat();
141
          ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
142
          fmtid.setValue("application/octet-stream");
143
          of.setFmtid(fmtid);
144
          of.setFormatName("Octet Stream");
145
          sysMeta.setObjectFormat(of);
146
        }
147
        sysMeta.setSize(size);
148
        
149
        return sysMeta;
150
    }
151
    
152
    /**
153
     * return a hash of all of the info that is in the systemmetadata table
154
     * @param localId
155
     * @return
156
     */
157
    public Hashtable<String, String> getSystemMetadataInfo(String localId)
158
    throws McdbDocNotFoundException
159
    {
160
        try
161
        {
162
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
163
            localId = acc.getDocid();
164
        }
165
        catch(Exception e)
166
        {
167
            //do nothing. just try the localId as it is
168
        }
169
        Hashtable<String, String> h = new Hashtable<String, String>();
170
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
171
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size " +
172
          "from systemmetadata where docid = ?";
173
        DBConnection dbConn = null;
174
        int serialNumber = -1;
175
        try 
176
        {
177
            // Get a database connection from the pool
178
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
179
            serialNumber = dbConn.getCheckOutSerialNumber();
180

    
181
            // Execute the insert statement
182
            PreparedStatement stmt = dbConn.prepareStatement(sql);
183
            stmt.setString(1, localId);
184
            ResultSet rs = stmt.executeQuery();
185
            if (rs.next()) 
186
            {
187
                String guid = rs.getString(1);
188
                Timestamp dateUploaded = rs.getTimestamp(2);
189
                String rightsHolder = rs.getString(3);
190
                String checksum = rs.getString(4);
191
                String checksumAlgorithm = rs.getString(5);
192
                String originMemberNode = rs.getString(6);
193
                String authoritativeMemberNode = rs.getString(7);
194
                Timestamp dateModified = rs.getTimestamp(8);
195
                String submitter = rs.getString(9);
196
                String objectFormat = rs.getString(10);
197
                long size = new Long(rs.getString(11)).longValue();
198
                
199
                h.put("guid", guid);
200
                h.put("date_uploaded", new Long(dateUploaded.getTime()).toString());
201
                h.put("rights_holder", rightsHolder);
202
                h.put("checksum", checksum);
203
                h.put("checksum_algorithm", checksumAlgorithm);
204
                h.put("origin_member_node", originMemberNode);
205
                h.put("authoritative_member_node", authoritativeMemberNode);
206
                h.put("date_modified", new Long(dateModified.getTime()).toString());
207
                h.put("submitter", submitter);
208
                h.put("object_format", objectFormat);
209
                h.put("size", new Long(size).toString());
210
                
211
                stmt.close();
212
            } 
213
            else
214
            {
215
                stmt.close();
216
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
217
                throw new McdbDocNotFoundException("2Could not find document " + localId);
218
            }
219
            
220
        } 
221
        catch (SQLException e) 
222
        {
223
            e.printStackTrace();
224
            logMetacat.error("Error while getting system metadata info for localid " + localId + " : "  
225
                    + e.getMessage());
226
        } 
227
        finally 
228
        {
229
            // Return database connection to the pool
230
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
231
        }
232
        return h;
233
    }
234
    
235
    /**
236
     * return a hash of all of the info that is in the systemmetadata table
237
     * @param guid
238
     * @return
239
     * @throws McdbDocNotFoundException 
240
     */
241
    public SystemMetadata getSystemMetadata(String guid)
242
    	throws McdbDocNotFoundException
243
    {
244
        
245
        SystemMetadata sysMeta = new SystemMetadata();
246
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
247
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size, " +
248
          "obsoletes, obsoleted_by " +
249
          "from systemmetadata where guid = ?";
250
        DBConnection dbConn = null;
251
        int serialNumber = -1;
252
        try 
253
        {
254
            // Get a database connection from the pool
255
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getSystemMetadata");
256
            serialNumber = dbConn.getCheckOutSerialNumber();
257

    
258
            // Execute the statement
259
            PreparedStatement stmt = dbConn.prepareStatement(sql);
260
            stmt.setString(1, guid);
261
            ResultSet rs = stmt.executeQuery();
262
            if (rs.next()) 
263
            {
264
                Timestamp dateUploaded = rs.getTimestamp(2);
265
                String rightsHolder = rs.getString(3);
266
                String checksum = rs.getString(4);
267
                String checksumAlgorithm = rs.getString(5);
268
                String originMemberNode = rs.getString(6);
269
                String authoritativeMemberNode = rs.getString(7);
270
                Timestamp dateModified = rs.getTimestamp(8);
271
                String submitter = rs.getString(9);
272
                String fmtidStr = rs.getString(10);
273
                long size = new Long(rs.getString(11)).longValue();
274
                String obsoletes = rs.getString(12);
275
                String obsoletedBy = rs.getString(13);
276

    
277
                
278
                Identifier sysMetaId = new Identifier();
279
                sysMetaId.setValue(guid);
280
                sysMeta.setIdentifier(sysMetaId);
281
                sysMeta.setDateUploaded(dateUploaded);
282
                Subject rightsHolderSubject = new Subject();
283
                rightsHolderSubject.setValue(rightsHolder);
284
                sysMeta.setRightsHolder(rightsHolderSubject);
285
                Checksum checksumObject = new Checksum();
286
                checksumObject.setValue(checksum);
287
                checksumObject.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
288
                sysMeta.setChecksum(checksumObject);
289
                NodeReference omn = new NodeReference();
290
                omn.setValue(originMemberNode);
291
                sysMeta.setOriginMemberNode(omn);
292
                NodeReference amn = new NodeReference();
293
                amn.setValue(authoritativeMemberNode);
294
                sysMeta.setAuthoritativeMemberNode(amn);
295
                sysMeta.setDateSysMetadataModified(dateModified);
296
                Subject submitterSubject = new Subject();
297
                submitterSubject.setValue(submitter);
298
                sysMeta.setSubmitter(submitterSubject);
299
                try {
300
        	        sysMeta.setObjectFormat(ObjectFormatCache.getInstance().getFormat(fmtidStr));
301
                } catch (NotFound nfe) {
302
                  logMetacat.error("The objectFormat " + fmtidStr +
303
                  	" is not registered. Setting the default format.");
304
                  ObjectFormat of = new ObjectFormat();
305
                  ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
306
                  fmtid.setValue("application/octet-stream");
307
                  of.setFmtid(fmtid);
308
                  of.setFormatName("Octet Stream");
309
                  sysMeta.setObjectFormat(of);
310
                }
311
                sysMeta.setSize(size);
312
                Identifier obsoletesId = new Identifier();
313
                obsoletesId.setValue(obsoletes);
314
                sysMeta.setObsoletes(obsoletesId);
315
                Identifier obsoletedById = new Identifier();
316
                obsoletedById.setValue(obsoletedBy);
317
                sysMeta.setObsoletedBy(obsoletedById);
318
                
319
                stmt.close();
320
            } 
321
            else
322
            {
323
                stmt.close();
324
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
325
                throw new McdbDocNotFoundException("Could not find " + guid);
326
            }
327
            
328
        } 
329
        catch (SQLException e) 
330
        {
331
            e.printStackTrace();
332
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "  
333
                    + e.getMessage());
334
        } 
335
        finally 
336
        {
337
            // Return database connection to the pool
338
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
339
        }
340

    
341
        // look up replication policy
342
        ReplicationPolicy replicationPolicy = new ReplicationPolicy();
343
        replicationPolicy.setBlockedMemberNodeList(getReplicationPolicy(guid, "blocked"));
344
        replicationPolicy.setPreferredMemberNodeList(getReplicationPolicy(guid, "preferred"));
345
		sysMeta.setReplicationPolicy(replicationPolicy);
346
		
347
		// look up replication status
348
		sysMeta.setReplicaList(getReplicationStatus(guid));
349
		
350
		// look up access policy
351
		try {
352
			sysMeta.setAccessPolicy(getAccessPolicy(guid));
353
		} catch (AccessException e) {
354
			throw new McdbDocNotFoundException(e);
355
		}
356
        
357
        return sysMeta;
358
    }
359
    
360
    
361
    private List<NodeReference> getReplicationPolicy(String guid, String policy)
362
		throws McdbDocNotFoundException {
363
		
364
		List<NodeReference> nodes = new ArrayList<NodeReference>();
365
		String sql = "select guid, policy, member_node " +
366
			"from systemMetadataReplicationPolicy where guid = ? and policy = ?";
367
	    DBConnection dbConn = null;
368
	    int serialNumber = -1;
369
	    try {
370
	        // Get a database connection from the pool
371
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicationPolicy");
372
	        serialNumber = dbConn.getCheckOutSerialNumber();
373
	
374
	        // Execute the statement
375
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
376
	        stmt.setString(1, guid);
377
	        stmt.setString(2, policy);
378
	        ResultSet rs = stmt.executeQuery();
379
	        while (rs.next()) 
380
	        {
381
	            String memberNode = rs.getString(3);
382
	            NodeReference node = new NodeReference();
383
	            node.setValue(memberNode);
384
	            nodes.add(node);
385
	        
386
	        } 
387
	        stmt.close();
388
	        
389
	    } catch (SQLException e) {
390
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
391
	    } 
392
	    finally {
393
	        // Return database connection to the pool
394
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
395
	    }
396
	    
397
	    return nodes;
398
	}
399
    
400
    private List<Replica> getReplicationStatus(String guid) throws McdbDocNotFoundException {
401
		
402
		List<Replica> replicas = new ArrayList<Replica>();
403
		String sql = "select guid, member_node, status, date_verified " +
404
			"from systemMetadataReplicationStatus where guid = ?";
405
	    DBConnection dbConn = null;
406
	    int serialNumber = -1;
407
	    try {
408
	        // Get a database connection from the pool
409
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicas");
410
	        serialNumber = dbConn.getCheckOutSerialNumber();
411
	
412
	        // Execute the statement
413
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
414
	        stmt.setString(1, guid);
415
	        ResultSet rs = stmt.executeQuery();
416
	        while (rs.next()) 
417
	        {
418
	            String memberNode = rs.getString(2);
419
	            String status = rs.getString(3);
420
	            java.sql.Date verified = rs.getDate(4);
421
	            
422
	            Replica replica = new Replica();	            
423
	            NodeReference node = new NodeReference();
424
	            node.setValue(memberNode);
425
	            replica.setReplicaMemberNode(node);
426
	            replica.setReplicationStatus(ReplicationStatus.convert(status));
427
	            replica.setReplicaVerified(new Date(verified.getTime()));
428
	            replicas.add(replica);
429
	        } 
430
	        stmt.close();
431
	        
432
	    } catch (SQLException e) {
433
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
434
	    } 
435
	    finally {
436
	        // Return database connection to the pool
437
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
438
	    }
439
	    
440
	    return replicas;
441
	}
442
    
443
    /**
444
     * return information on the document with localId.  These are the fields
445
     * from the xml_documents table.  They can be used to contstruct metadata 
446
     * about the object that is stored.
447
     * @param localId
448
     * @return
449
     * @throws McdbDocNotFoundException
450
     */
451
    public Hashtable<String, Object> getDocumentInfo(String localId)
452
        throws McdbDocNotFoundException
453
    {
454
        try
455
        {
456
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
457
            localId = acc.getDocid();
458
        }
459
        catch(Exception e)
460
        {
461
            //do nothing. just try the localId as it is
462
        }
463
        Hashtable<String, Object> h = new Hashtable<String, Object>();
464
        String sql = "select docname, doctype, user_owner, user_updated, " +
465
            "server_location, rev, date_created, date_updated from " + 
466
            "xml_documents where docid like '" + localId + "'";
467
        DBConnection dbConn = null;
468
        int serialNumber = -1;
469
        try 
470
        {
471
            // Get a database connection from the pool
472
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
473
            serialNumber = dbConn.getCheckOutSerialNumber();
474

    
475
            // Execute the insert statement
476
            PreparedStatement stmt = dbConn.prepareStatement(sql);
477
            ResultSet rs = stmt.executeQuery();
478
            if (rs.next()) 
479
            {
480
                String docname = rs.getString(1);
481
                String doctype = rs.getString(2);
482
                String user_owner = rs.getString(3);
483
                String user_updated = rs.getString(4);
484
                String server_location = rs.getString(5);
485
                int rev = rs.getInt(6);
486
                String date_created = rs.getString(7);
487
                String date_updated = rs.getString(8);
488
                h.put("docid", localId);
489
                h.put("docname", docname);
490
                h.put("doctype", doctype);
491
                h.put("user_owner", user_owner);
492
                h.put("user_updated", user_updated);
493
                h.put("server_location", server_location);
494
                h.put("rev", new Integer(rev).toString());
495
                h.put("date_created", date_created);
496
                h.put("date_updated", date_updated);
497
                
498
                stmt.close();
499
            } 
500
            else
501
            {
502
                stmt.close();
503
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
504
                throw new McdbDocNotFoundException("2Could not find document " + localId);
505
            }
506
            
507
            String sql2 = "select principal_name, permission, perm_type, perm_order from xml_access " +
508
            "where docid like '" + localId + "'";
509
            logMetacat.debug("executing sql: " + sql2);
510
            PreparedStatement stmt2 = dbConn.prepareStatement(sql2);
511
            rs = stmt2.executeQuery();
512
            Vector accessVector = new Vector();
513
            while(rs.next())
514
            {
515
                Hashtable accessHash = new Hashtable();
516
                String principal_name = rs.getString(1);
517
                String permission = rs.getString(2);
518
                String permissionType = rs.getString(3);
519
                String permissionOrder = rs.getString(4);
520
                accessHash.put("principal_name", principal_name);
521
                accessHash.put("permission", permission);
522
                accessHash.put("permission_type", permissionType);
523
                accessHash.put("permission_order", permissionOrder);
524
                logMetacat.debug("accessHash: " + accessHash.toString());
525
                accessVector.add(accessHash);
526
            }
527
            h.put("access", accessVector);
528
        } 
529
        catch (SQLException e) 
530
        {
531
            e.printStackTrace();
532
            logMetacat.error("Error while getting document info for localid " + localId + " : "  
533
                    + e.getMessage());
534
        } 
535
        finally 
536
        {
537
            // Return database connection to the pool
538
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
539
        }
540
        return h;
541
    }
542
    
543
    /**
544
     * return the newest rev for a given localId
545
     * @param localId
546
     * @return
547
     */
548
    public int getLatestRevForLocalId(String localId)
549
        throws McdbDocNotFoundException
550
    {
551
        try
552
        {
553
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
554
            localId = acc.getDocid();
555
        }
556
        catch(Exception e)
557
        {
558
            //do nothing. just try the localId as it is
559
        }
560
        int rev = 0;
561
        String sql = "select rev from xml_documents where docid like '" + localId + "'";
562
        DBConnection dbConn = null;
563
        int serialNumber = -1;
564
        try 
565
        {
566
            // Get a database connection from the pool
567
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLatestRevForLocalId");
568
            serialNumber = dbConn.getCheckOutSerialNumber();
569

    
570
            // Execute the insert statement
571
            PreparedStatement stmt = dbConn.prepareStatement(sql);
572
            ResultSet rs = stmt.executeQuery();
573
            if (rs.next()) 
574
            {
575
                rev = rs.getInt(1);
576
                stmt.close();
577
            } 
578
            else
579
            {
580
                stmt.close();
581
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
582
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
583
            }
584
        } 
585
        catch (SQLException e) 
586
        {
587
            logMetacat.error("Error while looking up the guid: " 
588
                    + e.getMessage());
589
        } 
590
        finally 
591
        {
592
            // Return database connection to the pool
593
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
594
        }
595
        return rev;
596
    }
597
    
598
    /**
599
     * return all local ids in the object store that do not have associated
600
     * system metadata
601
     */
602
    public List<String> getLocalIdsWithNoSystemMetadata()
603
    {
604
        Vector<String> ids = new Vector<String>();
605
        String sql = "select docid, rev from xml_documents " +
606
        		"where docid not in " +
607
        		"(select docid from identifier where guid in (select guid from systemmetadata)))";
608
        DBConnection dbConn = null;
609
        int serialNumber = -1;
610
        try 
611
        {
612
            // Get a database connection from the pool
613
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
614
            serialNumber = dbConn.getCheckOutSerialNumber();
615

    
616
            // Execute the insert statement
617
            PreparedStatement stmt = dbConn.prepareStatement(sql);
618
            ResultSet rs = stmt.executeQuery();
619
            while (rs.next()) 
620
            {
621
                String localid = rs.getString(1);
622
                String rev = rs.getString(2);
623
                localid += "." + rev;
624
                logMetacat.debug("id to add SM for: " + localid);
625
                ids.add(localid);
626
            } 
627
            stmt.close();
628
        } 
629
        catch (SQLException e) 
630
        {
631
            logMetacat.error("Error while looking up the guid: " 
632
                    + e.getMessage());
633
        } 
634
        finally 
635
        {
636
            // Return database connection to the pool
637
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
638
        }
639
        
640
        return ids;
641
    }
642
    
643
    /**
644
     * return a listing of all local ids in the object store
645
     * @return a list of all local ids in metacat
646
     */
647
    public List<String> getAllLocalIds()
648
       throws Exception
649
    {
650
        Vector<String> ids = new Vector<String>();
651
        String sql = "select docid from xml_documents";
652
        DBConnection dbConn = null;
653
        int serialNumber = -1;
654
        try 
655
        {
656
            // Get a database connection from the pool
657
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
658
            serialNumber = dbConn.getCheckOutSerialNumber();
659

    
660
            // Execute the insert statement
661
            PreparedStatement stmt = dbConn.prepareStatement(sql);
662
            ResultSet rs = stmt.executeQuery();
663
            while (rs.next()) 
664
            {
665
                String localid = rs.getString(1);
666
                ids.add(localid);
667
            } 
668
            stmt.close();
669
        } 
670
        catch (SQLException e) 
671
        {
672
            logMetacat.error("Error while looking up the guid: " 
673
                    + e.getMessage());
674
        } 
675
        finally 
676
        {
677
            // Return database connection to the pool
678
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
679
        }
680
        return ids;
681
    }
682
    
683
    /**
684
     * returns a list of system metadata-only guids since the given date
685
     * @return a list of system ids in metacat that do not correspond to objects
686
     * TODO: need to check which server they are on
687
     */
688
    public List<String> getUpdatedSystemMetadataIds(Date since)
689
       throws Exception
690
    {
691
        List<String> ids = new Vector<String>();
692
        String sql = 
693
        	"select guid from " + TYPE_SYSTEM_METADATA +
694
        	" where guid not in " +
695
        	" (select guid from " + TYPE_IDENTIFIER + ") " +
696
        	" and date_modified > ?";
697
        DBConnection dbConn = null;
698
        int serialNumber = -1;
699
        try 
700
        {
701
            // Get a database connection from the pool
702
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getUpdatedSystemMetadataIds");
703
            serialNumber = dbConn.getCheckOutSerialNumber();
704

    
705
            // Execute the insert statement
706
            PreparedStatement stmt = dbConn.prepareStatement(sql);
707
            stmt.setDate(1, new java.sql.Date(since.getTime()));
708
            ResultSet rs = stmt.executeQuery();
709
            while (rs.next()) 
710
            {
711
                String guid = rs.getString(1);
712
                ids.add(guid);
713
            } 
714
            stmt.close();
715
        } 
716
        catch (SQLException e) 
717
        {
718
            logMetacat.error("Error while looking up the updated guids: " 
719
                    + e.getMessage());
720
        } 
721
        finally 
722
        {
723
            // Return database connection to the pool
724
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
725
        }
726
        return ids;
727
    }
728
    
729

    
730
    
731
    /**
732
     * Determine if an identifier exists already, returning true if so.
733
     * 
734
     * @param guid the global identifier to look up
735
     * @return boolean true if the identifier exists
736
     */
737
    public boolean identifierExists(String guid)
738
    {
739
        boolean idExists = false;
740
        try {
741
            String id = getLocalId(guid);
742
            if (id != null) {
743
                idExists = true;
744
            }
745
        } catch (McdbDocNotFoundException e) {
746
        	// try system metadata only
747
        	try {
748
        		idExists = systemMetadataExisits(guid);
749
            } catch (McdbDocNotFoundException e2) {
750
            	idExists = false;
751
            }
752
        }
753
        return idExists;
754
    }
755
    
756
    /**
757
     * 
758
     * @param guid
759
     * @param rev
760
     * @return
761
     */
762
    public String generateLocalId(String guid, int rev)
763
    {
764
        return generateLocalId(guid, rev, false);
765
    }
766

    
767
    /**
768
     * Given a global identifier (guid), create a suitable local identifier that
769
     * follows Metacat's docid semantics and format (scope.id.rev), and create
770
     * a mapping between these two identifiers.  This effectively reserves both
771
     * the global and the local identifier, as they will now be present in the
772
     * identifier mapping table.  If the incoming guid has the syntax of a
773
     * Metacat docid (scope.id.rev), then simply use it.
774
     * 
775
     * @param guid the global string identifier
776
     * @param rev the revision number to be used in the localId
777
     * @return String containing the localId to be used for Metacat operations
778
     */
779
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata) 
780
    {
781
        String localId = "";
782
        boolean conformsToDocidFormat = false;
783
        
784
        // Check if the guid passed in is already in docid (scope.id.rev) format
785
        try {
786
            AccessionNumber acc = new AccessionNumber(guid, "NONE");
787
            if (new Integer(acc.getRev()).intValue() > 0) {
788
                conformsToDocidFormat = true;
789
            }
790
        } catch (NumberFormatException e) {
791
            // No action needed, simply detecting invalid AccessionNumbers
792
        } catch (AccessionNumberException e) {
793
            // No action needed, simply detecting invalid AccessionNumbers
794
        } catch (SQLException e) {
795
            // No action needed, simply detecting invalid AccessionNumbers
796
        }
797
        
798
        if (conformsToDocidFormat) {
799
            // if it conforms, use it for both guid and localId
800
            localId = guid;
801
        } else {
802
            // if not, then generate a new unique localId
803
            localId = DocumentUtil.generateDocumentId(rev);
804
        }
805
        
806
        // Register this new pair in the identifier mapping table
807
        logMetacat.debug("creating mapping in generateLocalId");
808
        if(!isSystemMetadata)
809
        { //don't do this if we're generating for system metadata
810
            createMapping(guid, localId);
811
        }
812
        
813
        return localId;
814
    }
815
    
816
    /**
817
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
818
     * if the docid, rev is not found in the identifiers or systemmetadata tables
819
     *
820
     * @param docid the docid to look up
821
     * @param rev the revision of the docid to look up
822
     * @return String containing the mapped guid
823
     * @throws McdbDocNotFoundException if the docid, rev is not found
824
     */
825
    public String getGUID(String docid, int rev)
826
      throws McdbDocNotFoundException
827
    {
828
        logMetacat.debug("getting guid for " + docid);
829
        String query = "select guid from identifier where docid = ? and rev = ?";
830
        String guid = null;
831
        
832
        DBConnection dbConn = null;
833
        int serialNumber = -1;
834
        try {
835
            // Get a database connection from the pool
836
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
837
            serialNumber = dbConn.getCheckOutSerialNumber();
838
            
839
            // Execute the insert statement
840
            PreparedStatement stmt = dbConn.prepareStatement(query);
841
            stmt.setString(1, docid);
842
            stmt.setInt(2, rev);
843
            ResultSet rs = stmt.executeQuery();
844
            if (rs.next()) 
845
            {
846
                guid = rs.getString(1);
847
            } 
848
            else
849
            {
850
            	throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
851
            }
852
            
853
        } catch (SQLException e) {
854
            logMetacat.error("Error while looking up the guid: " 
855
                    + e.getMessage());
856
        } finally {
857
            // Return database connection to the pool
858
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
859
        }
860
        
861
        return guid;
862
    }
863
    
864
    public boolean systemMetadataExisits(String guid)
865
			throws McdbDocNotFoundException {
866
		logMetacat.debug("looking up system metadata for guid " + guid);
867
		boolean exists = false;
868
		String query = "select guid from systemmetadata where guid = ?";
869

    
870
		DBConnection dbConn = null;
871
		int serialNumber = -1;
872
		try {
873
			// Get a database connection from the pool
874
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
875
			serialNumber = dbConn.getCheckOutSerialNumber();
876

    
877
			// Execute the insert statement
878
			PreparedStatement stmt = dbConn.prepareStatement(query);
879
			stmt.setString(1, guid);
880
			ResultSet rs = stmt.executeQuery();
881
			if (rs.next()) {
882
				exists = true;
883
			} else {
884
				throw new McdbDocNotFoundException(
885
						"No system metadata registered for guid " + guid);
886
			}
887

    
888
		} catch (SQLException e) {
889
			logMetacat.error("Error while looking up the system metadata: "
890
					+ e.getMessage());
891
		} finally {
892
			// Return database connection to the pool
893
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
894
		}
895

    
896
		return exists;
897
	}
898
    
899
    /**
900
     * creates a system metadata mapping and adds additional fields from sysmeta
901
     * to the table for quick searching.
902
     * 
903
     * @param guid the id to insert
904
     * @param localId the systemMetadata object to get the local id for
905
     * @throws McdbDocNotFoundException 
906
     */
907
    public void createSystemMetadata(SystemMetadata sysmeta) throws McdbDocNotFoundException
908
    {
909
    	String guid = sysmeta.getIdentifier().getValue();
910
    	// insert the record
911
        insertSystemMetadata(guid);
912
        // update with the values
913
        updateSystemMetadata(sysmeta);
914
    }
915
        
916
    
917
    /**
918
     * update a mapping
919
     * @param guid
920
     * @param localId
921
     */
922
    public void updateMapping(String guid, String localId)
923
    {
924
    	
925
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
926
        int serialNumber = -1;
927
        DBConnection dbConn = null;
928
        try {
929
            // Parse the localId into scope and rev parts
930
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
931
            String docid = acc.getDocid();
932
            int rev = 1;
933
            if(acc.getRev() != null)
934
            {
935
              rev = (new Integer(acc.getRev()).intValue());
936
            }
937

    
938
            // Get a database connection from the pool
939
            dbConn = 
940
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
941
            serialNumber = dbConn.getCheckOutSerialNumber();
942

    
943
            // Execute the update statement
944
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid='" + guid + "'";
945
            PreparedStatement stmt = dbConn.prepareStatement(query);
946
            stmt.setString(1, docid);
947
            stmt.setInt(2, rev);
948
            int rows = stmt.executeUpdate();
949

    
950
            stmt.close();
951
        } catch (SQLException e) {
952
            e.printStackTrace();
953
            logMetacat.error("SQL error while updating a mapping identifier: " 
954
                    + e.getMessage());
955
        } catch (NumberFormatException e) {
956
            e.printStackTrace();
957
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
958
                    + e.getMessage());
959
        } catch (AccessionNumberException e) {
960
            e.printStackTrace();
961
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
962
                    + e.getMessage());
963
        } finally {
964
            // Return database connection to the pool
965
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
966
        }
967
        logMetacat.debug("done updating mapping");
968
    }
969
        
970
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
971
            String checksum, String checksumAlgorithm, String originMemberNode,
972
            String authoritativeMemberNode, long modifiedDate, String submitter, 
973
            String guid, String objectFormat, long size, boolean replicationAllowed,
974
            int numberReplicas, String obsoletes, String obsoletedBy)
975
    {
976
        DBConnection dbConn = null;
977
        int serialNumber = -1;
978
        
979
        try {
980
            // Get a database connection from the pool
981
            dbConn = 
982
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
983
            serialNumber = dbConn.getCheckOutSerialNumber();
984

    
985
            // Execute the insert statement
986
            String query = "update " + TYPE_SYSTEM_METADATA + 
987
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
988
                "origin_member_node, authoritive_member_node, date_modified, " +
989
                "submitter, object_format, size, replication_allowed, number_replicas, obsoletes, obsoleted_by) " +
990
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
991
            PreparedStatement stmt = dbConn.prepareStatement(query);
992
            
993
            //data values
994
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
995
            stmt.setString(2, rightsHolder);
996
            stmt.setString(3, checksum);
997
            stmt.setString(4, checksumAlgorithm);
998
            stmt.setString(5, originMemberNode);
999
            stmt.setString(6, authoritativeMemberNode);
1000
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1001
            stmt.setString(8, submitter);
1002
            stmt.setString(9, objectFormat);
1003
            stmt.setString(10, new Long(size).toString());
1004
            stmt.setBoolean(11, replicationAllowed);
1005
            stmt.setInt(12, numberReplicas);
1006
            stmt.setString(13, obsoletes);
1007
            stmt.setString(14, obsoletedBy);
1008

    
1009
            //where clause
1010
            stmt.setString(15, guid);
1011
            logMetacat.debug("stmt: " + stmt.toString());
1012
            //execute
1013
            int rows = stmt.executeUpdate();
1014

    
1015
            stmt.close();
1016
        } catch (SQLException e) {
1017
            e.printStackTrace();
1018
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: " 
1019
                    + e.getMessage());
1020
        } catch (NumberFormatException e) {
1021
            e.printStackTrace();
1022
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: " 
1023
                    + e.getMessage());
1024
        } finally {
1025
            // Return database connection to the pool
1026
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1027
        }
1028
    }
1029
    
1030
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes)
1031
    {
1032
        DBConnection dbConn = null;
1033
        int serialNumber = -1;
1034
        
1035
        try {
1036
            // Get a database connection from the pool
1037
            dbConn = 
1038
                DBConnectionPool.getDBConnection("IdentifierManager.insertReplicationPolicy");
1039
            serialNumber = dbConn.getCheckOutSerialNumber();
1040

    
1041
            // remove existing values first
1042
            String delete = "delete from systemMetadataReplicationPolicy " + 
1043
            "where guid = ? and policy = ?";
1044
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1045
	        //data values
1046
	        stmt.setString(1, guid);
1047
	        stmt.setString(2, policy);
1048
	        //execute
1049
	        int deletedCount = stmt.executeUpdate();
1050
	        stmt.close();
1051
            
1052
            for (String memberNode: memberNodes) {
1053
	            // Execute the insert statement
1054
	            String insert = "insert into systemMetadataReplicationPolicy " + 
1055
	                "(guid, policy, member_node) " +
1056
	                "values (?, ?, ?)";
1057
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1058
	            
1059
	            //data values
1060
	            insertStatement.setString(1, guid);
1061
	            insertStatement.setString(2, policy);
1062
	            insertStatement.setString(3, memberNode);
1063
	            //execute
1064
	            int rows = insertStatement.executeUpdate();
1065
	            insertStatement.close();
1066
            }
1067
        } catch (SQLException e) {
1068
            logMetacat.error("SQL error while adding systemMetadataReplicationPolicy for: " + guid, e); 
1069
        } finally {
1070
            // Return database connection to the pool
1071
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1072
        }
1073
    }
1074
    
1075
    private void insertReplicationStatus(String guid, List<Replica> replicas) {
1076
        DBConnection dbConn = null;
1077
        int serialNumber = -1;
1078
        
1079
        try {
1080
            // Get a database connection from the pool
1081
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertReplicas");
1082
            serialNumber = dbConn.getCheckOutSerialNumber();
1083

    
1084
            // remove existing values first
1085
            String delete = "delete from systemMetadataReplicationStatus " + 
1086
            "where guid = ?";
1087
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1088
	        //data values
1089
	        stmt.setString(1, guid);
1090
	        //execute
1091
	        int deletedCount = stmt.executeUpdate();
1092
	        stmt.close();
1093
            
1094
            for (Replica replica: replicas) {
1095
	            // Execute the insert statement
1096
	            String insert = "insert into systemMetadataReplicationStatus " + 
1097
	                "(guid, member_node, status, date_verified) " +
1098
	                "values (?, ?, ?, ?)";
1099
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1100
	            
1101
	            //data values
1102
	            String memberNode = replica.getReplicaMemberNode().getValue();
1103
	            String status = replica.getReplicationStatus().toString();
1104
	            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1105
	            insertStatement.setString(1, guid);
1106
	            insertStatement.setString(2, memberNode);
1107
	            insertStatement.setString(3, status);
1108
	            insertStatement.setDate(4, sqlDate);
1109

    
1110
	            //execute
1111
	            int rows = insertStatement.executeUpdate();
1112
	            insertStatement.close();
1113
            }
1114
        } catch (SQLException e) {
1115
            logMetacat.error("SQL error while adding systemMetadataReplicationStatus for: " + guid, e); 
1116
        } finally {
1117
            // Return database connection to the pool
1118
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1119
        }
1120
    }
1121
    
1122
    /**
1123
     * Insert the system metadata fields into the db
1124
     * @param sm
1125
     * @throws McdbDocNotFoundException 
1126
     */
1127
    public void updateSystemMetadata(SystemMetadata sm) throws McdbDocNotFoundException {
1128
    	
1129
        Boolean replicationAllowed = false;
1130
		Integer numberReplicas = -1;
1131
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1132
    	if (replicationPolicy != null) {
1133
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1134
    		numberReplicas = replicationPolicy.getNumberReplicas();
1135
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1136
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1137
    	}
1138

    
1139
    	// the main systemMetadata fields
1140
		updateSystemMetadataFields(
1141
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1142
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(), 
1143
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(), 
1144
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm().xmlValue(), 
1145
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1146
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(), 
1147
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1148
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(), 
1149
                sm.getIdentifier().getValue(),
1150
                sm.getObjectFormat() == null ? null: sm.getObjectFormat().getFmtid().getValue(),
1151
                sm.getSize(),
1152
                replicationAllowed, 
1153
                numberReplicas,
1154
                sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
1155
                sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue());
1156
        
1157
        String guid = sm.getIdentifier().getValue();
1158
        
1159
        // save replication policies
1160
        if (replicationPolicy != null) {
1161
		    List<String> nodes = null;
1162
		    String policy = null;
1163
		    
1164
		    nodes = new ArrayList<String>();
1165
		    policy = "blocked";
1166
		    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1167
		    	nodes.add(node.getValue());
1168
		    }
1169
		    this.insertReplicationPolicy(guid, policy, nodes);
1170
		    
1171
		    nodes = new ArrayList<String>();
1172
		    policy = "preferred";
1173
		    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1174
		    	nodes.add(node.getValue());
1175
		    }
1176
	        this.insertReplicationPolicy(guid, policy, nodes);
1177
        }
1178
        
1179
        // save replica information
1180
        this.insertReplicationStatus(guid, sm.getReplicaList());
1181
        
1182
        // save access policy
1183
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1184
        if (accessPolicy != null) {
1185
        	try {
1186
				this.insertAccessPolicy(guid, accessPolicy);
1187
			} catch (AccessException e) {
1188
				throw new McdbDocNotFoundException(e);
1189
			}
1190
        }
1191
    }
1192
    
1193
    /**
1194
     * Creates Metacat access rules and inserts them
1195
     * @param accessPolicy
1196
     * @throws McdbDocNotFoundException
1197
     * @throws AccessException
1198
     */
1199
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1200
    	
1201
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1202
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1203
        	List<Subject> subjects = accessRule.getSubjectList();
1204
        	List<Permission> permissions = accessRule.getPermissionList();
1205
        	for (Subject subject: subjects) {
1206
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1207
        		accessDAO.setPrincipalName(subject.getValue());
1208
    			accessDAO.setGuid(guid);
1209
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1210
    			accessDAO.setPermOrder(AccessControlInterface.DENYFIRST);
1211
    			for (Permission permission: permissions) {
1212
    				Long metacatPermission = new Long(convertPermission(permission));
1213
        			accessDAO.addPermission(metacatPermission);
1214
    			}
1215
    			accessDAOs.add(accessDAO);
1216
        	}
1217
        }
1218
        
1219
        // use GUID to update
1220
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1221
        accessController.replaceAccess(guid, accessDAOs);
1222
        
1223
        
1224
    }
1225
    
1226
    /**
1227
     * Lookup access policy from Metacat
1228
     * @param guid
1229
     * @return
1230
     * @throws McdbDocNotFoundException
1231
     * @throws AccessException
1232
     */
1233
    private AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1234
    	// use GUID to look up the access
1235
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1236
    	List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1237
    	AccessRule accessRule = new AccessRule();    	
1238
        for (XMLAccessDAO accessDAO: accessDAOs) {
1239
        	Permission permission = convertPermission(accessDAO.getPermission().intValue());
1240
        	accessRule.addPermission(permission);
1241
        	Subject subject = new Subject();
1242
        	subject.setValue(accessDAO.getPrincipalName());
1243
        	accessRule.addSubject(subject);
1244
        }
1245
        AccessPolicy accessPolicy = new AccessPolicy();
1246
        accessPolicy.addAllow(accessRule);
1247
        return accessPolicy;
1248
    }
1249
    
1250
    public int convertPermission(Permission permission) {
1251
    	if (permission.equals(Permission.READ)) {
1252
    		return AccessControlInterface.READ;
1253
    	}
1254
    	if (permission.equals(Permission.WRITE)) {
1255
    		return AccessControlInterface.WRITE;
1256
    	}
1257
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1258
    		return AccessControlInterface.CHMOD;
1259
    	}
1260
		return -1;
1261
    }
1262
    
1263
    public Permission convertPermission(int permission) {
1264
    	if (permission == AccessControlInterface.READ) {
1265
    		return Permission.READ;
1266
    	}
1267
    	if (permission == AccessControlInterface.WRITE) {
1268
    		return Permission.WRITE;
1269
    	}
1270
    	if (permission == AccessControlInterface.CHMOD) {
1271
    		return Permission.CHANGE_PERMISSION;
1272
    	}
1273
		return null;
1274
    }
1275
    
1276
    /**
1277
     * Lookup a localId given the GUID. If
1278
     * the identifier is not found, throw an exception.
1279
     * 
1280
     * @param guid the global identifier to look up
1281
     * @return String containing the corresponding LocalId
1282
     * @throws McdbDocNotFoundException if the identifier is not found
1283
     */
1284
    public String getLocalId(String guid) throws McdbDocNotFoundException {
1285
      
1286
      String db_guid = "";
1287
      String docid = "";
1288
      int rev = 0;
1289
      
1290
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1291
      
1292
      DBConnection dbConn = null;
1293
      int serialNumber = -1;
1294
      try {
1295
          // Get a database connection from the pool
1296
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1297
          serialNumber = dbConn.getCheckOutSerialNumber();
1298
          
1299
          // Execute the insert statement
1300
          PreparedStatement stmt = dbConn.prepareStatement(query);
1301
          stmt.setString(1, guid);
1302
          ResultSet rs = stmt.executeQuery();
1303
          if (rs.next()) {
1304
              db_guid = rs.getString(1);
1305
              docid = rs.getString(2);
1306
              rev = rs.getInt(3);
1307
              assert(db_guid.equals(guid));
1308
          } else {
1309
              throw new McdbDocNotFoundException("Document not found:" + guid);
1310
          }
1311
          stmt.close();
1312
      } catch (SQLException e) {
1313
          logMetacat.error("Error while looking up the local identifier: " 
1314
                  + e.getMessage());
1315
      } finally {
1316
          // Return database connection to the pool
1317
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1318
      }
1319
      return docid + "." + rev;
1320
    }
1321
    
1322
    /**
1323
     * query the systemmetadata table based on the given parameters
1324
     * @param startTime
1325
     * @param endTime
1326
     * @param objectFormat
1327
     * @param replicaStatus
1328
     * @param start
1329
     * @param count
1330
     * @return ObjectList
1331
     * @throws SQLException 
1332
     * @throws ServiceException 
1333
     * @throws PropertyNotFoundException 
1334
     */
1335
    public ObjectList querySystemMetadata(Date startTime, Date endTime, 
1336
            ObjectFormatIdentifier objectFormatId, boolean replicaStatus, int start, int count) throws SQLException, PropertyNotFoundException, ServiceException
1337
    {
1338
        ObjectList ol = new ObjectList();
1339
        int total = 0;
1340
        DBConnection dbConn = null;
1341
        int serialNumber = -1;
1342
        
1343
        try {
1344
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
1345
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
1346
                "date_modified, submitter, object_format, size from systemmetadata";
1347
            
1348
            boolean f1 = false;
1349
            boolean f2 = false;
1350
            boolean f3 = false;
1351
            
1352
            if (startTime != null) {
1353
                sql += " where systemmetadata.date_modified > ?";
1354
                f1 = true;
1355
            }
1356
            
1357
            if (endTime != null) {
1358
                if (!f1) {
1359
                    sql += " where systemmetadata.date_modified < ?";
1360
                }
1361
                else {
1362
                    sql += " and systemmetadata.date_modified < ?";
1363
                }
1364
                f2 = true;
1365
            }
1366
            
1367
            if (objectFormatId != null) {
1368
                if (!f1 && !f2) {
1369
                    sql += " where object_format = ?";
1370
                }
1371
                else {
1372
                    sql += " and object_format = ?";
1373
                }
1374
                f3 = true;
1375
            }
1376
            
1377
            if (replicaStatus) {
1378
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
1379
                if (!f1 && !f2 && !f3) {
1380
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
1381
                }
1382
                else {
1383
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
1384
                }
1385
            }
1386
            
1387
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1388
            serialNumber = dbConn.getCheckOutSerialNumber();
1389
            PreparedStatement stmt = dbConn.prepareStatement(sql);
1390
            
1391
            if (f1 && f2 && f3) {
1392
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1393
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1394
                stmt.setString(3, objectFormatId.getValue());
1395
            }
1396
            else if (f1 && f2 && !f3) {
1397
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1398
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1399
            }
1400
            else if (f1 && !f2 && f3) {
1401
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1402
                stmt.setString(2, objectFormatId.getValue());
1403
            }
1404
            else if (f1 && !f2 && !f3) {
1405
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1406
            }
1407
            else if (!f1 && f2 && f3) {
1408
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1409
                stmt.setString(2, objectFormatId.getValue());
1410
            }
1411
            else if (!f1 && !f2 && f3) {
1412
                stmt.setString(1, objectFormatId.getValue());
1413
            }
1414
            else if (!f1 && f2 && !f3) {
1415
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1416
            }
1417
            
1418
            //logMetacat.debug("LISTOBJECTS QUERY: " + stmt.toString());
1419
            
1420
            ResultSet rs = stmt.executeQuery();
1421
            for (int i=0; i<start; i++) {
1422
                if (rs.next()) {
1423
                    total++;
1424
                } else {
1425
                    break;
1426
                }
1427
            }
1428
            
1429
            int countIndex = 0;
1430
                        
1431
            while (rs.next()) {
1432
                total++;
1433
                if (countIndex >= count) {
1434
                	// allow unlimited (negative number for count)
1435
                	if (count > 0) {
1436
                		break;
1437
                	}
1438
                }
1439
                                
1440
                String guid = rs.getString(1);
1441
                //logMetacat.debug("query found doc with guid " + guid);
1442
                //Timestamp dateUploaded = rs.getTimestamp(2);
1443
                //String rightsHolder = rs.getString(3);
1444
                String checksum = rs.getString(4);
1445
                String checksumAlgorithm = rs.getString(5);
1446
                //String originMemberNode = rs.getString(6);
1447
                //String authoritiveMemberNode = rs.getString(7);
1448
                Timestamp dateModified = rs.getTimestamp(8);
1449
                //String submitter = rs.getString(9);
1450
                String fmtidStr = rs.getString(10);
1451
                String sz = rs.getString(11);
1452
                long size = 0;
1453
                
1454
                if (sz != null && !sz.trim().equals("")) {
1455
                    size = new Long(rs.getString(11)).longValue();
1456
                }
1457
                
1458
                ObjectInfo oi = new ObjectInfo();
1459
                
1460
                Identifier id = new Identifier();
1461
                id.setValue(guid);
1462
                oi.setIdentifier(id);
1463
                
1464
                if (dateModified != null) {
1465
                	oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
1466
                }
1467
                
1468
                Checksum cs = new Checksum();
1469
                cs.setValue(checksum);
1470
                try {
1471
                	//cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1472
                    cs.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
1473
                } catch (Exception e) {
1474
					logMetacat.warn("could not parse checksum algorithm", e);
1475
				}
1476
                oi.setChecksum(cs);
1477
                
1478
                try {
1479
	                oi.setObjectFormat(ObjectFormatCache.getInstance().getFormat(fmtidStr));
1480
                } catch (NotFound e) {
1481
                	logMetacat.warn("could not find object format: " + fmtidStr, e);
1482
				}
1483
                                
1484
                oi.setSize(size);
1485
                
1486
                ol.addObjectInfo(oi);
1487
                countIndex++;
1488
            }
1489
            
1490
            // expend the resultset to get the total count of possible rows
1491
            while (rs.next()) { 
1492
                total++;
1493
            }
1494
        }
1495
        
1496
        finally {
1497
            // Return database connection to the pool
1498
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1499
        }
1500
        
1501
        ol.setStart(start);
1502
        ol.setCount(ol.sizeObjectInfoList());
1503
        ol.setTotal(total);
1504
        
1505
        return ol;
1506
    }
1507
    
1508
    /**
1509
     * create a mapping in the identifier table
1510
     * @param guid
1511
     * @param localId
1512
     */
1513
    public void createMapping(String guid, String localId)
1514
    {        
1515
        
1516
        int serialNumber = -1;
1517
        DBConnection dbConn = null;
1518
        try {
1519

    
1520
            // Parse the localId into scope and rev parts
1521
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1522
            String docid = acc.getDocid();
1523
            int rev = 1;
1524
            if (acc.getRev() != null) {
1525
              rev = (new Integer(acc.getRev()).intValue());
1526
            }
1527

    
1528
            // Get a database connection from the pool
1529
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1530
            serialNumber = dbConn.getCheckOutSerialNumber();
1531

    
1532
            // Execute the insert statement
1533
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1534
            PreparedStatement stmt = dbConn.prepareStatement(query);
1535
            stmt.setString(1, guid);
1536
            stmt.setString(2, docid);
1537
            stmt.setInt(3, rev);
1538
            logMetacat.debug("mapping query: " + stmt.toString());
1539
            int rows = stmt.executeUpdate();
1540

    
1541
            stmt.close();
1542
        } catch (SQLException e) {
1543
            e.printStackTrace();
1544
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1545
                    + e.getMessage());
1546
        } catch (NumberFormatException e) {
1547
            e.printStackTrace();
1548
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1549
                    + e.getMessage());
1550
        } catch (AccessionNumberException e) {
1551
            e.printStackTrace();
1552
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1553
                    + e.getMessage());
1554
        } finally {
1555
            // Return database connection to the pool
1556
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1557
        }
1558
    }
1559
    
1560
    /**
1561
     * create the systemmetadata record
1562
     * @param guid
1563
     */
1564
    private void insertSystemMetadata(String guid)
1565
    {        
1566
        
1567
        int serialNumber = -1;
1568
        DBConnection dbConn = null;
1569
        try {
1570

    
1571
            // Get a database connection from the pool
1572
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1573
            serialNumber = dbConn.getCheckOutSerialNumber();
1574

    
1575
            // Execute the insert statement
1576
            String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1577
            PreparedStatement stmt = dbConn.prepareStatement(query);
1578
            stmt.setString(1, guid);
1579
            logMetacat.debug("system metadata query: " + stmt.toString());
1580
            int rows = stmt.executeUpdate();
1581

    
1582
            stmt.close();
1583
        } catch (Exception e) {
1584
            e.printStackTrace();
1585
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1586
        } finally {
1587
            // Return database connection to the pool
1588
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1589
        }
1590
    }
1591
    
1592
    private void deleteSystemMetadata(String guid)
1593
    {        
1594
        
1595
        int serialNumber = -1;
1596
        DBConnection dbConn = null;
1597
        try {
1598

    
1599
            // Get a database connection from the pool
1600
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1601
            serialNumber = dbConn.getCheckOutSerialNumber();
1602

    
1603
            // Execute the statement
1604
            String query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
1605
            PreparedStatement stmt = dbConn.prepareStatement(query);
1606
            stmt.setString(1, guid);
1607
            logMetacat.debug("delete system metadata: " + stmt.toString());
1608
            int rows = stmt.executeUpdate();
1609

    
1610
            stmt.close();
1611
        } catch (Exception e) {
1612
            e.printStackTrace();
1613
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1614
        } finally {
1615
            // Return database connection to the pool
1616
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1617
        }
1618
    }
1619
}
1620

    
(37-37/65)