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.math.BigInteger;
28
import java.sql.PreparedStatement;
29
import java.sql.ResultSet;
30
import java.sql.SQLException;
31
import java.sql.Timestamp;
32
import java.util.ArrayList;
33
import java.util.Date;
34
import java.util.Hashtable;
35
import java.util.List;
36
import java.util.Vector;
37

    
38
import org.apache.log4j.Logger;
39
import org.dataone.client.v2.formats.ObjectFormatCache;
40
import org.dataone.service.exceptions.BaseException;
41
import org.dataone.service.exceptions.InvalidSystemMetadata;
42
import org.dataone.service.types.v1.AccessPolicy;
43
import org.dataone.service.types.v1.AccessRule;
44
import org.dataone.service.types.v1.Checksum;
45
import org.dataone.service.types.v1.Identifier;
46
import org.dataone.service.types.v1.NodeReference;
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.v2.SystemMetadata;
56

    
57
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
58
import edu.ucsb.nceas.metacat.database.DBConnection;
59
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
60
import edu.ucsb.nceas.metacat.database.DatabaseService;
61
import edu.ucsb.nceas.metacat.properties.PropertyService;
62
import edu.ucsb.nceas.metacat.shared.AccessException;
63
import edu.ucsb.nceas.metacat.shared.ServiceException;
64
import edu.ucsb.nceas.metacat.util.DocumentUtil;
65
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
66
import edu.ucsb.nceas.utilities.access.AccessControlInterface;
67
import edu.ucsb.nceas.utilities.access.XMLAccessDAO;
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, BigInteger size, BigInteger serialVersion) {
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);
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
        ObjectFormatIdentifier fmtid = null;
137
        try {
138
        	ObjectFormatIdentifier formatId = new ObjectFormatIdentifier();
139
        	formatId.setValue(fmtidStr);
140
        	fmtid = ObjectFormatCache.getInstance().getFormat(formatId).getFormatId();
141
        	sysMeta.setFormatId(fmtid);
142
        	
143
        } catch (BaseException nfe) {
144
            logMetacat.error("The objectFormat " + fmtidStr +
145
          	" is not registered. Setting the default format id.");
146
            fmtid = new ObjectFormatIdentifier();
147
            fmtid.setValue("application/octet-stream");
148
            sysMeta.setFormatId(fmtid);
149
            
150
        }
151
        sysMeta.setSize(size);
152
        sysMeta.setSerialVersion(serialVersion);
153
        
154
        return sysMeta;
155
    }
156
    
157
    /**
158
     * return a hash of all of the info that is in the systemmetadata table
159
     * @param localId
160
     * @return
161
     */
162
    public Hashtable<String, String> getSystemMetadataInfo(String localId)
163
    throws McdbDocNotFoundException
164
    {
165
        try
166
        {
167
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
168
            localId = acc.getDocid();
169
        }
170
        catch(Exception e)
171
        {
172
            //do nothing. just try the localId as it is
173
        }
174
        Hashtable<String, String> h = new Hashtable<String, String>();
175
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
176
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size " +
177
          "from systemmetadata where docid = ?";
178
        DBConnection dbConn = null;
179
        int serialNumber = -1;
180
        try 
181
        {
182
            // Get a database connection from the pool
183
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
184
            serialNumber = dbConn.getCheckOutSerialNumber();
185

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

    
262
        try 
263
        {
264
            // Get a database connection from the pool
265
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getSystemMetadata");
266
            serialNumber = dbConn.getCheckOutSerialNumber();
267

    
268
            // Execute the statement
269
            PreparedStatement stmt = dbConn.prepareStatement(sql);
270
            stmt.setString(1, guid);
271
            ResultSet rs = stmt.executeQuery();
272
            if (rs.next()) 
273
            {
274
                Timestamp dateUploaded = rs.getTimestamp(2);
275
                String rightsHolder = rs.getString(3);
276
                String checksum = rs.getString(4);
277
                String checksumAlgorithm = rs.getString(5);
278
                String originMemberNode = rs.getString(6);
279
                String authoritativeMemberNode = rs.getString(7);
280
                Timestamp dateModified = rs.getTimestamp(8);
281
                String submitter = rs.getString(9);
282
                String fmtidStr = rs.getString(10);
283
                BigInteger size = new BigInteger(rs.getString(11));
284
                replicationAllowed = new Boolean(rs.getBoolean(12));
285
                numberOfReplicas = new BigInteger(rs.getString(13));
286
                String obsoletes = rs.getString(14);
287
                String obsoletedBy = rs.getString(15);
288
                serialVersion = new BigInteger(rs.getString(16));
289
                archived = new Boolean(rs.getBoolean(17));
290
                String series_id = rs.getString(18);
291

    
292
                Identifier sysMetaId = new Identifier();
293
                sysMetaId.setValue(guid);
294
                sysMeta.setIdentifier(sysMetaId);
295
                sysMeta.setSerialVersion(serialVersion);
296
                sysMeta.setDateUploaded(dateUploaded);
297
                Subject rightsHolderSubject = new Subject();
298
                rightsHolderSubject.setValue(rightsHolder);
299
                sysMeta.setRightsHolder(rightsHolderSubject);
300
                Checksum checksumObject = new Checksum();
301
                checksumObject.setValue(checksum);
302
                checksumObject.setAlgorithm(checksumAlgorithm);
303
                sysMeta.setChecksum(checksumObject);
304
                if (originMemberNode != null) {
305
	                NodeReference omn = new NodeReference();
306
	                omn.setValue(originMemberNode);
307
	                sysMeta.setOriginMemberNode(omn);
308
                }
309
                if (authoritativeMemberNode != null) {
310
	                NodeReference amn = new NodeReference();
311
	                amn.setValue(authoritativeMemberNode);
312
	                sysMeta.setAuthoritativeMemberNode(amn);
313
                }
314
                sysMeta.setDateSysMetadataModified(dateModified);
315
                if (submitter != null) {
316
	                Subject submitterSubject = new Subject();
317
	                submitterSubject.setValue(submitter);
318
	                sysMeta.setSubmitter(submitterSubject);
319
                }
320
                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
321
                fmtid.setValue(fmtidStr);
322
            	sysMeta.setFormatId(fmtid);
323
                sysMeta.setSize(size);
324
                if (obsoletes != null) {
325
	                Identifier obsoletesId = new Identifier();
326
	                obsoletesId.setValue(obsoletes);
327
	                sysMeta.setObsoletes(obsoletesId);
328
                }
329
                if (obsoletedBy != null) {
330
		            Identifier obsoletedById = new Identifier();
331
		            obsoletedById.setValue(obsoletedBy);
332
		            sysMeta.setObsoletedBy(obsoletedById);
333
                }
334
                sysMeta.setArchived(archived);
335
                if(series_id != null) {
336
                    Identifier seriesId = new Identifier();
337
                    seriesId.setValue(series_id);
338
                    sysMeta.setSeriesId(seriesId);
339
                }
340
                stmt.close();
341
            } 
342
            else
343
            {
344
                stmt.close();
345
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
346
                throw new McdbDocNotFoundException("Could not find " + guid);
347
            }
348
            
349
        } 
350
        catch (SQLException e) 
351
        {
352
            e.printStackTrace();
353
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "  
354
                    + e.getMessage());
355
        } 
356
        finally 
357
        {
358
            // Return database connection to the pool
359
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
360
        }
361

    
362
        // populate the replication policy
363
        ReplicationPolicy replicationPolicy = new ReplicationPolicy();
364
        if ( numberOfReplicas != null  && numberOfReplicas.intValue() != -1 ) {
365
            replicationPolicy.setNumberReplicas(numberOfReplicas.intValue());
366
            
367
        }
368
        
369
        if ( replicationAllowed != null ) {
370
            replicationPolicy.setReplicationAllowed(replicationAllowed);
371
            
372
        }
373
        replicationPolicy.setBlockedMemberNodeList(getReplicationPolicy(guid, "blocked"));
374
        replicationPolicy.setPreferredMemberNodeList(getReplicationPolicy(guid, "preferred"));
375
		    sysMeta.setReplicationPolicy(replicationPolicy);
376
		
377
		    // look up replication status
378
		    sysMeta.setReplicaList(getReplicationStatus(guid));
379
		
380
		    // look up access policy
381
		    try {
382
		    	sysMeta.setAccessPolicy(getAccessPolicy(guid));
383
		    } catch (AccessException e) {
384
		    	throw new McdbDocNotFoundException(e);
385
		    }
386
        
387
        return sysMeta;
388
    }
