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.Session;
55
import org.dataone.service.types.v1.Subject;
56
import org.dataone.service.types.v1.SystemMetadata;
57

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

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

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

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

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

    
182
            // Execute the insert statement
183
            PreparedStatement stmt = dbConn.prepareStatement(sql);
184
            stmt.setString(1, localId);
185
            ResultSet rs = stmt.executeQuery();
186
            if (rs.next()) 
187
            {
188
                String guid = rs.getString(1);
189
                Timestamp dateUploaded = rs.getTimestamp(2);
190
                String rightsHolder = rs.getString(3);
191
                String checksum = rs.getString(4);
192
                String checksumAlgorithm = rs.getString(5);
193
                String originMemberNode = rs.getString(6);
194
                String authoritativeMemberNode = rs.getString(7);
195
                Timestamp dateModified = rs.getTimestamp(8);
196
                String submitter = rs.getString(9);
197
                String objectFormat = rs.getString(10);
198
                long size = new Long(rs.getString(11)).longValue();
199
                
200
                h.put("guid", guid);
201
                h.put("date_uploaded", new Long(dateUploaded.getTime()).toString());
202
                h.put("rights_holder", rightsHolder);
203
                h.put("checksum", checksum);
204
                h.put("checksum_algorithm", checksumAlgorithm);
205
                h.put("origin_member_node", originMemberNode);
206
                h.put("authoritative_member_node", authoritativeMemberNode);
207
                h.put("date_modified", new Long(dateModified.getTime()).toString());
208
                h.put("submitter", submitter);
209
                h.put("object_format", objectFormat);
210
                h.put("size", new Long(size).toString());
211
                
212
                stmt.close();
213
            } 
214
            else
215
            {
216
                stmt.close();
217
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
218
                throw new McdbDocNotFoundException("2Could not find document " + localId);
219
            }
220
            
221
        } 
222
        catch (SQLException e) 
223
        {
224
            e.printStackTrace();
225
            logMetacat.error("Error while getting system metadata info for localid " + localId + " : "  
226
                    + e.getMessage());
227
        } 
228
        finally 
229
        {
230
            // Return database connection to the pool
231
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
232
        }
233
        return h;
234
    }
235
    
236
    /**
237
     * return a hash of all of the info that is in the systemmetadata table
238
     * @param guid
239
     * @return
240
     * @throws McdbDocNotFoundException 
241
     */
242
    public SystemMetadata getSystemMetadata(String guid)
243
    	throws McdbDocNotFoundException
244
    {
245
        
246
        SystemMetadata sysMeta = new SystemMetadata();
247
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
248
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size " +
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
                
275
                Identifier sysMetaId = new Identifier();
276
                sysMetaId.setValue(guid);
277
                sysMeta.setIdentifier(sysMetaId);
278
                sysMeta.setDateUploaded(dateUploaded);
279
                Subject rightsHolderSubject = new Subject();
280
                rightsHolderSubject.setValue(rightsHolder);
281
                sysMeta.setRightsHolder(rightsHolderSubject);
282
                Checksum checksumObject = new Checksum();
283
                checksumObject.setValue(checksum);
284
                checksumObject.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
285
                sysMeta.setChecksum(checksumObject);
286
                NodeReference omn = new NodeReference();
287
                omn.setValue(originMemberNode);
288
                sysMeta.setOriginMemberNode(omn);
289
                NodeReference amn = new NodeReference();
290
                amn.setValue(authoritativeMemberNode);
291
                sysMeta.setAuthoritativeMemberNode(amn);
292
                sysMeta.setDateSysMetadataModified(dateModified);
293
                Subject submitterSubject = new Subject();
294
                submitterSubject.setValue(submitter);
295
                sysMeta.setSubmitter(submitterSubject);
296
                try {
297
        	        sysMeta.setObjectFormat(ObjectFormatCache.getInstance().getFormat(fmtidStr));
298
                } catch (NotFound nfe) {
299
                  logMetacat.error("The objectFormat " + fmtidStr +
300
                  	" is not registered. Setting the default format.");
301
                  ObjectFormat of = new ObjectFormat();
302
                  ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
303
                  fmtid.setValue("application/octet-stream");
304
                  of.setFmtid(fmtid);
305
                  of.setFormatName("Octet Stream");
306
                  sysMeta.setObjectFormat(of);
307
                }
308
                sysMeta.setSize(size);
309
                
310
                stmt.close();
311
            } 
312
            else
313
            {
314
                stmt.close();
315
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
316
                throw new McdbDocNotFoundException("Could not find " + guid);
317
            }
318
            
319
        } 
320
        catch (SQLException e) 
321
        {
322
            e.printStackTrace();
323
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "  
324
                    + e.getMessage());
325
        } 
326
        finally 
327
        {
328
            // Return database connection to the pool
329
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
330
        }
331
        
332
        // look up provenance information
333
        sysMeta.setObsoletes(getSystemMetadataProvenance(sysMeta.getIdentifier().getValue(), "obsoletes").get(0));
334
        sysMeta.setObsoletedBy(getSystemMetadataProvenance(sysMeta.getIdentifier().getValue(), "obsoletedBy").get(0));
335
        
336
        // look up replication policy
337
        ReplicationPolicy replicationPolicy = new ReplicationPolicy();
338
        replicationPolicy.setBlockedMemberNodeList(getReplicationPolicy(guid, "blocked"));
339
        replicationPolicy.setPreferredMemberNodeList(getReplicationPolicy(guid, "preferred"));
340
		sysMeta.setReplicationPolicy(replicationPolicy);
341
		
342
		// look up replication status
343
		sysMeta.setReplicaList(getReplicationStatus(guid));
344
		
345
		// look up access policy
346
		try {
347
			sysMeta.setAccessPolicy(getAccessPolicy(guid));
348
		} catch (AccessException e) {
349
			throw new McdbDocNotFoundException(e);
350
		}
351
        
352
        return sysMeta;
353
    }
354
    
355
    private List<Identifier> getSystemMetadataProvenance(String guid, String relationship)