389
    
390
    
391
    private List<NodeReference> getReplicationPolicy(String guid, String policy)
392
		throws McdbDocNotFoundException {
393
		
394
		List<NodeReference> nodes = new ArrayList<NodeReference>();
395
		String sql = "select guid, policy, member_node " +
396
			"from smReplicationPolicy where guid = ? and policy = ?";
397
	    DBConnection dbConn = null;
398
	    int serialNumber = -1;
399
	    try {
400
	        // Get a database connection from the pool
401
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicationPolicy");
402
	        serialNumber = dbConn.getCheckOutSerialNumber();
403
	
404
	        // Execute the statement
405
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
406
	        stmt.setString(1, guid);
407
	        stmt.setString(2, policy);
408
	        ResultSet rs = stmt.executeQuery();
409
	        while (rs.next()) 
410
	        {
411
	            String memberNode = rs.getString(3);
412
	            NodeReference node = new NodeReference();
413
	            node.setValue(memberNode);
414
	            nodes.add(node);
415
	        
416
	        } 
417
	        stmt.close();
418
	        
419
	    } catch (SQLException e) {
420
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
421
	    } 
422
	    finally {
423
	        // Return database connection to the pool
424
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
425
	    }
426
	    
427
	    return nodes;
428
	}
429
    
430
    private List<Replica> getReplicationStatus(String guid) throws McdbDocNotFoundException {
431
		
432
		List<Replica> replicas = new ArrayList<Replica>();
433
		String sql = "select guid, member_node, status, date_verified " +
434
			"from smReplicationStatus where guid = ?";
435
	    DBConnection dbConn = null;
436
	    int serialNumber = -1;
437
	    try {
438
	        // Get a database connection from the pool
439
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicas");
440
	        serialNumber = dbConn.getCheckOutSerialNumber();
441
	
442
	        // Execute the statement
443
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
444
	        stmt.setString(1, guid);
445
	        ResultSet rs = stmt.executeQuery();
446
	        while (rs.next()) 
447
	        {
448
	            String memberNode = rs.getString(2);
449
	            String status = rs.getString(3);
450
	            java.sql.Timestamp verified = rs.getTimestamp(4);
451
	            
452
	            Replica replica = new Replica();	            
453
	            NodeReference node = new NodeReference();
454
	            node.setValue(memberNode);
455
	            replica.setReplicaMemberNode(node);
456
	            replica.setReplicationStatus(ReplicationStatus.valueOf(status));
457
	            replica.setReplicaVerified(new Date(verified.getTime()));
458
	            replicas.add(replica);
459
	        } 
460
	        stmt.close();
461
	        
462
	    } catch (SQLException e) {
463
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
464
	    } 
465
	    finally {
466
	        // Return database connection to the pool
467
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
468
	    }
469
	    
470
	    return replicas;
471
	}
472
    
473
    
474
    /**
475
     * return the newest rev for a given localId
476
     * @param localId
477
     * @return
478
     */
479
    public int getLatestRevForLocalId(String localId)
480
        throws McdbDocNotFoundException
481
    {
482
        try
483
        {
484
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
485
            localId = acc.getDocid();
486
        }
487
        catch(Exception e)
488
        {
489
            //do nothing. just try the localId as it is
490
        }
491
        int rev = 0;
492
        String sql = "select rev from xml_documents where docid like ? ";
493
        DBConnection dbConn = null;
494
        int serialNumber = -1;
495
        try 
496
        {
497
            // Get a database connection from the pool
498
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLatestRevForLocalId");
499
            serialNumber = dbConn.getCheckOutSerialNumber();
500

    
501
            // Execute the insert statement
502
            PreparedStatement stmt = dbConn.prepareStatement(sql);
503
            stmt.setString(1, localId);
504
            ResultSet rs = stmt.executeQuery();
505
            if (rs.next()) 
506
            {
507
                rev = rs.getInt(1);
508
                stmt.close();
509
            } 
510
            else
511
            {
512
                stmt.close();
513
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
514
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
515
            }
516
        } 
517
        catch (SQLException e) 
518
        {
519
            logMetacat.error("Error while looking up the guid: " 
520
                    + e.getMessage());
521
        } 
522
        finally 
523
        {
524
            // Return database connection to the pool
525
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
526
        }
527
        return rev;
528
    }
529
    
530
    /**
531
     * return all local ids in the object store that do not have associated
532
     * system metadata
533
     */
534
    public List<String> getLocalIdsWithNoSystemMetadata(boolean includeRevisions, int serverLocation)
535
    {
536
        Vector<String> ids = new Vector<String>();
537
        String sql = "select docid, rev from xml_documents " +
538
        		"where docid not in " +
539
        		"(select docid from identifier where guid in (select guid from systemmetadata))";
540
        if (serverLocation > 0) {
541
        	sql = sql + " and server_location = ? ";
542
        }
543
        
544
        String revisionSql = "select docid, rev from xml_revisions " +
545
				"where docid not in " +
546
				"(select docid from identifier where guid in (select guid from systemmetadata))";
547
        if (serverLocation > 0) {
548
        	revisionSql = revisionSql + " and server_location = ? ";
549
        }
550
        
551
        if (includeRevisions) {
552
        	sql = sql + " UNION ALL " + revisionSql;
553
        }
554
        
555
        DBConnection dbConn = null;
556
        int serialNumber = -1;
557
        try 
558
        {
559
            // Get a database connection from the pool
560
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
561
            serialNumber = dbConn.getCheckOutSerialNumber();
562

    
563
            // Execute the insert statement
564
            PreparedStatement stmt = dbConn.prepareStatement(sql);
565
            // set params based on what we have in the query string
566
            if (serverLocation > 0) {
567
            	stmt.setInt(1, serverLocation);
568
            	if (includeRevisions) {
569
            		stmt.setInt(2, serverLocation);
570
            	}
571
            }
572
            ResultSet rs = stmt.executeQuery();
573
            while (rs.next()) 
574
            {
575
                String localid = rs.getString(1);
576
                String rev = rs.getString(2);
577
                localid += "." + rev;
578
                logMetacat.debug("id to add SM for: " + localid);
579
                ids.add(localid);
580
            } 
581
            stmt.close();
582
        } 
583
        catch (SQLException e) 
584
        {
585
            logMetacat.error("Error while looking up the guid: " 
586
                    + e.getMessage());
587
        } 
588
        finally 
589
        {
590
            // Return database connection to the pool
591
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
592
        }
593
        
594
        return ids;
595
    }
596
    
597
    /**
598
     * return a listing of all local ids in the object store
599
     * @return a list of all local ids in metacat
600
     */
601
    public List<String> getAllLocalIds()
602
    // seems to be an unnecessary and restrictive throw -rnahf 13-Sep-2011
603
    //    throws Exception
604
    {
605
        Vector<String> ids = new Vector<String>();
606
        String sql = "select docid from xml_documents";
607
        DBConnection dbConn = null;
608
        int serialNumber = -1;
609
        try 
610
        {
611
            // Get a database connection from the pool
612
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
613
            serialNumber = dbConn.getCheckOutSerialNumber();
614

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

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

    
702
            // Execute the insert statement
703
            PreparedStatement stmt = dbConn.prepareStatement(sql);
704
            stmt.setDate(1, new java.sql.Date(since.getTime()));
705
            ResultSet rs = stmt.executeQuery();
706
            while (rs.next()) 
707
            {
708
                String guid = rs.getString(1);
709
                ids.add(guid);
710
            } 
711
            stmt.close();
712
        } 
713
        catch (SQLException e) 
714
        {
715
            logMetacat.error("Error while looking up the updated guids: " 
716
                    + e.getMessage());
717
        } 
718
        finally 
719
        {
720
            // Return database connection to the pool
721
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
722
        }
723
        return ids;
724
    }
725
    
726
    /**
727
     * returns a list of system metadata-only guids since the given date
728
     * @return a list of system ids in metacat that do not correspond to objects
729
     * TODO: need to check which server they are on
730
     */
731
    public Date getLastModifiedDate() throws Exception {
732
        Date maxDate = null;
733

    
734
        List<String> ids = new Vector<String>();
735
        String sql = 
736
        	"select max(date_modified) from " + TYPE_SYSTEM_METADATA;
737
        DBConnection dbConn = null;
738
        int serialNumber = -1;
739
        try 
740
        {
741
            // Get a database connection from the pool
742
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLastModifiedDate");
743
            serialNumber = dbConn.getCheckOutSerialNumber();
744

    
745
            // Execute the insert statement
746
            PreparedStatement stmt = dbConn.prepareStatement(sql);
747
            ResultSet rs = stmt.executeQuery();
748
            if (rs.next()) {
749
            	maxDate = rs.getDate(1);
750
            } 
751
            stmt.close();
752
        } 
753
        catch (SQLException e) 
754
        {
755
            logMetacat.error("Error while looking up the latest update date: " 
756
                    + e.getMessage());
757
        } 
758
        finally 
759
        {
760
            // Return database connection to the pool
761
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
762
        }
763
        return maxDate;
764
    }
765

    
766
    
767
    /**
768
     * Determine if an identifier exists already, returning true if so.
769
     * NOTE: looks in the identifier and system metadata table for a match
770
     * (in that order)
771
     * 
772
     * @param guid the global identifier to look up
773
     * @return boolean true if the identifier exists
774
     */
775
    public boolean identifierExists(String guid) throws SQLException
776
    {
777
        boolean idExists = false;
778
        try {
779
            String id = getLocalId(guid);
780
            if (id != null) {
781
                idExists = true;
782
            }
783
        } catch (McdbDocNotFoundException e) {
784
        	// try system metadata only
785
        	    //this will check if the guid field on the system metadata table has the id
786
        		idExists = systemMetadataPIDExists(guid);
787
        		if(!idExists) {
788
        		    //if the guid field of the system metadata table doesn't have the id,
789
        		    //we will check if the serial_id field of the system metadata table has it
790
        		    idExists=systemMetadataSIDExists(guid);
791
        		}
792
            
793
        }
794
        return idExists;
795
    }
796
    
797
    /**
798
     * Determine if an identifier mapping exists already, 
799
     * returning true if so.
800
     * 
801
     * @param guid the global identifier to look up
802
     * @return boolean true if the identifier exists
803
     */
804
    public boolean mappingExists(String guid) throws SQLException
805
    {
806
        boolean idExists = false;
807
        try {
808
            String id = getLocalId(guid);
809
            if (id != null) {
810
                idExists = true;
811
            }
812
        } catch (McdbDocNotFoundException e) {
813
        	// nope!
814
        }
815
        return idExists;
816
    }
817
    
818
    /**
819
     * 
820
     * @param guid
821
     * @param rev
822
     * @return
823
     */
824
    public String generateLocalId(String guid, int rev)
825
    {
826
        return generateLocalId(guid, rev, false);
827
    }
828

    
829
    /**
830
     * Given a global identifier (guid), create a suitable local identifier that
831
     * follows Metacat's docid semantics and format (scope.id.rev), and create
832
     * a mapping between these two identifiers.  This effectively reserves both
833
     * the global and the local identifier, as they will now be present in the
834
     * identifier mapping table.  
835
     * 
836
     * REMOVED feature: If the incoming guid has the syntax of a
837
     * Metacat docid (scope.id.rev), then simply use it.
838
     * WHY: because "test.1.001" becomes "test.1.1" which is not correct for DataONE
839
     * identifier use (those revision numbers are just chartacters and should not be interpreted)
840
     * 
841
     * @param guid the global string identifier
842
     * @param rev the revision number to be used in the localId
843
     * @return String containing the localId to be used for Metacat operations
844
     */
845
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata) 
846
    {
847
        String localId = "";
848
        boolean conformsToDocidFormat = false;
849
        
850
        // BRL -- do not allow Metacat-conforming IDs to be used:
851
        // test.1.001 becomes test.1.1 which is NOT correct for DataONE identifiers
852
        // Check if the guid passed in is already in docid (scope.id.rev) format
853
//        try {
854
//            AccessionNumber acc = new AccessionNumber(guid, "NONE");
855
//            if (new Integer(acc.getRev()).intValue() > 0) {
856
//                conformsToDocidFormat = true;
857
//            }
858
//        } catch (NumberFormatException e) {
859
//            // No action needed, simply detecting invalid AccessionNumbers
860
//        } catch (AccessionNumberException e) {
861
//            // No action needed, simply detecting invalid AccessionNumbers
862
//        } catch (SQLException e) {
863
//            // No action needed, simply detecting invalid AccessionNumbers
864
//        }
865
        
866
        if (conformsToDocidFormat) {
867
            // if it conforms, use it for both guid and localId
868
            localId = guid;
869
        } else {
870
            // if not, then generate a new unique localId
871
            localId = DocumentUtil.generateDocumentId(rev);
872
        }
873
        
874
        // Register this new pair in the identifier mapping table
875
        logMetacat.debug("creating mapping in generateLocalId");
876
        if(!isSystemMetadata)
877
        { //don't do this if we're generating for system metadata
878
            createMapping(guid, localId);
879
        }
880
        
881
        return localId;
882
    }
883
    
884
    /**
885
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
886
     * if the docid, rev is not found in the identifiers or systemmetadata tables
887
     *
888
     * @param docid the docid to look up
889
     * @param rev the revision of the docid to look up
890
     * @return String containing the mapped guid
891
     * @throws McdbDocNotFoundException if the docid, rev is not found
892
     */
893
    public String getGUID(String docid, int rev)
894
      throws McdbDocNotFoundException
895
    {
896
        logMetacat.debug("getting guid for " + docid);
897
        String query = "select guid from identifier where docid = ? and rev = ?";
898
        String guid = null;
899
        
900
        DBConnection dbConn = null;
901
        int serialNumber = -1;
902
        try {
903
            // Get a database connection from the pool
904
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
905
            serialNumber = dbConn.getCheckOutSerialNumber();
906
            
907
            // Execute the insert statement
908
            PreparedStatement stmt = dbConn.prepareStatement(query);
909
            stmt.setString(1, docid);
910
            stmt.setInt(2, rev);
911
            ResultSet rs = stmt.executeQuery();
912
            if (rs.next()) 
913
            {
914
                guid = rs.getString(1);
915
            } 
916
            else
917
            {
918
            	throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
919
            }
920
            
921
        } catch (SQLException e) {
922
            logMetacat.error("Error while looking up the guid: " 
923
                    + e.getMessage());
924
        } finally {
925
            // Return database connection to the pool
926
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
927
        }
928
        
929
        return guid;
930
    }
931
    
932
    /**
933
     * Get the pid of the head (current) version of objects match the specified sid.
934
     * DataONE defines the latest version as "current" if the object in question has 
935
     * a matching SID and no value in the "obsoletedBy" field, regardless if it is "archived" or not.
936
     * If we can't find any pid associated with the sid doesn't have a value in obsoletedBy field, 
937
     * the pid associated with the sid  which has the max date_uploaded will be returned
938
     * @param sid specified sid which should match.
939
     * @return the pid of the head version. The null will be returned if there is no pid found.
940
     * @throws SQLException 
941
     */