356
    	throws McdbDocNotFoundException {
357
    	
358
    	List<Identifier> identifiers = new ArrayList<Identifier>();
359
    	String sql = "select guid, relationship, target_guid " +
360
    		"from systemMetadataProvenance where guid = ? and relationship = ?";
361
	    DBConnection dbConn = null;
362
	    int serialNumber = -1;
363
	    try {
364
	        // Get a database connection from the pool
365
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getSystemMetadataProvenance");
366
	        serialNumber = dbConn.getCheckOutSerialNumber();
367
	
368
	        // Execute the statement
369
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
370
	        stmt.setString(1, guid);
371
	        stmt.setString(2, relationship);
372
	        ResultSet rs = stmt.executeQuery();
373
	        while (rs.next()) 
374
	        {
375
	            String targetGuid = rs.getString(3);
376
	            Identifier id = new Identifier();
377
	            id.setValue(targetGuid);
378
	            identifiers.add(id);
379
	        
380
	        } 
381
	        stmt.close();
382
	        
383
	    } 
384
	    catch (SQLException e) {
385
	        logMetacat.error("Error while getting system metadata provenance for guid " + guid, e);
386
	    } 
387
	    finally {
388
	        // Return database connection to the pool
389
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
390
	    }
391
	    
392
	    return identifiers;
393
	}
394
    
395
    private List<NodeReference> getReplicationPolicy(String guid, String policy)
396
		throws McdbDocNotFoundException {
397
		
398
		List<NodeReference> nodes = new ArrayList<NodeReference>();
399
		String sql = "select guid, policy, member_node " +
400
			"from systemMetadataReplicationPolicy where guid = ? and policy = ?";
401
	    DBConnection dbConn = null;
402
	    int serialNumber = -1;
403
	    try {
404
	        // Get a database connection from the pool
405
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicationPolicy");
406
	        serialNumber = dbConn.getCheckOutSerialNumber();
407
	
408
	        // Execute the statement
409
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
410
	        stmt.setString(1, guid);
411
	        stmt.setString(2, policy);
412
	        ResultSet rs = stmt.executeQuery();
413
	        while (rs.next()) 
414
	        {
415
	            String memberNode = rs.getString(3);
416
	            NodeReference node = new NodeReference();
417
	            node.setValue(memberNode);
418
	            nodes.add(node);
419
	        
420
	        } 
421
	        stmt.close();
422
	        
423
	    } catch (SQLException e) {
424
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
425
	    } 
426
	    finally {
427
	        // Return database connection to the pool
428
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
429
	    }
430
	    
431
	    return nodes;
432
	}
433
    
434
    private List<Replica> getReplicationStatus(String guid) throws McdbDocNotFoundException {
435
		
436
		List<Replica> replicas = new ArrayList<Replica>();
437
		String sql = "select guid, member_node, status, date_verified " +
438
			"from systemMetadataReplicationStatus where guid = ?";
439
	    DBConnection dbConn = null;
440
	    int serialNumber = -1;
441
	    try {
442
	        // Get a database connection from the pool
443
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicas");
444
	        serialNumber = dbConn.getCheckOutSerialNumber();
445
	
446
	        // Execute the statement
447
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
448
	        stmt.setString(1, guid);
449
	        ResultSet rs = stmt.executeQuery();
450
	        while (rs.next()) 
451
	        {
452
	            String memberNode = rs.getString(2);
453
	            String status = rs.getString(3);
454
	            java.sql.Date verified = rs.getDate(4);
455
	            
456
	            Replica replica = new Replica();	            
457
	            NodeReference node = new NodeReference();
458
	            node.setValue(memberNode);
459
	            replica.setReplicaMemberNode(node);
460
	            replica.setReplicationStatus(ReplicationStatus.convert(status));
461
	            replica.setReplicaVerified(new Date(verified.getTime()));
462
	            replicas.add(replica);
463
	        } 
464
	        stmt.close();
465
	        
466
	    } catch (SQLException e) {
467
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
468
	    } 
469
	    finally {
470
	        // Return database connection to the pool
471
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
472
	    }
473
	    
474
	    return replicas;
475
	}
476
    
477
    /**
478
     * return information on the document with localId.  These are the fields
479
     * from the xml_documents table.  They can be used to contstruct metadata 
480
     * about the object that is stored.
481
     * @param localId
482
     * @return
483
     * @throws McdbDocNotFoundException
484
     */
485
    public Hashtable<String, Object> getDocumentInfo(String localId)
486
        throws McdbDocNotFoundException
487
    {
488
        try
489
        {
490
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
491
            localId = acc.getDocid();
492
        }
493
        catch(Exception e)
494
        {
495
            //do nothing. just try the localId as it is
496
        }
497
        Hashtable<String, Object> h = new Hashtable<String, Object>();
498
        String sql = "select docname, doctype, user_owner, user_updated, " +
499
            "server_location, rev, date_created, date_updated from " + 
500
            "xml_documents where docid like '" + localId + "'";
501
        DBConnection dbConn = null;
502
        int serialNumber = -1;
503
        try 
504
        {
505
            // Get a database connection from the pool
506
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
507
            serialNumber = dbConn.getCheckOutSerialNumber();
508

    
509
            // Execute the insert statement
510
            PreparedStatement stmt = dbConn.prepareStatement(sql);
511
            ResultSet rs = stmt.executeQuery();
512
            if (rs.next()) 
513
            {
514
                String docname = rs.getString(1);
515
                String doctype = rs.getString(2);
516
                String user_owner = rs.getString(3);
517
                String user_updated = rs.getString(4);
518
                String server_location = rs.getString(5);
519
                int rev = rs.getInt(6);
520
                String date_created = rs.getString(7);
521
                String date_updated = rs.getString(8);
522
                h.put("docid", localId);
523
                h.put("docname", docname);
524
                h.put("doctype", doctype);
525
                h.put("user_owner", user_owner);
526
                h.put("user_updated", user_updated);
527
                h.put("server_location", server_location);
528
                h.put("rev", new Integer(rev).toString());
529
                h.put("date_created", date_created);
530
                h.put("date_updated", date_updated);
531
                
532
                stmt.close();
533
            } 
534
            else
535
            {
536
                stmt.close();
537
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
538
                throw new McdbDocNotFoundException("2Could not find document " + localId);
539
            }
540
            
541
            String sql2 = "select principal_name, permission, perm_type, perm_order from xml_access " +
542
            "where docid like '" + localId + "'";
543
            logMetacat.debug("executing sql: " + sql2);
544
            PreparedStatement stmt2 = dbConn.prepareStatement(sql2);
545
            rs = stmt2.executeQuery();
546
            Vector accessVector = new Vector();
547
            while(rs.next())
548
            {
549
                Hashtable accessHash = new Hashtable();
550
                String principal_name = rs.getString(1);
551
                String permission = rs.getString(2);
552
                String permissionType = rs.getString(3);
553
                String permissionOrder = rs.getString(4);
554
                accessHash.put("principal_name", principal_name);
555
                accessHash.put("permission", permission);
556
                accessHash.put("permission_type", permissionType);
557
                accessHash.put("permission_order", permissionOrder);
558
                logMetacat.debug("accessHash: " + accessHash.toString());
559
                accessVector.add(accessHash);
560
            }
561
            h.put("access", accessVector);
562
        } 
563
        catch (SQLException e) 
564
        {
565
            e.printStackTrace();
566
            logMetacat.error("Error while getting document info for localid " + localId + " : "  
567
                    + e.getMessage());
568
        } 
569
        finally 
570
        {
571
            // Return database connection to the pool
572
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
573
        }
574
        return h;
575
    }