942
    public Identifier getHeadPID(Identifier sid) throws SQLException {
943
        Identifier pid = null;
944
        if(sid != null && sid.getValue() != null && !sid.getValue().trim().equals("")) {
945
            logMetacat.debug("getting pid of the head version for matching the sid: " + sid.getValue());
946
            String sql = "select guid from systemMetadata where obsoleted_by is null and series_id = ?";
947
            DBConnection dbConn = null;
948
            int serialNumber = -1;
949
            try {
950
                // Get a database connection from the pool
951
                dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getHeadPID");
952
                serialNumber = dbConn.getCheckOutSerialNumber();
953
                // Execute the insert statement
954
                PreparedStatement stmt = dbConn.prepareStatement(sql);
955
                stmt.setString(1, sid.getValue());
956
                ResultSet rs = stmt.executeQuery();
957
                if (rs.next()) 
958
                {
959
                    pid = new Identifier();
960
                    pid.setValue(rs.getString(1));
961
                   
962
                } else {
963
                    //we don't find any pid associated with the sid doesn't have value in obsoletedBy field.
964
                    //The pid associated with the sid  which has the max date_uploaded will be returned.
965
                    sql = "select guid from systemMetadata where series_id = ? and date_uploaded=(select max(date_uploaded) from systemMetadata where series_id = ?)";
966
                    stmt = dbConn.prepareStatement(sql);
967
                    stmt.setString(1, sid.getValue());
968
                    stmt.setString(2, sid.getValue());
969
                    rs = stmt.executeQuery();
970
                    if(rs.next()) {
971
                        pid = new Identifier();
972
                        pid.setValue(rs.getString(1));
973
                    }
974
                }
975
                
976
            } catch (SQLException e) {
977
                logMetacat.error("Error while get the head pid for the sid "+sid.getValue()+" : " 
978
                        + e.getMessage());
979
                throw e;
980
            } finally {
981
                // Return database connection to the pool
982
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
983
            }
984
        }
985
        return pid;
986
    }
987
    
988
    /**
989
     * Check if the specified sid object exists on the serial id field on the system metadata table
990
     * @param sid
991
     * @return true if it exists; false otherwise.
992
     * @throws SQLException
993
     */
994
    public boolean systemMetadataSIDExists(Identifier sid) throws SQLException {
995
        if (sid != null && sid.getValue() != null && !sid.getValue().trim().equals("")) {
996
            return systemMetadataSIDExists(sid.getValue());
997
        } else {
998
            return false;
999
        }
1000
    }
1001
    
1002
    /**
1003
     * Check if the specified sid exists on the serial id field on the system metadata table
1004
     * @param id
1005
     * @return true if it exists; false otherwise.
1006
     */
1007
    public boolean systemMetadataSIDExists(String sid) throws SQLException {
1008
        boolean exists = false;
1009
        logMetacat.debug("Check if the  sid: " + sid +" exists on the series_id field of the system metadata table.");
1010
        if(sid != null && !sid.trim().equals("")) {
1011
            String sql = "select guid from systemMetadata where series_id = ?";
1012
            DBConnection dbConn = null;
1013
            int serialNumber = -1;
1014
            try {
1015
                // Get a database connection from the pool
1016
                dbConn = DBConnectionPool.getDBConnection("IdentifierManager.serialIdExists");
1017
                serialNumber = dbConn.getCheckOutSerialNumber();
1018
                // Execute the insert statement
1019
                PreparedStatement stmt = dbConn.prepareStatement(sql);
1020
                stmt.setString(1, sid);
1021
                ResultSet rs = stmt.executeQuery();
1022
                if (rs.next()) 
1023
                {
1024
                    exists = true;
1025
                } 
1026
                
1027
            } catch (SQLException e) {
1028
                logMetacat.error("Error while checking if the sid "+sid+" exists on the series_id field of the system metadata table: " 
1029
                        + e.getMessage());
1030
                throw e;
1031
            } finally {
1032
                // Return database connection to the pool
1033
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1034
            }
1035
        }
1036
        return exists;
1037
    }
1038
    
1039
    /**
1040
     * Determine if the specified identifier object exists or not.
1041
     * @param pid - the specified identifier
1042
     * @return true if it is exists.
1043
     * @throws SQLException
1044
     * @throws NullPointerException
1045
     */
1046
    public boolean systemMetadataPIDExists(Identifier pid) throws SQLException {
1047
        if (pid != null && pid.getValue() != null && !pid.getValue().trim().equals("")) {
1048
            return systemMetadataPIDExists(pid.getValue());
1049
        } else {
1050
            return false;
1051
        }
1052
    }
1053
    
1054
    public boolean systemMetadataPIDExists(String guid) throws SQLException {
1055
		logMetacat.debug("looking up system metadata for guid " + guid);
1056
		boolean exists = false;
1057
		String query = "select guid from systemmetadata where guid = ?";
1058
		DBConnection dbConn = null;
1059
		int serialNumber = -1;
1060
		if(guid != null && !guid.trim().equals("")) {
1061
		    try {
1062
	            // Get a database connection from the pool
1063
	            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
1064
	            serialNumber = dbConn.getCheckOutSerialNumber();
1065

    
1066
	            // Execute the insert statement
1067
	            PreparedStatement stmt = dbConn.prepareStatement(query);
1068
	            stmt.setString(1, guid);
1069
	            ResultSet rs = stmt.executeQuery();
1070
	            if (rs.next()) {
1071
	                exists = true;
1072
	            }
1073

    
1074
	        } catch (SQLException e) {
1075
	            logMetacat.error("Error while looking up the system metadata: "
1076
	                    + e.getMessage());
1077
	            throw e;
1078
	        } finally {
1079
	            // Return database connection to the pool
1080
	            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1081
	        }
1082
		}
1083
		return exists;
1084
	}
1085
    
1086
    /**
1087
     * creates a system metadata mapping and adds additional fields from sysmeta
1088
     * to the table for quick searching.
1089
     * 
1090
     * @param guid the id to insert
1091
     * @param localId the systemMetadata object to get the local id for
1092
     * @throws McdbDocNotFoundException 
1093
     * @throws SQLException 
1094
     * @throws InvalidSystemMetadata 
1095
     */
1096
    public void insertOrUpdateSystemMetadata(SystemMetadata sysmeta) 
1097
        throws McdbDocNotFoundException, SQLException, InvalidSystemMetadata {
1098
    	String guid = sysmeta.getIdentifier().getValue();
1099
    	
1100
    	 // Get a database connection from the pool
1101
        DBConnection dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1102
        int serialNumber = dbConn.getCheckOutSerialNumber();
1103
        
1104
        try {
1105
        	// use a single transaction for it all
1106
        	dbConn.setAutoCommit(false);
1107
        	
1108
	    	// insert the record if needed
1109
        	if (!IdentifierManager.getInstance().systemMetadataPIDExists(guid)) {
1110
    	        insertSystemMetadata(guid, dbConn);
1111
			}
1112
	        // update with the values
1113
	        updateSystemMetadata(sysmeta, dbConn);
1114
	        
1115
	        // commit if we got here with no errors
1116
	        dbConn.commit();
1117
        } catch (Exception e) {
1118
            e.printStackTrace();
1119
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1120
            dbConn.rollback();
1121
        } finally {
1122
            // Return database connection to the pool
1123
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1124
        }
1125
        
1126
        
1127
    }
1128
        
1129
    
1130
    /**
1131
     * update a mapping
1132
     * @param guid
1133
     * @param localId
1134
     */
1135
    public void updateMapping(String guid, String localId)
1136
    {
1137
    	
1138
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
1139
        int serialNumber = -1;
1140
        DBConnection dbConn = null;
1141
        try {
1142
            // Parse the localId into scope and rev parts
1143
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1144
            String docid = acc.getDocid();
1145
            int rev = 1;
1146
            if(acc.getRev() != null)
1147
            {
1148
              rev = (new Integer(acc.getRev()).intValue());
1149
            }
1150

    
1151
            // Get a database connection from the pool
1152
            dbConn = 
1153
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1154
            serialNumber = dbConn.getCheckOutSerialNumber();
1155

    
1156
            // Execute the update statement
1157
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid = ?";
1158
            PreparedStatement stmt = dbConn.prepareStatement(query);
1159
            stmt.setString(1, docid);
1160
            stmt.setInt(2, rev);
1161
            stmt.setString(3, guid);
1162
            int rows = stmt.executeUpdate();
1163

    
1164
            stmt.close();
1165
        } catch (SQLException e) {
1166
            e.printStackTrace();
1167
            logMetacat.error("SQL error while updating a mapping identifier: " 
1168
                    + e.getMessage());
1169
        } catch (NumberFormatException e) {
1170
            e.printStackTrace();
1171
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
1172
                    + e.getMessage());
1173
        } catch (AccessionNumberException e) {
1174
            e.printStackTrace();
1175
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
1176
                    + e.getMessage());
1177
        } finally {
1178
            // Return database connection to the pool
1179
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1180
        }
1181
        logMetacat.debug("done updating mapping");
1182
    }
1183
        
1184
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1185
        String checksum, String checksumAlgorithm, String originMemberNode, 
1186
        String authoritativeMemberNode, long modifiedDate, String submitter, 
1187
        String guid, String objectFormat, BigInteger size, boolean archived,
1188
        boolean replicationAllowed, int numberReplicas, String obsoletes,
1189
        String obsoletedBy, BigInteger serialVersion, String seriesId, DBConnection dbConn) throws SQLException  {
1190
  
1191
        // Execute the insert statement
1192
        String query = "update " + TYPE_SYSTEM_METADATA + 
1193
            " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1194
            "origin_member_node, authoritive_member_node, date_modified, " +
1195
            "submitter, object_format, size, archived, replication_allowed, number_replicas, " +
1196
            "obsoletes, obsoleted_by, serial_version, series_id) " +
1197
            "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1198
        PreparedStatement stmt = dbConn.prepareStatement(query);
1199
        
1200
        //data values
1201
        stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1202
        stmt.setString(2, rightsHolder);
1203
        stmt.setString(3, checksum);
1204
        stmt.setString(4, checksumAlgorithm);
1205
        stmt.setString(5, originMemberNode);
1206
        stmt.setString(6, authoritativeMemberNode);
1207
        stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1208
        stmt.setString(8, submitter);
1209
        stmt.setString(9, objectFormat);
1210
        stmt.setString(10, size.toString());
1211
        stmt.setBoolean(11, archived);
1212
        stmt.setBoolean(12, replicationAllowed);
1213
        stmt.setInt(13, numberReplicas);
1214
        stmt.setString(14, obsoletes);
1215
        stmt.setString(15, obsoletedBy);
1216
        stmt.setString(16, serialVersion.toString());
1217
        stmt.setString(17, seriesId);
1218

    
1219

    
1220
        //where clause
1221
        stmt.setString(18, guid);
1222
        logMetacat.debug("stmt: " + stmt.toString());
1223
        //execute
1224
        int rows = stmt.executeUpdate();
1225

    
1226
        stmt.close();
1227
               
1228
    }
1229
    
1230
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes, DBConnection dbConn) throws SQLException
1231
    {
1232
           
1233
        // remove existing values first
1234
        String delete = "delete from smReplicationPolicy " + 
1235
        "where guid = ? and policy = ?";
1236
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1237
        //data values
1238
        stmt.setString(1, guid);
1239
        stmt.setString(2, policy);
1240
        //execute
1241
        int deletedCount = stmt.executeUpdate();
1242
        stmt.close();
1243
        
1244
        for (String memberNode: memberNodes) {
1245
            // Execute the insert statement
1246
            String insert = "insert into smReplicationPolicy " + 
1247
                "(guid, policy, member_node) " +
1248
                "values (?, ?, ?)";
1249
            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1250
            
1251
            //data values
1252
            insertStatement.setString(1, guid);
1253
            insertStatement.setString(2, policy);
1254
            insertStatement.setString(3, memberNode);
1255
            
1256
            logMetacat.debug("smReplicationPolicy sql: " + insertStatement.toString());
1257

    
1258
            //execute
1259
            int rows = insertStatement.executeUpdate();
1260
            insertStatement.close();
1261
        }
1262
        
1263
    }
1264
    
1265
    private void insertReplicationStatus(String guid, List<Replica> replicas, DBConnection dbConn) throws SQLException {
1266
       
1267
        // remove existing values first
1268
        String delete = "delete from smReplicationStatus " + 
1269
        "where guid = ?";
1270
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1271
        //data values
1272
        stmt.setString(1, guid);
1273
        //execute
1274
        int deletedCount = stmt.executeUpdate();
1275
        stmt.close();
1276
        
1277
        if (replicas != null) {
1278
            for (Replica replica: replicas) {
1279
	            // Execute the insert statement
1280
	            String insert = "insert into smReplicationStatus " + 
1281
	                "(guid, member_node, status, date_verified) " +
1282
	                "values (?, ?, ?, ?)";
1283
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1284
	            
1285
	            //data values
1286
	            String memberNode = replica.getReplicaMemberNode().getValue();
1287
	            String status = replica.getReplicationStatus().toString();
1288
	            java.sql.Timestamp sqlDate = new java.sql.Timestamp(replica.getReplicaVerified().getTime());
1289
	            insertStatement.setString(1, guid);
1290
	            insertStatement.setString(2, memberNode);
1291
	            insertStatement.setString(3, status);
1292
	            insertStatement.setTimestamp(4, sqlDate);
1293

    
1294
	            logMetacat.debug("smReplicationStatus sql: " + insertStatement.toString());
1295
	            
1296
	            //execute
1297
	            int rows = insertStatement.executeUpdate();
1298
	            insertStatement.close();
1299
            }
1300
        }
1301
       
1302
    }
1303
    
1304
    /**
1305
     * Insert the system metadata fields into the db
1306
     * @param sm
1307
     * @throws McdbDocNotFoundException 
1308
     * @throws SQLException 
1309
     * @throws InvalidSystemMetadata 
1310
     * @throws AccessException 
1311
     */
1312
    public void updateSystemMetadata(SystemMetadata sm, DBConnection dbConn) 
1313
      throws McdbDocNotFoundException, SQLException, InvalidSystemMetadata, AccessException {
1314
    	
1315
      Boolean replicationAllowed = false;
1316
		  Integer numberReplicas = -1;
1317
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1318
    	if (replicationPolicy != null) {
1319
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1320
    		numberReplicas = replicationPolicy.getNumberReplicas();
1321
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1322
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1323
    	}
1324
    	
1325
    	// the main systemMetadata fields
1326
		  updateSystemMetadataFields(
1327
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1328
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(), 
1329
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(), 
1330
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm(), 
1331
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1332
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(), 
1333
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1334
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(), 
1335
		    sm.getIdentifier().getValue(),
1336
		    sm.getFormatId() == null ? null: sm.getFormatId().getValue(),
1337
		    sm.getSize(),
1338
		    sm.getArchived() == null ? false: sm.getArchived(),
1339
		    replicationAllowed, 
1340
		    numberReplicas,
1341
		    sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
1342
		    sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue(),
1343
		    sm.getSerialVersion(),
1344
		    sm.getSeriesId() == null ? null: sm.getSeriesId().getValue(),
1345
		    dbConn
1346
        );
1347
        
1348
        String guid = sm.getIdentifier().getValue();
1349
        
1350
        // save replication policies
1351
        if (replicationPolicy != null) {
1352
		    List<String> nodes = null;
1353
		    String policy = null;
1354
		    
1355
		    // check for null 
1356
		    if (replicationPolicy.getBlockedMemberNodeList() != null) {
1357
			    nodes = new ArrayList<String>();
1358
			    policy = "blocked";
1359
			    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1360
			    	nodes.add(node.getValue());
1361
			    }
1362
			    this.insertReplicationPolicy(guid, policy, nodes, dbConn);
1363
		    }
1364
		    
1365
		    if (replicationPolicy.getPreferredMemberNodeList() != null) {
1366
			    nodes = new ArrayList<String>();
1367
			    policy = "preferred";
1368
			    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1369
			    	nodes.add(node.getValue());
1370
			    }
1371
		        this.insertReplicationPolicy(guid, policy, nodes, dbConn);
1372
		    }
1373
        }
1374
        
1375
        // save replica information
1376
        this.insertReplicationStatus(guid, sm.getReplicaList(), dbConn);
1377
        
1378
        // save access policy
1379
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1380
        if (accessPolicy != null) {
1381
			this.insertAccessPolicy(guid, accessPolicy);
1382
        }
1383
    }
1384
    
1385
    /**
1386
     * Creates Metacat access rules and inserts them
1387
     * @param accessPolicy
1388
     * @throws McdbDocNotFoundException
1389
     * @throws AccessException
1390
     */
1391
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1392
    	
1393
    	// check for the existing permOrder so that we remain compatible with it (DataONE does not care)
1394
        XMLAccessAccess accessController  = new XMLAccessAccess();
1395
		String existingPermOrder = AccessControlInterface.ALLOWFIRST;
1396
        Vector<XMLAccessDAO> existingAccess = accessController.getXMLAccessForDoc(guid);
1397
        if (existingAccess != null && existingAccess.size() > 0) {
1398
        	existingPermOrder = existingAccess.get(0).getPermOrder();
1399
        }