576
    
577
    /**
578
     * return the newest rev for a given localId
579
     * @param localId
580
     * @return
581
     */
582
    public int getLatestRevForLocalId(String localId)
583
        throws McdbDocNotFoundException
584
    {
585
        try
586
        {
587
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
588
            localId = acc.getDocid();
589
        }
590
        catch(Exception e)
591
        {
592
            //do nothing. just try the localId as it is
593
        }
594
        int rev = 0;
595
        String sql = "select rev from xml_documents where docid like '" + localId + "'";
596
        DBConnection dbConn = null;
597
        int serialNumber = -1;
598
        try 
599
        {
600
            // Get a database connection from the pool
601
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLatestRevForLocalId");
602
            serialNumber = dbConn.getCheckOutSerialNumber();
603

    
604
            // Execute the insert statement
605
            PreparedStatement stmt = dbConn.prepareStatement(sql);
606
            ResultSet rs = stmt.executeQuery();
607
            if (rs.next()) 
608
            {
609
                rev = rs.getInt(1);
610
                stmt.close();
611
            } 
612
            else
613
            {
614
                stmt.close();
615
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
616
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
617
            }
618
        } 
619
        catch (SQLException e) 
620
        {
621
            logMetacat.error("Error while looking up the guid: " 
622
                    + e.getMessage());
623
        } 
624
        finally 
625
        {
626
            // Return database connection to the pool
627
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
628
        }
629
        return rev;
630
    }
631
    
632
    /**
633
     * return all local ids in the object store that do not have associated
634
     * system metadata
635
     */
636
    public List<String> getLocalIdsWithNoSystemMetadata()
637
    {
638
        Vector<String> ids = new Vector<String>();
639
        String sql = "select docid, rev from xml_documents " +
640
        		"where docid not in " +
641
        		"(select docid from identifier where guid in (select guid from systemmetadata)))";
642
        DBConnection dbConn = null;
643
        int serialNumber = -1;
644
        try 
645
        {
646
            // Get a database connection from the pool
647
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
648
            serialNumber = dbConn.getCheckOutSerialNumber();
649

    
650
            // Execute the insert statement
651
            PreparedStatement stmt = dbConn.prepareStatement(sql);
652
            ResultSet rs = stmt.executeQuery();
653
            while (rs.next()) 
654
            {
655
                String localid = rs.getString(1);
656
                String rev = rs.getString(2);
657
                localid += "." + rev;
658
                logMetacat.debug("id to add SM for: " + localid);
659
                ids.add(localid);
660
            } 
661
            stmt.close();
662
        } 
663
        catch (SQLException e) 
664
        {
665
            logMetacat.error("Error while looking up the guid: " 
666
                    + e.getMessage());
667
        } 
668
        finally 
669
        {
670
            // Return database connection to the pool
671
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
672
        }
673
        
674
        return ids;
675
    }
676
    
677
    /**
678
     * return a listing of all local ids in the object store
679
     * @return a list of all local ids in metacat
680
     */
681
    public List<String> getAllLocalIds()
682
       throws Exception
683
    {
684
        Vector<String> ids = new Vector<String>();
685
        String sql = "select docid from xml_documents";
686
        DBConnection dbConn = null;
687
        int serialNumber = -1;
688
        try 
689
        {
690
            // Get a database connection from the pool
691
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
692
            serialNumber = dbConn.getCheckOutSerialNumber();
693

    
694
            // Execute the insert statement
695
            PreparedStatement stmt = dbConn.prepareStatement(sql);
696
            ResultSet rs = stmt.executeQuery();
697
            while (rs.next()) 
698
            {
699
                String localid = rs.getString(1);
700
                ids.add(localid);
701
            } 
702
            stmt.close();
703
        } 
704
        catch (SQLException e) 
705
        {
706
            logMetacat.error("Error while looking up the guid: " 
707
                    + e.getMessage());
708
        } 
709
        finally 
710
        {
711
            // Return database connection to the pool
712
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
713
        }
714
        return ids;
715
    }
716
    
717
    /**
718
     * returns a list of system metadata-only guids since the given date
719
     * @return a list of system ids in metacat that do not correspond to objects
720
     * TODO: need to check which server they are on
721
     */
722
    public List<String> getUpdatedSystemMetadataIds(Date since)
723
       throws Exception
724
    {
725
        List<String> ids = new Vector<String>();
726
        String sql = 
727
        	"select guid from " + TYPE_SYSTEM_METADATA +
728
        	" where guid not in " +
729
        	" (select guid from " + TYPE_IDENTIFIER + ") " +
730
        	" and date_modified > ?";
731
        DBConnection dbConn = null;
732
        int serialNumber = -1;
733
        try 
734
        {
735
            // Get a database connection from the pool
736
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getUpdatedSystemMetadataIds");
737
            serialNumber = dbConn.getCheckOutSerialNumber();
738

    
739
            // Execute the insert statement
740
            PreparedStatement stmt = dbConn.prepareStatement(sql);
741
            stmt.setDate(1, new java.sql.Date(since.getTime()));
742
            ResultSet rs = stmt.executeQuery();
743
            while (rs.next()) 
744
            {
745
                String guid = rs.getString(1);
746
                ids.add(guid);
747
            } 
748
            stmt.close();
749
        } 
750
        catch (SQLException e) 
751
        {
752
            logMetacat.error("Error while looking up the updated guids: " 
753
                    + e.getMessage());
754
        } 
755
        finally 
756
        {
757
            // Return database connection to the pool
758
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
759
        }
760
        return ids;
761
    }
762
    
763

    
764
    