1400
        
1401
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1402
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1403
        	List<Subject> subjects = accessRule.getSubjectList();
1404
        	List<Permission> permissions = accessRule.getPermissionList();
1405
        	for (Subject subject: subjects) {
1406
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1407
        		accessDAO.setPrincipalName(subject.getValue());
1408
    			accessDAO.setGuid(guid);
1409
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1410
				accessDAO.setPermOrder(existingPermOrder);
1411
    			if (permissions != null) {
1412
	    			for (Permission permission: permissions) {
1413
	    				Long metacatPermission = new Long(convertPermission(permission));
1414
	        			accessDAO.addPermission(metacatPermission);
1415
	    			}
1416
    			}
1417
    			accessDAOs.add(accessDAO);
1418
        	}
1419
        }
1420
        
1421
        
1422
        // remove all existing allow records
1423
        accessController.deleteXMLAccessForDoc(guid, AccessControlInterface.ALLOW);
1424
        // add the ones we can for this guid
1425
        accessController.insertAccess(guid, accessDAOs);
1426
        
1427
        
1428
    }
1429
    
1430
    /**
1431
     * Lookup access policy from Metacat
1432
     * @param guid
1433
     * @return
1434
     * @throws McdbDocNotFoundException
1435
     * @throws AccessException
1436
     */
1437
    public AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1438
        AccessPolicy accessPolicy = new AccessPolicy();
1439

    
1440
    	// use GUID to look up the access
1441
        XMLAccessAccess accessController  = new XMLAccessAccess();
1442
        List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1443
        
1444
        for (XMLAccessDAO accessDAO: accessDAOs) {
1445
        	// only add allow rule
1446
        	if (accessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
1447
	        	AccessRule accessRule = new AccessRule();    	
1448
	        	List <Permission> permissions = convertPermission(accessDAO.getPermission().intValue());
1449
	        	// cannot include if we have no permissions
1450
	        	if (permissions == null || permissions.isEmpty()) {
1451
	        		logMetacat.warn("skipping empty access rule permissions for " + guid);
1452
	        		continue;
1453
	        	}
1454
	        	accessRule.setPermissionList(permissions);
1455
	        	Subject subject = new Subject();
1456
	        	subject.setValue(accessDAO.getPrincipalName());
1457
	        	accessRule.addSubject(subject);
1458
	            accessPolicy.addAllow(accessRule);
1459
        	}
1460
        }
1461
        return accessPolicy;
1462
    }
1463
    
1464
    public int convertPermission(Permission permission) {
1465
    	if (permission.equals(Permission.READ)) {
1466
    		return AccessControlInterface.READ;
1467
    	}
1468
    	if (permission.equals(Permission.WRITE)) {
1469
    		return AccessControlInterface.WRITE;
1470
    	}
1471
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1472
    		return AccessControlInterface.CHMOD;
1473
    	}
1474
		return -1;
1475
    }
1476
    
1477
    public List<Permission> convertPermission(int permission) {
1478
    	
1479
    	List<Permission> permissions = new ArrayList<Permission>();
1480
    	if (permission == AccessControlInterface.ALL) {
1481
    		permissions.add(Permission.READ);
1482
    		permissions.add(Permission.WRITE);
1483
    		permissions.add(Permission.CHANGE_PERMISSION);
1484
    		return permissions;
1485
    	}
1486
    	
1487
    	if ((permission & AccessControlInterface.CHMOD) == AccessControlInterface.CHMOD) {
1488
    		permissions.add(Permission.CHANGE_PERMISSION);
1489
    	}
1490
    	if ((permission & AccessControlInterface.READ) == AccessControlInterface.READ) {
1491
    		permissions.add(Permission.READ);
1492
    	}
1493
    	if ((permission & AccessControlInterface.WRITE) == AccessControlInterface.WRITE) {
1494
    		permissions.add(Permission.WRITE);
1495
    	}
1496
    	
1497
		return permissions;
1498
    }
1499
    
1500
    /**
1501
     * Lookup a localId given the GUID. If
1502
     * the identifier is not found, throw an exception.
1503
     * 
1504
     * @param guid the global identifier to look up
1505
     * @return String containing the corresponding LocalId
1506
     * @throws McdbDocNotFoundException if the identifier is not found
1507
     */
1508
    public String getLocalId(String guid) throws McdbDocNotFoundException, SQLException {
1509
      
1510
      String db_guid = "";
1511
      String docid = "";
1512
      int rev = 0;
1513
      
1514
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1515
      
1516
      DBConnection dbConn = null;
1517
      int serialNumber = -1;
1518
      try {
1519
          // Get a database connection from the pool
1520
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1521
          serialNumber = dbConn.getCheckOutSerialNumber();
1522
          
1523
          // Execute the insert statement
1524
          PreparedStatement stmt = dbConn.prepareStatement(query);
1525
          stmt.setString(1, guid);
1526
          ResultSet rs = stmt.executeQuery();
1527
          if (rs.next()) {
1528
              db_guid = rs.getString(1);
1529
              docid = rs.getString(2);
1530
              rev = rs.getInt(3);
1531
              assert(db_guid.equals(guid));
1532
          } else {
1533
              throw new McdbDocNotFoundException("Document not found:" + guid);
1534
          }
1535
          stmt.close();
1536
      } catch (SQLException e) {
1537
          logMetacat.error("Error while looking up the local identifier: " 
1538
                  + e.getMessage());
1539
          throw e;
1540
      } finally {
1541
          // Return database connection to the pool
1542
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1543
      }
1544
      return docid + "." + rev;
1545
    }
1546
    
1547
    /**
1548
     * query the systemmetadata table based on the given parameters
1549
     * @param startTime
1550
     * @param endTime
1551
     * @param objectFormat
1552
     * @param replicaStatus
1553
     * @param start
1554
     * @param count
1555
     * @return ObjectList
1556
     * @throws SQLException 
1557
     * @throws ServiceException 
1558
     * @throws PropertyNotFoundException 
1559
     */
1560
    public ObjectList querySystemMetadata(Date startTime, Date endTime,
1561
        ObjectFormatIdentifier objectFormatId, boolean replicaStatus,
1562
        int start, int count, Identifier identifier, boolean isSID) 