765
    /**
766
     * Determine if an identifier exists already, returning true if so.
767
     * 
768
     * @param guid the global identifier to look up
769
     * @return boolean true if the identifier exists
770
     */
771
    public boolean identifierExists(String guid)
772
    {
773
        boolean idExists = false;
774
        try {
775
            String id = getLocalId(guid);
776
            if (id != null) {
777
                idExists = true;
778
            }
779
        } catch (McdbDocNotFoundException e) {
780
        	// try system metadata only
781
        	try {
782
        		idExists = systemMetadataExisits(guid);
783
            } catch (McdbDocNotFoundException e2) {
784
            	idExists = false;
785
            }
786
        }
787
        return idExists;
788
    }
789
    
790
    /**
791
     * 
792
     * @param guid
793
     * @param rev
794
     * @return
795
     */
796
    public String generateLocalId(String guid, int rev)
797
    {
798
        return generateLocalId(guid, rev, false);
799
    }
800

    
801
    /**
802
     * Given a global identifier (guid), create a suitable local identifier that
803
     * follows Metacat's docid semantics and format (scope.id.rev), and create
804
     * a mapping between these two identifiers.  This effectively reserves both
805
     * the global and the local identifier, as they will now be present in the
806
     * identifier mapping table.  If the incoming guid has the syntax of a
807
     * Metacat docid (scope.id.rev), then simply use it.
808
     * 
809
     * @param guid the global string identifier
810
     * @param rev the revision number to be used in the localId
811
     * @return String containing the localId to be used for Metacat operations
812
     */
813
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata) 
814
    {
815
        String localId = "";
816
        boolean conformsToDocidFormat = false;
817
        
818
        // Check if the guid passed in is already in docid (scope.id.rev) format
819
        try {
820
            AccessionNumber acc = new AccessionNumber(guid, "NONE");
821
            if (new Integer(acc.getRev()).intValue() > 0) {
822
                conformsToDocidFormat = true;
823
            }
824
        } catch (NumberFormatException e) {
825
            // No action needed, simply detecting invalid AccessionNumbers
826
        } catch (AccessionNumberException e) {
827
            // No action needed, simply detecting invalid AccessionNumbers
828
        } catch (SQLException e) {
829
            // No action needed, simply detecting invalid AccessionNumbers
830
        }
831
        
832
        if (conformsToDocidFormat) {
833
            // if it conforms, use it for both guid and localId
834
            localId = guid;
835
        } else {
836
            // if not, then generate a new unique localId
837
            localId = DocumentUtil.generateDocumentId(rev);
838
        }
839
        
840
        // Register this new pair in the identifier mapping table
841
        logMetacat.debug("creating mapping in generateLocalId");
842
        if(!isSystemMetadata)
843
        { //don't do this if we're generating for system metadata
844
            createMapping(guid, localId);
845
        }
846
        
847
        return localId;
848
    }
849
    
850
    /**
851
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
852
     * if the docid, rev is not found in the identifiers or systemmetadata tables
853
     *
854
     * @param docid the docid to look up
855
     * @param rev the revision of the docid to look up
856
     * @return String containing the mapped guid
857
     * @throws McdbDocNotFoundException if the docid, rev is not found
858
     */
859
    public String getGUID(String docid, int rev)
860
      throws McdbDocNotFoundException
861
    {
862
        logMetacat.debug("getting guid for " + docid);
863
        String query = "select guid from identifier where docid = ? and rev = ?";
864
        String guid = null;
865
        
866
        DBConnection dbConn = null;
867
        int serialNumber = -1;
868
        try {
869
            // Get a database connection from the pool
870
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
871
            serialNumber = dbConn.getCheckOutSerialNumber();
872
            
873
            // Execute the insert statement
874
            PreparedStatement stmt = dbConn.prepareStatement(query);
875
            stmt.setString(1, docid);
876
            stmt.setInt(2, rev);
877
            ResultSet rs = stmt.executeQuery();
878
            if (rs.next()) 
879
            {
880
                guid = rs.getString(1);
881
            } 
882
            else
883
            {
884
            	throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
885
            }
886
            
887
        } catch (SQLException e) {
888
            logMetacat.error("Error while looking up the guid: " 
889
                    + e.getMessage());
890
        } finally {
891
            // Return database connection to the pool
892
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
893
        }
894
        
895
        return guid;
896
    }
897
    
898
    public boolean systemMetadataExisits(String guid)
899
			throws McdbDocNotFoundException {
900
		logMetacat.debug("looking up system metadata for guid " + guid);
901
		boolean exists = false;
902
		String query = "select guid from systemmetadata where guid = ?";
903

    
904
		DBConnection dbConn = null;
905
		int serialNumber = -1;
906
		try {
907
			// Get a database connection from the pool
908
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
909
			serialNumber = dbConn.getCheckOutSerialNumber();
910

    
911
			// Execute the insert statement
912
			PreparedStatement stmt = dbConn.prepareStatement(query);
913
			stmt.setString(1, guid);
914
			ResultSet rs = stmt.executeQuery();
915
			if (rs.next()) {
916
				exists = true;
917
			} else {
918
				throw new McdbDocNotFoundException(
919
						"No system metadata registered for guid " + guid);
920
			}
921

    
922
		} catch (SQLException e) {
923
			logMetacat.error("Error while looking up the system metadata: "
924
					+ e.getMessage());
925
		} finally {
926
			// Return database connection to the pool
927
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
928
		}
929

    
930
		return exists;
931
	}
932
    
933
    /**
934
     * creates a system metadata mapping and adds additional fields from sysmeta
935
     * to the table for quick searching.
936
     * 
937
     * @param guid the id to insert
938
     * @param localId the systemMetadata object to get the local id for
939
     * @throws McdbDocNotFoundException 
940
     */
941
    public void createSystemMetadata(SystemMetadata sysmeta) throws McdbDocNotFoundException
942
    {
943
    	String guid = sysmeta.getIdentifier().getValue();
944
    	// insert the record
945
        insertSystemMetadata(guid);
946
        // update with the values
947
        updateSystemMetadata(sysmeta);
948
    }
949
        
950
    
951
    /**
952
     * update a mapping
953
     * @param guid
954
     * @param localId
955
     */
956
    public void updateMapping(String guid, String localId)
957
    {
958
    	
959
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
960
        int serialNumber = -1;
961
        DBConnection dbConn = null;
962
        try {
963
            // Parse the localId into scope and rev parts
964
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
965
            String docid = acc.getDocid();
966
            int rev = 1;
967
            if(acc.getRev() != null)
968
            {
969
              rev = (new Integer(acc.getRev()).intValue());
970
            }
971

    
972
            // Get a database connection from the pool
973
            dbConn = 
974
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
975
            serialNumber = dbConn.getCheckOutSerialNumber();
976

    
977
            // Execute the update statement
978
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid='" + guid + "'";
979
            PreparedStatement stmt = dbConn.prepareStatement(query);
980
            stmt.setString(1, docid);
981
            stmt.setInt(2, rev);
982
            int rows = stmt.executeUpdate();
983

    
984
            stmt.close();
985
        } catch (SQLException e) {
986
            e.printStackTrace();
987
            logMetacat.error("SQL error while updating a mapping identifier: " 
988
                    + e.getMessage());
989
        } catch (NumberFormatException e) {
990
            e.printStackTrace();
991
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
992
                    + e.getMessage());
993
        } catch (AccessionNumberException e) {
994
            e.printStackTrace();
995
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
996
                    + e.getMessage());
997
        } finally {
998
            // Return database connection to the pool
999
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1000
        }
1001
        logMetacat.debug("done updating mapping");
1002
    }
1003
        
1004
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1005
            String checksum, String checksumAlgorithm, String originMemberNode,
1006
            String authoritativeMemberNode, long modifiedDate, String submitter, 
1007
            String guid, String objectFormat, long size, boolean replicationAllowed,
1008
            int numberReplicas)
1009
    {
1010
        DBConnection dbConn = null;
1011
        int serialNumber = -1;
1012
        
1013
        try {
1014
            // Get a database connection from the pool
1015
            dbConn = 
1016
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1017
            serialNumber = dbConn.getCheckOutSerialNumber();
1018

    
1019
            // Execute the insert statement
1020
            String query = "update " + TYPE_SYSTEM_METADATA + 
1021
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1022
                "origin_member_node, authoritive_member_node, date_modified, " +
1023
                "submitter, object_format, size, replication_allowed, number_replicas) " +
1024
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1025
            PreparedStatement stmt = dbConn.prepareStatement(query);
1026
            
1027
            //data values
1028
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1029
            stmt.setString(2, rightsHolder);
1030
            stmt.setString(3, checksum);
1031
            stmt.setString(4, checksumAlgorithm);
1032
            stmt.setString(5, originMemberNode);
1033
            stmt.setString(6, authoritativeMemberNode);
1034
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1035
            stmt.setString(8, submitter);
1036
            stmt.setString(9, objectFormat);
1037
            stmt.setString(10, new Long(size).toString());
1038
            stmt.setBoolean(11, replicationAllowed);
1039
            stmt.setInt(12, numberReplicas);
1040
            //where clause
1041
            stmt.setString(13, guid);
1042
            logMetacat.debug("stmt: " + stmt.toString());
1043
            //execute
1044
            int rows = stmt.executeUpdate();
1045

    
1046
            stmt.close();
1047
        } catch (SQLException e) {
1048
            e.printStackTrace();
1049
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: " 
1050
                    + e.getMessage());
1051
        } catch (NumberFormatException e) {
1052
            e.printStackTrace();
1053
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: " 
1054
                    + e.getMessage());
1055
        } finally {
1056
            // Return database connection to the pool
1057
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1058
        }
1059
    }
1060
    
1061
    private void insertSystemMetadataProvenance(String guid, String relationship, List<String> targetGuids)
1062
    {
1063
        DBConnection dbConn = null;
1064
        int serialNumber = -1;
1065
        
1066
        try {
1067
            // Get a database connection from the pool
1068
            dbConn = 
1069
                DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadataProvenance");
1070
            serialNumber = dbConn.getCheckOutSerialNumber();
1071

    
1072
            // remove existing values first
1073
            String delete = "delete from systemMetadataProvenance " + 
1074
            "where guid = ? and relationship = ?";
1075
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1076
	        //data values
1077
	        stmt.setString(1, guid);
1078
	        stmt.setString(2, relationship);
1079
	        //execute
1080
	        int deletedCount = stmt.executeUpdate();
1081
	        stmt.close();
1082
            
1083
            for (String targetGuid: targetGuids) {
1084
	            // Execute the insert statement
1085
	            String insert = "insert into systemMetadataProvenance " + 
1086
	                "(guid, relationship, target_guid) " +
1087
	                "values (?, ?, ?)";
1088
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1089
	            
1090
	            //data values
1091
	            insertStatement.setString(1, guid);
1092
	            insertStatement.setString(2, relationship);
1093
	            insertStatement.setString(3, targetGuid);
1094
	            //execute
1095
	            int rows = insertStatement.executeUpdate();
1096
	            insertStatement.close();
1097
            }
1098
        } catch (SQLException e) {
1099
            logMetacat.error("SQL error while adding systemMetadataProvenance for: " + guid, e); 
1100
        } finally {
1101
            // Return database connection to the pool
1102
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1103
        }
1104
    }
1105
    
1106
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes)
1107
    {
1108
        DBConnection dbConn = null;
1109
        int serialNumber = -1;
1110
        
1111
        try {
1112
            // Get a database connection from the pool
1113
            dbConn = 
1114
                DBConnectionPool.getDBConnection("IdentifierManager.insertReplicationPolicy");
1115
            serialNumber = dbConn.getCheckOutSerialNumber();
1116

    
1117
            // remove existing values first
1118
            String delete = "delete from systemMetadataReplicationPolicy " + 
1119
            "where guid = ? and policy = ?";
1120
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1121
	        //data values
1122
	        stmt.setString(1, guid);
1123
	        stmt.setString(2, policy);
1124
	        //execute
1125
	        int deletedCount = stmt.executeUpdate();
1126
	        stmt.close();
1127
            
1128
            for (String memberNode: memberNodes) {
1129
	            // Execute the insert statement
1130
	            String insert = "insert into systemMetadataReplicationPolicy " + 
1131
	                "(guid, policy, member_node) " +
1132
	                "values (?, ?, ?)";
1133
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1134
	            
1135
	            //data values
1136
	            insertStatement.setString(1, guid);
1137
	            insertStatement.setString(2, policy);
1138
	            insertStatement.setString(3, memberNode);
1139
	            //execute
1140
	            int rows = insertStatement.executeUpdate();
1141
	            insertStatement.close();
1142
            }
1143
        } catch (SQLException e) {
1144
            logMetacat.error("SQL error while adding systemMetadataReplicationPolicy for: " + guid, e); 
1145
        } finally {
1146
            // Return database connection to the pool
1147
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1148
        }
1149
    }