1563
        throws SQLException, PropertyNotFoundException, ServiceException {
1564
        ObjectList ol = new ObjectList();
1565
        DBConnection dbConn = null;
1566
        int serialNumber = -1;
1567

    
1568
        try {
1569
            String fieldSql = "select guid, date_uploaded, rights_holder, checksum, "
1570
                    + "checksum_algorithm, origin_member_node, authoritive_member_node, "
1571
                    + "date_modified, submitter, object_format, size from systemmetadata";
1572
            
1573
            // handle special case quickly
1574
            String countSql = "select count(guid) from systemmetadata";
1575
            
1576
            // the clause
1577
            String whereClauseSql = "";
1578

    
1579
            boolean f1 = false;
1580
            boolean f2 = false;
1581
            boolean f3 = false;
1582
            boolean f4 = false;
1583

    
1584

    
1585
            if (startTime != null) {
1586
                whereClauseSql += " where systemmetadata.date_modified >= ?";
1587
                f1 = true;
1588
            }
1589

    
1590
            if (endTime != null) {
1591
                if (!f1) {
1592
                    whereClauseSql += " where systemmetadata.date_modified < ?";
1593
                } else {
1594
                    whereClauseSql += " and systemmetadata.date_modified < ?";
1595
                }
1596
                f2 = true;
1597
            }
1598

    
1599
            if (objectFormatId != null) {
1600
                if (!f1 && !f2) {
1601
                    whereClauseSql += " where object_format = ?";
1602
                } else {
1603
                    whereClauseSql += " and object_format = ?";
1604
                }
1605
                f3 = true;
1606
            }
1607
            
1608
            if(identifier != null && identifier.getValue() != null && !identifier.getValue().equals("")) {
1609
                if (!f1 && !f2 && !f3 ) {
1610
                    if(isSID) {
1611
                        whereClauseSql += " where series_id = ?";
1612
                    } else {
1613
                        whereClauseSql += " where guid = ?";
1614
                    }
1615
                    
1616
                } else {
1617
                    if(isSID) {
1618
                        whereClauseSql += " and series_id = ?";
1619
                    } else {
1620
                        whereClauseSql += " and guid = ?";
1621
                    }
1622
                }
1623
                f4 = true;
1624
            }
1625

    
1626
            if (!replicaStatus) {
1627
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.nodeId");
1628
                if (!f1 && !f2 && !f3 && !f4) {
1629
                    whereClauseSql += " where authoritive_member_node = '" +
1630
                        currentNodeId.trim() + "'";
1631
                } else {
1632
                    whereClauseSql += " and authoritive_member_node = '" +
1633
                        currentNodeId.trim() + "'";
1634
                }
1635
            }
1636
            
1637
           
1638
            
1639
            // connection
1640
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1641
            serialNumber = dbConn.getCheckOutSerialNumber();
1642

    
1643
            // the field query
1644
            String orderBySql = " order by guid ";
1645
            String fieldQuery = fieldSql + whereClauseSql + orderBySql;
1646
            String finalQuery = DatabaseService.getInstance().getDBAdapter().getPagedQuery(fieldQuery, start, count);
1647
            PreparedStatement fieldStmt = dbConn.prepareStatement(finalQuery);
1648
            
1649
            // construct the count query and statment
1650
            String countQuery = countSql + whereClauseSql;
1651
            PreparedStatement countStmt = dbConn.prepareStatement(countQuery);
1652

    
1653
            if (f1 && f2 && f3 && f4) {
1654
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1655
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1656
                fieldStmt.setString(3, objectFormatId.getValue());
1657
                fieldStmt.setString(4, identifier.getValue());
1658
                // count
1659
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1660
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1661
                countStmt.setString(3, objectFormatId.getValue());
1662
                countStmt.setString(4, identifier.getValue());
1663
            } if (f1 && f2 && f3 && !f4) {
1664
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1665
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1666
                fieldStmt.setString(3, objectFormatId.getValue());
1667
                // count
1668
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1669
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1670
                countStmt.setString(3, objectFormatId.getValue());
1671
            } else if (f1 && f2 && !f3 && f4) {
1672
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1673
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1674
                fieldStmt.setString(3, identifier.getValue());
1675
                // count
1676
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1677
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1678
                countStmt.setString(3, identifier.getValue());
1679
            } else if (f1 && f2 && !f3 && !f4) {
1680
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1681
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1682
                // count
1683
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1684
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1685
            } else if (f1 && !f2 && f3 && f4) {
1686
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1687
                fieldStmt.setString(2, objectFormatId.getValue());
1688
                fieldStmt.setString(3, identifier.getValue());
1689
                // count
1690
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1691
                countStmt.setString(2, objectFormatId.getValue());
1692
                countStmt.setString(3, identifier.getValue());
1693
            } else if (f1 && !f2 && f3 && !f4) {
1694
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1695
                fieldStmt.setString(2, objectFormatId.getValue());
1696
                // count
1697
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1698
                countStmt.setString(2, objectFormatId.getValue());
1699
            } else if (f1 && !f2 && !f3 && f4) {
1700
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1701
                fieldStmt.setString(2, identifier.getValue());
1702
                // count
1703
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1704
                countStmt.setString(2, identifier.getValue());
1705
            } else if (f1 && !f2 && !f3 && !f4) {
1706
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1707
                // count
1708
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1709
            } else if (!f1 && f2 && f3 && f4) {
1710
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1711
                fieldStmt.setString(2, objectFormatId.getValue());
1712
                fieldStmt.setString(3, identifier.getValue());
1713
                // count
1714
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1715
                countStmt.setString(2, objectFormatId.getValue());
1716
                countStmt.setString(3, identifier.getValue());
1717
            } else if (!f1 && f2 && f3 && !f4) {
1718
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1719
                fieldStmt.setString(2, objectFormatId.getValue());
1720
                // count
1721
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1722
                countStmt.setString(2, objectFormatId.getValue());
1723
            } else if (!f1 && !f2 && f3 && f4) {
1724
                fieldStmt.setString(1, objectFormatId.getValue());
1725
                fieldStmt.setString(2, identifier.getValue());
1726
                // count
1727
                countStmt.setString(1, objectFormatId.getValue());
1728
                countStmt.setString(2, identifier.getValue());
1729
            } else if (!f1 && !f2 && f3 && !f4) {
1730
                fieldStmt.setString(1, objectFormatId.getValue());
1731
                // count
1732
                countStmt.setString(1, objectFormatId.getValue());
1733
            } else if (!f1 && f2 && !f3 && f4) {
1734
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1735
                fieldStmt.setString(2, identifier.getValue());
1736
                // count
1737
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1738
                countStmt.setString(2, identifier.getValue());
1739
            } else if (!f1 && f2 && !f3 && !f4) {
1740
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1741
                // count
1742
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1743
            } else if (!f1 && !f2 && !f3 && f4) {
1744
                fieldStmt.setString(1, identifier.getValue());
1745
                // count
1746
                countStmt.setString(1, identifier.getValue());
1747
            } else if (!f1 && !f2 && !f3 && !f4) {
1748
                //do nothing
1749
            }
1750

    
1751
            logMetacat.debug("list objects fieldStmt: " + fieldStmt.toString());
1752
            
1753
            logMetacat.debug("list objects countStmt: " + countStmt.toString());
1754
            
1755
            // get the total object count no matter what
1756
            int total = 0;
1757
            ResultSet totalResult = countStmt.executeQuery();
1758
            if (totalResult.next()) {
1759
            	total = totalResult.getInt(1);
1760
            }
1761
            
1762
            logMetacat.debug("list objects total: " + total);
1763

    
1764
        	// set the totals
1765
        	ol.setStart(start);
1766
            ol.setCount(count);
1767
            ol.setTotal(total);
1768
            
1769
            // retrieve the actual records if requested
1770
            if (count != 0) {
1771
            	
1772
                ResultSet rs = fieldStmt.executeQuery();
1773
	            while (rs.next()) {                
1774
	                
1775
	                String guid = rs.getString(1);
1776
	                logMetacat.debug("query found object with guid " + guid);
1777
	                // Timestamp dateUploaded = rs.getTimestamp(2);
1778
	                // String rightsHolder = rs.getString(3);
1779
	                String checksum = rs.getString(4);
1780
	                String checksumAlgorithm = rs.getString(5);
1781
	                // String originMemberNode = rs.getString(6);
1782
	                // String authoritiveMemberNode = rs.getString(7);
1783
	                Timestamp dateModified = rs.getTimestamp(8);
1784
	                // String submitter = rs.getString(9);
1785
	                String fmtidStr = rs.getString(10);
1786
	                String sz = rs.getString(11);
1787
	                BigInteger size = new BigInteger("0");
1788
	
1789
	                if (sz != null && !sz.trim().equals("")) {
1790
	                    size = new BigInteger(rs.getString(11));
1791
	                }
1792
	
1793
	                ObjectInfo oi = new ObjectInfo();
1794
	
1795
	                Identifier id = new Identifier();
1796
	                id.setValue(guid);
1797
	                oi.setIdentifier(id);
1798
	
1799
	                if (dateModified != null) {
1800
	                    oi.setDateSysMetadataModified(dateModified);
1801
	                }
1802
	
1803
	                Checksum cs = new Checksum();
1804
	                cs.setValue(checksum);
1805
	                try {
1806
	                    // cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1807
	                    cs.setAlgorithm(checksumAlgorithm);
1808
	                } catch (Exception e) {
1809
	                    logMetacat.error("could not parse checksum algorithm", e);
1810
	                    continue;
1811
	                }
1812
	                oi.setChecksum(cs);
1813
	
1814
	                // set the format type
1815
	                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
1816
	                fmtid.setValue(fmtidStr);
1817
	                oi.setFormatId(fmtid);
1818
	
1819
	                oi.setSize(size);
1820
	
1821
	                ol.addObjectInfo(oi);                    
1822

    
1823
	            }
1824
	            
1825
	            logMetacat.debug("list objects count: " + ol.sizeObjectInfoList());
1826

    
1827
	            // set the actual count retrieved
1828
	            ol.setCount(ol.sizeObjectInfoList());
1829
	
1830
	        }
1831
            
1832
        }
1833

    
1834
        finally {
1835
            // Return database connection to the pool
1836
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1837
        }
1838

    
1839
        return ol;
1840
    }