1150
    
1151
    private void insertReplicationStatus(String guid, List<Replica> replicas) {
1152
        DBConnection dbConn = null;
1153
        int serialNumber = -1;
1154
        
1155
        try {
1156
            // Get a database connection from the pool
1157
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertReplicas");
1158
            serialNumber = dbConn.getCheckOutSerialNumber();
1159

    
1160
            // remove existing values first
1161
            String delete = "delete from systemMetadataReplicationStatus " + 
1162
            "where guid = ?";
1163
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1164
	        //data values
1165
	        stmt.setString(1, guid);
1166
	        //execute
1167
	        int deletedCount = stmt.executeUpdate();
1168
	        stmt.close();
1169
            
1170
            for (Replica replica: replicas) {
1171
	            // Execute the insert statement
1172
	            String insert = "insert into systemMetadataReplicationStatus " + 
1173
	                "(guid, member_node, status, date_verified) " +
1174
	                "values (?, ?, ?, ?)";
1175
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1176
	            
1177
	            //data values
1178
	            String memberNode = replica.getReplicaMemberNode().getValue();
1179
	            String status = replica.getReplicationStatus().toString();
1180
	            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1181
	            insertStatement.setString(1, guid);
1182
	            insertStatement.setString(2, memberNode);
1183
	            insertStatement.setString(3, status);
1184
	            insertStatement.setDate(4, sqlDate);
1185

    
1186
	            //execute
1187
	            int rows = insertStatement.executeUpdate();
1188
	            insertStatement.close();
1189
            }
1190
        } catch (SQLException e) {
1191
            logMetacat.error("SQL error while adding systemMetadataReplicationStatus for: " + guid, e); 
1192
        } finally {
1193
            // Return database connection to the pool
1194
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1195
        }
1196
    }
1197
    
1198
    /**
1199
     * Insert the system metadata fields into the db
1200
     * @param sm
1201
     * @throws McdbDocNotFoundException 
1202
     */
1203
    public void updateSystemMetadata(SystemMetadata sm) throws McdbDocNotFoundException {
1204
    	
1205
        Boolean replicationAllowed = false;
1206
		Integer numberReplicas = -1;
1207
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1208
    	if (replicationPolicy != null) {
1209
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1210
    		numberReplicas = replicationPolicy.getNumberReplicas();
1211
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1212
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1213
    	}
1214

    
1215
    	// the main systemMetadata fields
1216
		updateSystemMetadataFields(
1217
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1218
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(), 
1219
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(), 
1220
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm().name(), 
1221
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1222
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(), 
1223
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1224
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(), 
1225
                sm.getIdentifier().getValue(),
1226
                sm.getObjectFormat() == null ? null: sm.getObjectFormat().getFmtid().getValue(),
1227
                sm.getSize(),
1228
                replicationAllowed, 
1229
                numberReplicas);
1230
        
1231
        // add provenance information
1232
        String guid = sm.getIdentifier().getValue();
1233
        Identifier id = null;
1234
        List<String> targetGuids = null;
1235
        String relationship = null;
1236
        
1237
        relationship = "obsoletedBy";
1238
        targetGuids = new ArrayList<String>();
1239
        id = sm.getObsoletedBy();
1240
        if (id != null) {
1241
	        targetGuids.add(id.getValue());
1242
	        this.insertSystemMetadataProvenance(guid, relationship, targetGuids);
1243
        }
1244
        relationship = "obsoletes";
1245
        targetGuids = new ArrayList<String>();
1246
        id = sm.getObsoletes();
1247
        if (id != null) {
1248
	        targetGuids.add(id.getValue());
1249
	        this.insertSystemMetadataProvenance(guid, relationship, targetGuids);
1250
        }
1251
        
1252
        // TODO inspect the ORE map
1253
        relationship = "describes";
1254
        relationship = "describedBy";        
1255
        relationship = "derivedFrom";
1256
                
1257
        // save replication policies
1258
        if (replicationPolicy != null) {
1259
		    List<String> nodes = null;
1260
		    String policy = null;
1261
		    
1262
		    nodes = new ArrayList<String>();
1263
		    policy = "blocked";
1264
		    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1265
		    	nodes.add(node.getValue());
1266
		    }
1267
		    this.insertReplicationPolicy(guid, policy, nodes);
1268
		    
1269
		    nodes = new ArrayList<String>();
1270
		    policy = "preferred";
1271
		    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1272
		    	nodes.add(node.getValue());
1273
		    }
1274
	        this.insertReplicationPolicy(guid, policy, nodes);
1275
        }
1276
        
1277
        // save replica information
1278
        this.insertReplicationStatus(guid, sm.getReplicaList());
1279
        
1280
        // save access policy
1281
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1282
        if (accessPolicy != null) {
1283
        	try {
1284
				this.insertAccessPolicy(guid, accessPolicy);
1285
			} catch (AccessException e) {
1286
				throw new McdbDocNotFoundException(e);
1287
			}
1288
        }
1289
    }
1290
    
1291
    /**
1292
     * Creates Metacat access rules and inserts them
1293
     * @param accessPolicy
1294
     * @throws McdbDocNotFoundException
1295
     * @throws AccessException
1296
     */
1297
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1298
    	
1299
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1300
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1301
        	List<Subject> subjects = accessRule.getSubjectList();
1302
        	List<Permission> permissions = accessRule.getPermissionList();
1303
        	for (Subject subject: subjects) {
1304
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1305
        		accessDAO.setPrincipalName(subject.getValue());
1306
    			accessDAO.setGuid(guid);
1307
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1308
    			accessDAO.setPermOrder(AccessControlInterface.DENYFIRST);
1309
    			for (Permission permission: permissions) {
1310
    				Long metacatPermission = new Long(convertPermission(permission));
1311
        			accessDAO.addPermission(metacatPermission);
1312
    			}
1313
    			accessDAOs.add(accessDAO);
1314
        	}
1315
        }
1316
        
1317
        // use GUID to update
1318
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1319
        accessController.replaceAccess(guid, accessDAOs);
1320
        
1321
        
1322
    }
1323
    
1324
    /**
1325
     * Lookup access policy from Metacat
1326
     * @param guid
1327
     * @return
1328
     * @throws McdbDocNotFoundException
1329
     * @throws AccessException
1330
     */
1331
    private AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1332
    	// use GUID to look up the access
1333
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1334
    	List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1335
    	AccessRule accessRule = new AccessRule();    	
1336
        for (XMLAccessDAO accessDAO: accessDAOs) {
1337
        	Permission permission = convertPermission(accessDAO.getPermission().intValue());
1338
        	accessRule.addPermission(permission);
1339
        	Subject subject = new Subject();
1340
        	subject.setValue(accessDAO.getPrincipalName());
1341
        	accessRule.addSubject(subject);
1342
        }
1343
        AccessPolicy accessPolicy = new AccessPolicy();
1344
        accessPolicy.addAllow(accessRule);
1345
        return accessPolicy;
1346
    }
1347
    
1348
    public int convertPermission(Permission permission) {
1349
    	if (permission.equals(Permission.READ)) {
1350
    		return AccessControlInterface.READ;
1351
    	}
1352
    	if (permission.equals(Permission.WRITE)) {
1353
    		return AccessControlInterface.WRITE;
1354
    	}
1355
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1356
    		return AccessControlInterface.CHMOD;
1357
    	}
1358
		return -1;
1359
    }
1360
    
1361
    public Permission convertPermission(int permission) {
1362
    	if (permission == AccessControlInterface.READ) {
1363
    		return Permission.READ;
1364
    	}
1365
    	if (permission == AccessControlInterface.WRITE) {
1366
    		return Permission.WRITE;
1367
    	}
1368
    	if (permission == AccessControlInterface.CHMOD) {
1369
    		return Permission.CHANGE_PERMISSION;
1370
    	}
1371
		return null;
1372
    }
1373
    
1374
    /**
1375
     * Lookup a localId given the GUID. If
1376
     * the identifier is not found, throw an exception.
1377
     * 
1378
     * @param guid the global identifier to look up
1379
     * @return String containing the corresponding LocalId
1380
     * @throws McdbDocNotFoundException if the identifier is not found
1381
     */
1382
    public String getLocalId(String guid) throws McdbDocNotFoundException {
1383
      
1384
      String db_guid = "";
1385
      String docid = "";
1386
      int rev = 0;
1387
      
1388
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1389
      
1390
      DBConnection dbConn = null;
1391
      int serialNumber = -1;
1392
      try {
1393
          // Get a database connection from the pool
1394
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1395
          serialNumber = dbConn.getCheckOutSerialNumber();
1396
          
1397
          // Execute the insert statement
1398
          PreparedStatement stmt = dbConn.prepareStatement(query);
1399
          stmt.setString(1, guid);
1400
          ResultSet rs = stmt.executeQuery();
1401
          if (rs.next()) {
1402
              db_guid = rs.getString(1);
1403
              docid = rs.getString(2);
1404
              rev = rs.getInt(3);
1405
              assert(db_guid.equals(guid));
1406
          } else {
1407
              throw new McdbDocNotFoundException("Document not found:" + guid);
1408
          }
1409
          stmt.close();
1410
      } catch (SQLException e) {
1411
          logMetacat.error("Error while looking up the local identifier: " 
1412
                  + e.getMessage());
1413
      } finally {
1414
          // Return database connection to the pool
1415
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1416
      }
1417
      return docid + "." + rev;
1418
    }
1419
    
1420
    /**
1421
     * query the systemmetadata table based on the given parameters
1422
     * @param startTime
1423
     * @param endTime
1424
     * @param objectFormat
1425
     * @param replicaStatus
1426
     * @param start
1427
     * @param count
1428
     * @return ObjectList
1429
     * @throws SQLException 
1430
     * @throws ServiceException 
1431
     * @throws PropertyNotFoundException 
1432
     */
1433
    public ObjectList querySystemMetadata(Date startTime, Date endTime, 
1434
            ObjectFormatIdentifier objectFormatId, boolean replicaStatus, int start, int count) throws SQLException, PropertyNotFoundException, ServiceException