1841
    
1842
    /**
1843
     * create a mapping in the identifier table
1844
     * @param guid
1845
     * @param localId
1846
     */
1847
    public void createMapping(String guid, String localId)
1848
    {        
1849
        
1850
        int serialNumber = -1;
1851
        DBConnection dbConn = null;
1852
        try {
1853

    
1854
            // Parse the localId into scope and rev parts
1855
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1856
            String docid = acc.getDocid();
1857
            int rev = 1;
1858
            if (acc.getRev() != null) {
1859
              rev = (new Integer(acc.getRev()).intValue());
1860
            }
1861

    
1862
            // Get a database connection from the pool
1863
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1864
            serialNumber = dbConn.getCheckOutSerialNumber();
1865

    
1866
            // Execute the insert statement
1867
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1868
            PreparedStatement stmt = dbConn.prepareStatement(query);
1869
            stmt.setString(1, guid);
1870
            stmt.setString(2, docid);
1871
            stmt.setInt(3, rev);
1872
            logMetacat.debug("mapping query: " + stmt.toString());
1873
            int rows = stmt.executeUpdate();
1874

    
1875
            stmt.close();
1876
        } catch (SQLException e) {
1877
            e.printStackTrace();
1878
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1879
                    + e.getMessage());
1880
        } catch (NumberFormatException e) {
1881
            e.printStackTrace();
1882
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1883
                    + e.getMessage());
1884
        } catch (AccessionNumberException e) {
1885
            e.printStackTrace();
1886
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1887
                    + e.getMessage());
1888
        } finally {
1889
            // Return database connection to the pool
1890
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1891
        }
1892
    }
1893
    
1894
    /**
1895
     * remove a mapping in the identifier table
1896
     * @param guid
1897
     * @param localId
1898
     */
1899
    public void removeMapping(String guid, String localId)
1900
    {        
1901
        
1902
        int serialNumber = -1;
1903
        DBConnection dbConn = null;
1904
        try {
1905

    
1906
            // Parse the localId into scope and rev parts
1907
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1908
            String docid = acc.getDocid();
1909
            int rev = 1;
1910
            if (acc.getRev() != null) {
1911
              rev = (new Integer(acc.getRev()).intValue());
1912
            }
1913

    
1914
            // Get a database connection from the pool
1915
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.removeMapping");
1916
            serialNumber = dbConn.getCheckOutSerialNumber();
1917

    
1918
            // Execute the insert statement
1919
            String query = "DELETE FROM " + TYPE_IDENTIFIER + " WHERE guid = ? AND docid = ? AND rev = ?";
1920
            PreparedStatement stmt = dbConn.prepareStatement(query);
1921
            stmt.setString(1, guid);
1922
            stmt.setString(2, docid);
1923
            stmt.setInt(3, rev);
1924
            logMetacat.debug("remove mapping query: " + stmt.toString());
1925
            int rows = stmt.executeUpdate();
1926

    
1927
            stmt.close();
1928
        } catch (SQLException e) {
1929
            e.printStackTrace();
1930
            logMetacat.error("removeMapping: SQL error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1931
                    + e.getMessage());
1932
        } catch (NumberFormatException e) {
1933
            e.printStackTrace();
1934
            logMetacat.error("removeMapping: NumberFormat error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1935
                    + e.getMessage());
1936
        } catch (AccessionNumberException e) {
1937
            e.printStackTrace();
1938
            logMetacat.error("removeMapping: AccessionNumber error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1939
                    + e.getMessage());
1940
        } finally {
1941
            // Return database connection to the pool
1942
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1943
        }
1944
    }
1945
    
1946
    /**
1947
     * create the systemmetadata record
1948
     * @param guid
1949
     * @param dbConn 
1950
     * @throws SQLException 
1951
     */
1952
    private void insertSystemMetadata(String guid, DBConnection dbConn) throws SQLException
1953
    {        
1954

    
1955
        // Execute the insert statement
1956
        String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1957
        PreparedStatement stmt = dbConn.prepareStatement(query);
1958
        stmt.setString(1, guid);
1959
        logMetacat.debug("system metadata query: " + stmt.toString());
1960
        int rows = stmt.executeUpdate();
1961

    
1962
        stmt.close();
1963
        
1964
    }
1965
    
1966
    public boolean deleteSystemMetadata(String guid)
1967
    {        
1968
        boolean success = false;
1969
        int serialNumber = -1;
1970
        DBConnection dbConn = null;
1971
        String query = null;
1972
        PreparedStatement stmt = null;
1973
        int rows = 0;
1974
        try {
1975

    
1976
        	 // Get a database connection from the pool
1977
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.deleteSystemMetadata");
1978
            serialNumber = dbConn.getCheckOutSerialNumber();
1979
            dbConn.setAutoCommit(false);
1980
        	
1981
            // remove the smReplicationPolicy
1982
            query = "delete from smReplicationPolicy " + 
1983
            "where guid = ?";
1984
            stmt = dbConn.prepareStatement(query);
1985
            stmt.setString(1, guid);
1986
            logMetacat.debug("delete smReplicationPolicy: " + stmt.toString());
1987
            rows = stmt.executeUpdate();
1988
            stmt.close();
1989
            
1990
            // remove the smReplicationStatus
1991
            query = "delete from smReplicationStatus " + 
1992
            "where guid = ?";
1993
            stmt = dbConn.prepareStatement(query);
1994
            stmt.setString(1, guid);
1995
            logMetacat.debug("delete smReplicationStatus: " + stmt.toString());
1996
            rows = stmt.executeUpdate();
1997
            stmt.close();
1998
            
1999
            // remove main system metadata entry
2000
            query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
2001
            stmt = dbConn.prepareStatement(query);
2002
            stmt.setString(1, guid);
2003
            logMetacat.debug("delete system metadata: " + stmt.toString());
2004
            rows = stmt.executeUpdate();
2005
            stmt.close();
2006
            
2007
            dbConn.commit();
2008
            dbConn.setAutoCommit(true);
2009
            success = true;
2010
            // TODO: remove the access?
2011
            // Metacat keeps "deleted" documents so we should not remove access rules.
2012
            
2013
        } catch (Exception e) {
2014
            e.printStackTrace();
2015
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
2016
            try {
2017
				dbConn.rollback();
2018
			} catch (SQLException sqle) {
2019
	            logMetacat.error("Error while rolling back delete for record: " + guid, sqle );
2020
			}
2021
        } finally {
2022
            // Return database connection to the pool
2023
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2024
        }
2025
        return success;
2026
    }
2027
    
2028
    public void updateAuthoritativeMemberNodeId(String existingMemberNodeId, String newMemberNodeId)
2029
    {
2030
        DBConnection dbConn = null;
2031
        int serialNumber = -1;
2032
        
2033
        try {
2034
            // Get a database connection from the pool
2035
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.updateAuthoritativeMemberNodeId");
2036
            serialNumber = dbConn.getCheckOutSerialNumber();
2037

    
2038
            // Execute the insert statement
2039
            String query = "update " + TYPE_SYSTEM_METADATA + 
2040
                " set authoritive_member_node = ? " +
2041
                " where authoritive_member_node = ?";
2042
            PreparedStatement stmt = dbConn.prepareStatement(query);
2043
            
2044
            //data values
2045
            stmt.setString(1, newMemberNodeId);
2046
            stmt.setString(2, existingMemberNodeId);
2047

    
2048
            logMetacat.debug("stmt: " + stmt.toString());
2049
            //execute
2050
            int rows = stmt.executeUpdate();
2051

    
2052
            stmt.close();
2053
        } catch (SQLException e) {
2054
            e.printStackTrace();
2055
            logMetacat.error("updateSystemMetadataFields: SQL error while updating system metadata: " 
2056
                    + e.getMessage());
2057
        } catch (NumberFormatException e) {
2058
            e.printStackTrace();
2059
            logMetacat.error("updateSystemMetadataFields: NumberFormat error while updating system metadata: " 
2060
                    + e.getMessage());
2061
        } finally {
2062
            // Return database connection to the pool
2063
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2064
        }
2065
    }
2066
}
2067

    
(36-36/63)