1435
    {
1436
        ObjectList ol = new ObjectList();
1437
        int total = 0;
1438
        DBConnection dbConn = null;
1439
        int serialNumber = -1;
1440
        
1441
        try {
1442
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
1443
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
1444
                "date_modified, submitter, object_format, size from systemmetadata";
1445
            
1446
            boolean f1 = false;
1447
            boolean f2 = false;
1448
            boolean f3 = false;
1449
            
1450
            if (startTime != null) {
1451
                sql += " where systemmetadata.date_modified > ?";
1452
                f1 = true;
1453
            }
1454
            
1455
            if (endTime != null) {
1456
                if (!f1) {
1457
                    sql += " where systemmetadata.date_modified < ?";
1458
                }
1459
                else {
1460
                    sql += " and systemmetadata.date_modified < ?";
1461
                }
1462
                f2 = true;
1463
            }
1464
            
1465
            if (objectFormatId != null) {
1466
                if (!f1 && !f2) {
1467
                    sql += " where object_format = ?";
1468
                }
1469
                else {
1470
                    sql += " and object_format = ?";
1471
                }
1472
                f3 = true;
1473
            }
1474
            
1475
            if (replicaStatus) {
1476
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
1477
                if (!f1 && !f2 && !f3) {
1478
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
1479
                }
1480
                else {
1481
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
1482
                }
1483
            }
1484
            
1485
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1486
            serialNumber = dbConn.getCheckOutSerialNumber();
1487
            PreparedStatement stmt = dbConn.prepareStatement(sql);
1488
            
1489
            if (f1 && f2 && f3) {
1490
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1491
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1492
                stmt.setString(3, objectFormatId.getValue());
1493
            }
1494
            else if (f1 && f2 && !f3) {
1495
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1496
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1497
            }
1498
            else if (f1 && !f2 && f3) {
1499
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1500
                stmt.setString(2, objectFormatId.getValue());
1501
            }
1502
            else if (f1 && !f2 && !f3) {
1503
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1504
            }
1505
            else if (!f1 && f2 && f3) {
1506
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1507
                stmt.setString(2, objectFormatId.getValue());
1508
            }
1509
            else if (!f1 && !f2 && f3) {
1510
                stmt.setString(1, objectFormatId.getValue());
1511
            }
1512
            else if (!f1 && f2 && !f3) {
1513
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1514
            }
1515
            
1516
            //logMetacat.debug("LISTOBJECTS QUERY: " + stmt.toString());
1517
            
1518
            ResultSet rs = stmt.executeQuery();
1519
            for (int i=0; i<start; i++) {
1520
                if (rs.next()) {
1521
                    total++;
1522
                } else {
1523
                    break;
1524
                }
1525
            }
1526
            
1527
            int countIndex = 0;
1528
                        
1529
            while (rs.next()) {
1530
                total++;
1531
                if (countIndex >= count) {
1532
                	// allow unlimited (negative number for count)
1533
                	if (count > 0) {
1534
                		break;
1535
                	}
1536
                }
1537
                                
1538
                String guid = rs.getString(1);
1539
                //logMetacat.debug("query found doc with guid " + guid);
1540
                //Timestamp dateUploaded = rs.getTimestamp(2);
1541
                //String rightsHolder = rs.getString(3);
1542
                String checksum = rs.getString(4);
1543
                String checksumAlgorithm = rs.getString(5);
1544
                //String originMemberNode = rs.getString(6);
1545
                //String authoritiveMemberNode = rs.getString(7);
1546
                Timestamp dateModified = rs.getTimestamp(8);
1547
                //String submitter = rs.getString(9);
1548
                String fmtidStr = rs.getString(10);
1549
                String sz = rs.getString(11);
1550
                long size = 0;
1551
                
1552
                if (sz != null && !sz.trim().equals("")) {
1553
                    size = new Long(rs.getString(11)).longValue();
1554
                }
1555
                
1556
                ObjectInfo oi = new ObjectInfo();
1557
                
1558
                Identifier id = new Identifier();
1559
                id.setValue(guid);
1560
                oi.setIdentifier(id);
1561
                
1562
                if (dateModified != null) {
1563
                	oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
1564
                }
1565
                
1566
                Checksum cs = new Checksum();
1567
                cs.setValue(checksum);
1568
                try {
1569
                	cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1570
                    //cs.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
1571
                } catch (Exception e) {
1572
					logMetacat.warn("could not parse checksum algorithm", e);
1573
				}
1574
                oi.setChecksum(cs);
1575
                
1576
                try {
1577
	                oi.setObjectFormat(ObjectFormatCache.getInstance().getFormat(fmtidStr));
1578
                } catch (NotFound e) {
1579
                	logMetacat.warn("could not find object format: " + fmtidStr, e);
1580
				}
1581
                                
1582
                oi.setSize(size);
1583
                
1584
                ol.addObjectInfo(oi);
1585
                countIndex++;
1586
            }
1587
            
1588
            // expend the resultset to get the total count of possible rows
1589
            while (rs.next()) { 
1590
                total++;
1591
            }
1592
        }
1593
        
1594
        finally {
1595
            // Return database connection to the pool
1596
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1597
        }
1598
        
1599
        ol.setStart(start);
1600
        ol.setCount(ol.sizeObjectInfoList());
1601
        ol.setTotal(total);
1602
        
1603
        return ol;
1604
    }
1605
    
1606
    /**
1607
     * create a mapping in the identifier table
1608
     * @param guid
1609
     * @param localId
1610
     */
1611
    public void createMapping(String guid, String localId)
1612
    {        
1613
        
1614
        int serialNumber = -1;
1615
        DBConnection dbConn = null;
1616
        try {
1617

    
1618
            // Parse the localId into scope and rev parts
1619
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1620
            String docid = acc.getDocid();
1621
            int rev = 1;
1622
            if (acc.getRev() != null) {
1623
              rev = (new Integer(acc.getRev()).intValue());
1624
            }
1625

    
1626
            // Get a database connection from the pool
1627
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1628
            serialNumber = dbConn.getCheckOutSerialNumber();
1629

    
1630
            // Execute the insert statement
1631
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1632
            PreparedStatement stmt = dbConn.prepareStatement(query);
1633
            stmt.setString(1, guid);
1634
            stmt.setString(2, docid);
1635
            stmt.setInt(3, rev);
1636
            logMetacat.debug("mapping query: " + stmt.toString());
1637
            int rows = stmt.executeUpdate();
1638

    
1639
            stmt.close();
1640
        } catch (SQLException e) {
1641
            e.printStackTrace();
1642
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1643
                    + e.getMessage());
1644
        } catch (NumberFormatException e) {
1645
            e.printStackTrace();
1646
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1647
                    + e.getMessage());
1648
        } catch (AccessionNumberException e) {
1649
            e.printStackTrace();
1650
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1651
                    + e.getMessage());
1652
        } finally {
1653
            // Return database connection to the pool
1654
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1655
        }
1656
    }
1657
    
1658
    /**
1659
     * create the systemmetadata record
1660
     * @param guid
1661
     */
1662
    private void insertSystemMetadata(String guid)
1663
    {        
1664
        
1665
        int serialNumber = -1;
1666
        DBConnection dbConn = null;
1667
        try {
1668

    
1669
            // Get a database connection from the pool
1670
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1671
            serialNumber = dbConn.getCheckOutSerialNumber();
1672

    
1673
            // Execute the insert statement
1674
            String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1675
            PreparedStatement stmt = dbConn.prepareStatement(query);
1676
            stmt.setString(1, guid);
1677
            logMetacat.debug("system metadata query: " + stmt.toString());
1678
            int rows = stmt.executeUpdate();
1679

    
1680
            stmt.close();
1681
        } catch (Exception e) {
1682
            e.printStackTrace();
1683
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1684
        } finally {
1685
            // Return database connection to the pool
1686
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1687
        }
1688
    }
1689
    
1690
    private void deleteSystemMetadata(String guid)
1691
    {        
1692
        
1693
        int serialNumber = -1;
1694
        DBConnection dbConn = null;
1695
        try {
1696

    
1697
            // Get a database connection from the pool
1698
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1699
            serialNumber = dbConn.getCheckOutSerialNumber();
1700

    
1701
            // Execute the statement
1702
            String query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
1703
            PreparedStatement stmt = dbConn.prepareStatement(query);
1704
            stmt.setString(1, guid);
1705
            logMetacat.debug("delete system metadata: " + stmt.toString());
1706
            int rows = stmt.executeUpdate();
1707

    
1708
            stmt.close();
1709
        } catch (Exception e) {
1710
            e.printStackTrace();
1711
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1712
        } finally {
1713
            // Return database connection to the pool
1714
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1715
        }
1716
    }
1717
}
1718

    
(37-37/65)