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 " +
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

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

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

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

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

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

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

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

    
728
        List<String> ids = new Vector<String>();
729
        String sql = 
730
        	"select max(date_modified) from " + TYPE_SYSTEM_METADATA;
731
        DBConnection dbConn = null;
732
        int serialNumber = -1;
733
        try 
734
        {
735
            // Get a database connection from the pool
736
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLastModifiedDate");
737
            serialNumber = dbConn.getCheckOutSerialNumber();
738

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

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

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

    
1024
		DBConnection dbConn = null;
1025
		int serialNumber = -1;
1026
		try {
1027
			// Get a database connection from the pool
1028
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
1029
			serialNumber = dbConn.getCheckOutSerialNumber();
1030

    
1031
			// Execute the insert statement
1032
			PreparedStatement stmt = dbConn.prepareStatement(query);
1033
			stmt.setString(1, guid);
1034
			ResultSet rs = stmt.executeQuery();
1035
			if (rs.next()) {
1036
				exists = true;
1037
			}
1038

    
1039
		} catch (SQLException e) {
1040
			logMetacat.error("Error while looking up the system metadata: "
1041
					+ e.getMessage());
1042
			throw e;
1043
		} finally {
1044
			// Return database connection to the pool
1045
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1046
		}
1047

    
1048
		return exists;
1049
	}
1050
    
1051
    /**
1052
     * creates a system metadata mapping and adds additional fields from sysmeta
1053
     * to the table for quick searching.
1054
     * 
1055
     * @param guid the id to insert
1056
     * @param localId the systemMetadata object to get the local id for
1057
     * @throws McdbDocNotFoundException 
1058
     * @throws SQLException 
1059
     * @throws InvalidSystemMetadata 
1060
     */
1061
    public void insertOrUpdateSystemMetadata(SystemMetadata sysmeta) 
1062
        throws McdbDocNotFoundException, SQLException, InvalidSystemMetadata {
1063
    	String guid = sysmeta.getIdentifier().getValue();
1064
    	
1065
    	 // Get a database connection from the pool
1066
        DBConnection dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1067
        int serialNumber = dbConn.getCheckOutSerialNumber();
1068
        
1069
        try {
1070
        	// use a single transaction for it all
1071
        	dbConn.setAutoCommit(false);
1072
        	
1073
	    	// insert the record if needed
1074
        	if (!IdentifierManager.getInstance().systemMetadataPIDExists(guid)) {
1075
    	        insertSystemMetadata(guid, dbConn);
1076
			}
1077
	        // update with the values
1078
	        updateSystemMetadata(sysmeta, dbConn);
1079
	        
1080
	        // commit if we got here with no errors
1081
	        dbConn.commit();
1082
        } catch (Exception e) {
1083
            e.printStackTrace();
1084
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1085
            dbConn.rollback();
1086
        } finally {
1087
            // Return database connection to the pool
1088
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1089
        }
1090
        
1091
        
1092
    }
1093
        
1094
    
1095
    /**
1096
     * update a mapping
1097
     * @param guid
1098
     * @param localId
1099
     */
1100
    public void updateMapping(String guid, String localId)
1101
    {
1102
    	
1103
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
1104
        int serialNumber = -1;
1105
        DBConnection dbConn = null;
1106
        try {
1107
            // Parse the localId into scope and rev parts
1108
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1109
            String docid = acc.getDocid();
1110
            int rev = 1;
1111
            if(acc.getRev() != null)
1112
            {
1113
              rev = (new Integer(acc.getRev()).intValue());
1114
            }
1115

    
1116
            // Get a database connection from the pool
1117
            dbConn = 
1118
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1119
            serialNumber = dbConn.getCheckOutSerialNumber();
1120

    
1121
            // Execute the update statement
1122
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid = ?";
1123
            PreparedStatement stmt = dbConn.prepareStatement(query);
1124
            stmt.setString(1, docid);
1125
            stmt.setInt(2, rev);
1126
            stmt.setString(3, guid);
1127
            int rows = stmt.executeUpdate();
1128

    
1129
            stmt.close();
1130
        } catch (SQLException e) {
1131
            e.printStackTrace();
1132
            logMetacat.error("SQL error while updating a mapping identifier: " 
1133
                    + e.getMessage());
1134
        } catch (NumberFormatException e) {
1135
            e.printStackTrace();
1136
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
1137
                    + e.getMessage());
1138
        } catch (AccessionNumberException e) {
1139
            e.printStackTrace();
1140
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
1141
                    + e.getMessage());
1142
        } finally {
1143
            // Return database connection to the pool
1144
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1145
        }
1146
        logMetacat.debug("done updating mapping");
1147
    }
1148
        
1149
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1150
        String checksum, String checksumAlgorithm, String originMemberNode, 
1151
        String authoritativeMemberNode, long modifiedDate, String submitter, 
1152
        String guid, String objectFormat, BigInteger size, boolean archived,
1153
        boolean replicationAllowed, int numberReplicas, String obsoletes,
1154
        String obsoletedBy, BigInteger serialVersion, String seriesId, DBConnection dbConn) throws SQLException  {
1155
  
1156
        // Execute the insert statement
1157
        String query = "update " + TYPE_SYSTEM_METADATA + 
1158
            " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1159
            "origin_member_node, authoritive_member_node, date_modified, " +
1160
            "submitter, object_format, size, archived, replication_allowed, number_replicas, " +
1161
            "obsoletes, obsoleted_by, serial_version, series_id) " +
1162
            "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1163
        PreparedStatement stmt = dbConn.prepareStatement(query);
1164
        
1165
        //data values
1166
        stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1167
        stmt.setString(2, rightsHolder);
1168
        stmt.setString(3, checksum);
1169
        stmt.setString(4, checksumAlgorithm);
1170
        stmt.setString(5, originMemberNode);
1171
        stmt.setString(6, authoritativeMemberNode);
1172
        stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1173
        stmt.setString(8, submitter);
1174
        stmt.setString(9, objectFormat);
1175
        stmt.setString(10, size.toString());
1176
        stmt.setBoolean(11, archived);
1177
        stmt.setBoolean(12, replicationAllowed);
1178
        stmt.setInt(13, numberReplicas);
1179
        stmt.setString(14, obsoletes);
1180
        stmt.setString(15, obsoletedBy);
1181
        stmt.setString(16, serialVersion.toString());
1182
        stmt.setString(17, seriesId);
1183

    
1184

    
1185
        //where clause
1186
        stmt.setString(18, guid);
1187
        logMetacat.debug("stmt: " + stmt.toString());
1188
        //execute
1189
        int rows = stmt.executeUpdate();
1190

    
1191
        stmt.close();
1192
               
1193
    }
1194
    
1195
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes, DBConnection dbConn) throws SQLException
1196
    {
1197
           
1198
        // remove existing values first
1199
        String delete = "delete from smReplicationPolicy " + 
1200
        "where guid = ? and policy = ?";
1201
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1202
        //data values
1203
        stmt.setString(1, guid);
1204
        stmt.setString(2, policy);
1205
        //execute
1206
        int deletedCount = stmt.executeUpdate();
1207
        stmt.close();
1208
        
1209
        for (String memberNode: memberNodes) {
1210
            // Execute the insert statement
1211
            String insert = "insert into smReplicationPolicy " + 
1212
                "(guid, policy, member_node) " +
1213
                "values (?, ?, ?)";
1214
            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1215
            
1216
            //data values
1217
            insertStatement.setString(1, guid);
1218
            insertStatement.setString(2, policy);
1219
            insertStatement.setString(3, memberNode);
1220
            
1221
            logMetacat.debug("smReplicationPolicy sql: " + insertStatement.toString());
1222

    
1223
            //execute
1224
            int rows = insertStatement.executeUpdate();
1225
            insertStatement.close();
1226
        }
1227
        
1228
    }
1229
    
1230
    private void insertReplicationStatus(String guid, List<Replica> replicas, DBConnection dbConn) throws SQLException {
1231
       
1232
        // remove existing values first
1233
        String delete = "delete from smReplicationStatus " + 
1234
        "where guid = ?";
1235
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1236
        //data values
1237
        stmt.setString(1, guid);
1238
        //execute
1239
        int deletedCount = stmt.executeUpdate();
1240
        stmt.close();
1241
        
1242
        if (replicas != null) {
1243
            for (Replica replica: replicas) {
1244
	            // Execute the insert statement
1245
	            String insert = "insert into smReplicationStatus " + 
1246
	                "(guid, member_node, status, date_verified) " +
1247
	                "values (?, ?, ?, ?)";
1248
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1249
	            
1250
	            //data values
1251
	            String memberNode = replica.getReplicaMemberNode().getValue();
1252
	            String status = replica.getReplicationStatus().toString();
1253
	            java.sql.Timestamp sqlDate = new java.sql.Timestamp(replica.getReplicaVerified().getTime());
1254
	            insertStatement.setString(1, guid);
1255
	            insertStatement.setString(2, memberNode);
1256
	            insertStatement.setString(3, status);
1257
	            insertStatement.setTimestamp(4, sqlDate);
1258

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

    
1405
    	// use GUID to look up the access
1406
        XMLAccessAccess accessController  = new XMLAccessAccess();
1407
        List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1408
        
1409
        for (XMLAccessDAO accessDAO: accessDAOs) {
1410
        	// only add allow rule
1411
        	if (accessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
1412
	        	AccessRule accessRule = new AccessRule();    	
1413
	        	List <Permission> permissions = convertPermission(accessDAO.getPermission().intValue());
1414
	        	// cannot include if we have no permissions
1415
	        	if (permissions == null || permissions.isEmpty()) {
1416
	        		logMetacat.warn("skipping empty access rule permissions for " + guid);
1417
	        		continue;
1418
	        	}
1419
	        	accessRule.setPermissionList(permissions);
1420
	        	Subject subject = new Subject();
1421
	        	subject.setValue(accessDAO.getPrincipalName());
1422
	        	accessRule.addSubject(subject);
1423
	            accessPolicy.addAllow(accessRule);
1424
        	}
1425
        }
1426
        return accessPolicy;
1427
    }
1428
    
1429
    public int convertPermission(Permission permission) {
1430
    	if (permission.equals(Permission.READ)) {
1431
    		return AccessControlInterface.READ;
1432
    	}
1433
    	if (permission.equals(Permission.WRITE)) {
1434
    		return AccessControlInterface.WRITE;
1435
    	}
1436
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1437
    		return AccessControlInterface.CHMOD;
1438
    	}
1439
		return -1;
1440
    }
1441
    
1442
    public List<Permission> convertPermission(int permission) {
1443
    	
1444
    	List<Permission> permissions = new ArrayList<Permission>();
1445
    	if (permission == AccessControlInterface.ALL) {
1446
    		permissions.add(Permission.READ);
1447
    		permissions.add(Permission.WRITE);
1448
    		permissions.add(Permission.CHANGE_PERMISSION);
1449
    		return permissions;
1450
    	}
1451
    	
1452
    	if ((permission & AccessControlInterface.CHMOD) == AccessControlInterface.CHMOD) {
1453
    		permissions.add(Permission.CHANGE_PERMISSION);
1454
    	}
1455
    	if ((permission & AccessControlInterface.READ) == AccessControlInterface.READ) {
1456
    		permissions.add(Permission.READ);
1457
    	}
1458
    	if ((permission & AccessControlInterface.WRITE) == AccessControlInterface.WRITE) {
1459
    		permissions.add(Permission.WRITE);
1460
    	}
1461
    	
1462
		return permissions;
1463
    }
1464
    
1465
    /**
1466
     * Lookup a localId given the GUID. If
1467
     * the identifier is not found, throw an exception.
1468
     * 
1469
     * @param guid the global identifier to look up
1470
     * @return String containing the corresponding LocalId
1471
     * @throws McdbDocNotFoundException if the identifier is not found
1472
     */
1473
    public String getLocalId(String guid) throws McdbDocNotFoundException, SQLException {
1474
      
1475
      String db_guid = "";
1476
      String docid = "";
1477
      int rev = 0;
1478
      
1479
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1480
      
1481
      DBConnection dbConn = null;
1482
      int serialNumber = -1;
1483
      try {
1484
          // Get a database connection from the pool
1485
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1486
          serialNumber = dbConn.getCheckOutSerialNumber();
1487
          
1488
          // Execute the insert statement
1489
          PreparedStatement stmt = dbConn.prepareStatement(query);
1490
          stmt.setString(1, guid);
1491
          ResultSet rs = stmt.executeQuery();
1492
          if (rs.next()) {
1493
              db_guid = rs.getString(1);
1494
              docid = rs.getString(2);
1495
              rev = rs.getInt(3);
1496
              assert(db_guid.equals(guid));
1497
          } else {
1498
              throw new McdbDocNotFoundException("Document not found:" + guid);
1499
          }
1500
          stmt.close();
1501
      } catch (SQLException e) {
1502
          logMetacat.error("Error while looking up the local identifier: " 
1503
                  + e.getMessage());
1504
          throw e;
1505
      } finally {
1506
          // Return database connection to the pool
1507
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1508
      }
1509
      return docid + "." + rev;
1510
    }
1511
    
1512
    /**
1513
     * query the systemmetadata table based on the given parameters
1514
     * @param startTime
1515
     * @param endTime
1516
     * @param objectFormat
1517
     * @param replicaStatus
1518
     * @param start
1519
     * @param count
1520
     * @return ObjectList
1521
     * @throws SQLException 
1522
     * @throws ServiceException 
1523
     * @throws PropertyNotFoundException 
1524
     */
1525
    public ObjectList querySystemMetadata(Date startTime, Date endTime,
1526
        ObjectFormatIdentifier objectFormatId, boolean replicaStatus,
1527
        int start, int count) 
1528
        throws SQLException, PropertyNotFoundException, ServiceException {
1529
        ObjectList ol = new ObjectList();
1530
        DBConnection dbConn = null;
1531
        int serialNumber = -1;
1532

    
1533
        try {
1534
            String fieldSql = "select guid, date_uploaded, rights_holder, checksum, "
1535
                    + "checksum_algorithm, origin_member_node, authoritive_member_node, "
1536
                    + "date_modified, submitter, object_format, size from systemmetadata";
1537
            
1538
            // handle special case quickly
1539
            String countSql = "select count(guid) from systemmetadata";
1540
            
1541
            // the clause
1542
            String whereClauseSql = "";
1543

    
1544
            boolean f1 = false;
1545
            boolean f2 = false;
1546
            boolean f3 = false;
1547

    
1548
            if (startTime != null) {
1549
                whereClauseSql += " where systemmetadata.date_modified >= ?";
1550
                f1 = true;
1551
            }
1552

    
1553
            if (endTime != null) {
1554
                if (!f1) {
1555
                    whereClauseSql += " where systemmetadata.date_modified < ?";
1556
                } else {
1557
                    whereClauseSql += " and systemmetadata.date_modified < ?";
1558
                }
1559
                f2 = true;
1560
            }
1561

    
1562
            if (objectFormatId != null) {
1563
                if (!f1 && !f2) {
1564
                    whereClauseSql += " where object_format = ?";
1565
                } else {
1566
                    whereClauseSql += " and object_format = ?";
1567
                }
1568
                f3 = true;
1569
            }
1570

    
1571
            if (!replicaStatus) {
1572
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.nodeId");
1573
                if (!f1 && !f2 && !f3) {
1574
                    whereClauseSql += " where authoritive_member_node = '" +
1575
                        currentNodeId.trim() + "'";
1576
                } else {
1577
                    whereClauseSql += " and authoritive_member_node = '" +
1578
                        currentNodeId.trim() + "'";
1579
                }
1580
            }
1581
            
1582
            // connection
1583
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1584
            serialNumber = dbConn.getCheckOutSerialNumber();
1585

    
1586
            // the field query
1587
            String orderBySql = " order by guid ";
1588
            String fieldQuery = fieldSql + whereClauseSql + orderBySql;
1589
            String finalQuery = DatabaseService.getInstance().getDBAdapter().getPagedQuery(fieldQuery, start, count);
1590
            PreparedStatement fieldStmt = dbConn.prepareStatement(finalQuery);
1591
            
1592
            // construct the count query and statment
1593
            String countQuery = countSql + whereClauseSql;
1594
            PreparedStatement countStmt = dbConn.prepareStatement(countQuery);
1595

    
1596
            if (f1 && f2 && f3) {
1597
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1598
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1599
                fieldStmt.setString(3, objectFormatId.getValue());
1600
                // count
1601
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1602
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1603
                countStmt.setString(3, objectFormatId.getValue());
1604
            } else if (f1 && f2 && !f3) {
1605
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1606
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1607
                // count
1608
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1609
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1610
            } else if (f1 && !f2 && f3) {
1611
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1612
                fieldStmt.setString(2, objectFormatId.getValue());
1613
                // count
1614
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1615
                countStmt.setString(2, objectFormatId.getValue());
1616
            } else if (f1 && !f2 && !f3) {
1617
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1618
                // count
1619
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1620
            } else if (!f1 && f2 && f3) {
1621
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1622
                fieldStmt.setString(2, objectFormatId.getValue());
1623
                // count
1624
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1625
                countStmt.setString(2, objectFormatId.getValue());
1626
            } else if (!f1 && !f2 && f3) {
1627
                fieldStmt.setString(1, objectFormatId.getValue());
1628
                // count
1629
                countStmt.setString(1, objectFormatId.getValue());
1630
            } else if (!f1 && f2 && !f3) {
1631
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1632
                // count
1633
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1634
            }
1635

    
1636
            logMetacat.debug("list objects fieldStmt: " + fieldStmt.toString());
1637
            
1638
            logMetacat.debug("list objects countStmt: " + countStmt.toString());
1639
            
1640
            // get the total object count no matter what
1641
            int total = 0;
1642
            ResultSet totalResult = countStmt.executeQuery();
1643
            if (totalResult.next()) {
1644
            	total = totalResult.getInt(1);
1645
            }
1646
            
1647
            logMetacat.debug("list objects total: " + total);
1648

    
1649
        	// set the totals
1650
        	ol.setStart(start);
1651
            ol.setCount(count);
1652
            ol.setTotal(total);
1653
            
1654
            // retrieve the actual records if requested
1655
            if (count != 0) {
1656
            	
1657
                ResultSet rs = fieldStmt.executeQuery();
1658
	            while (rs.next()) {                
1659
	                
1660
	                String guid = rs.getString(1);
1661
	                logMetacat.debug("query found object with guid " + guid);
1662
	                // Timestamp dateUploaded = rs.getTimestamp(2);
1663
	                // String rightsHolder = rs.getString(3);
1664
	                String checksum = rs.getString(4);
1665
	                String checksumAlgorithm = rs.getString(5);
1666
	                // String originMemberNode = rs.getString(6);
1667
	                // String authoritiveMemberNode = rs.getString(7);
1668
	                Timestamp dateModified = rs.getTimestamp(8);
1669
	                // String submitter = rs.getString(9);
1670
	                String fmtidStr = rs.getString(10);
1671
	                String sz = rs.getString(11);
1672
	                BigInteger size = new BigInteger("0");
1673
	
1674
	                if (sz != null && !sz.trim().equals("")) {
1675
	                    size = new BigInteger(rs.getString(11));
1676
	                }
1677
	
1678
	                ObjectInfo oi = new ObjectInfo();
1679
	
1680
	                Identifier id = new Identifier();
1681
	                id.setValue(guid);
1682
	                oi.setIdentifier(id);
1683
	
1684
	                if (dateModified != null) {
1685
	                    oi.setDateSysMetadataModified(dateModified);
1686
	                }
1687
	
1688
	                Checksum cs = new Checksum();
1689
	                cs.setValue(checksum);
1690
	                try {
1691
	                    // cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1692
	                    cs.setAlgorithm(checksumAlgorithm);
1693
	                } catch (Exception e) {
1694
	                    logMetacat.error("could not parse checksum algorithm", e);
1695
	                    continue;
1696
	                }
1697
	                oi.setChecksum(cs);
1698
	
1699
	                // set the format type
1700
	                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
1701
	                fmtid.setValue(fmtidStr);
1702
	                oi.setFormatId(fmtid);
1703
	
1704
	                oi.setSize(size);
1705
	
1706
	                ol.addObjectInfo(oi);                    
1707

    
1708
	            }
1709
	            
1710
	            logMetacat.debug("list objects count: " + ol.sizeObjectInfoList());
1711

    
1712
	            // set the actual count retrieved
1713
	            ol.setCount(ol.sizeObjectInfoList());
1714
	
1715
	        }
1716
            
1717
        }
1718

    
1719
        finally {
1720
            // Return database connection to the pool
1721
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1722
        }
1723

    
1724
        return ol;
1725
    }
1726
    
1727
    /**
1728
     * create a mapping in the identifier table
1729
     * @param guid
1730
     * @param localId
1731
     */
1732
    public void createMapping(String guid, String localId)
1733
    {        
1734
        
1735
        int serialNumber = -1;
1736
        DBConnection dbConn = null;
1737
        try {
1738

    
1739
            // Parse the localId into scope and rev parts
1740
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1741
            String docid = acc.getDocid();
1742
            int rev = 1;
1743
            if (acc.getRev() != null) {
1744
              rev = (new Integer(acc.getRev()).intValue());
1745
            }
1746

    
1747
            // Get a database connection from the pool
1748
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1749
            serialNumber = dbConn.getCheckOutSerialNumber();
1750

    
1751
            // Execute the insert statement
1752
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1753
            PreparedStatement stmt = dbConn.prepareStatement(query);
1754
            stmt.setString(1, guid);
1755
            stmt.setString(2, docid);
1756
            stmt.setInt(3, rev);
1757
            logMetacat.debug("mapping query: " + stmt.toString());
1758
            int rows = stmt.executeUpdate();
1759

    
1760
            stmt.close();
1761
        } catch (SQLException e) {
1762
            e.printStackTrace();
1763
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1764
                    + e.getMessage());
1765
        } catch (NumberFormatException e) {
1766
            e.printStackTrace();
1767
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1768
                    + e.getMessage());
1769
        } catch (AccessionNumberException e) {
1770
            e.printStackTrace();
1771
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1772
                    + e.getMessage());
1773
        } finally {
1774
            // Return database connection to the pool
1775
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1776
        }
1777
    }
1778
    
1779
    /**
1780
     * remove a mapping in the identifier table
1781
     * @param guid
1782
     * @param localId
1783
     */
1784
    public void removeMapping(String guid, String localId)
1785
    {        
1786
        
1787
        int serialNumber = -1;
1788
        DBConnection dbConn = null;
1789
        try {
1790

    
1791
            // Parse the localId into scope and rev parts
1792
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1793
            String docid = acc.getDocid();
1794
            int rev = 1;
1795
            if (acc.getRev() != null) {
1796
              rev = (new Integer(acc.getRev()).intValue());
1797
            }
1798

    
1799
            // Get a database connection from the pool
1800
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.removeMapping");
1801
            serialNumber = dbConn.getCheckOutSerialNumber();
1802

    
1803
            // Execute the insert statement
1804
            String query = "DELETE FROM " + TYPE_IDENTIFIER + " WHERE guid = ? AND docid = ? AND rev = ?";
1805
            PreparedStatement stmt = dbConn.prepareStatement(query);
1806
            stmt.setString(1, guid);
1807
            stmt.setString(2, docid);
1808
            stmt.setInt(3, rev);
1809
            logMetacat.debug("remove mapping query: " + stmt.toString());
1810
            int rows = stmt.executeUpdate();
1811

    
1812
            stmt.close();
1813
        } catch (SQLException e) {
1814
            e.printStackTrace();
1815
            logMetacat.error("removeMapping: SQL error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1816
                    + e.getMessage());
1817
        } catch (NumberFormatException e) {
1818
            e.printStackTrace();
1819
            logMetacat.error("removeMapping: NumberFormat error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1820
                    + e.getMessage());
1821
        } catch (AccessionNumberException e) {
1822
            e.printStackTrace();
1823
            logMetacat.error("removeMapping: AccessionNumber error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1824
                    + e.getMessage());
1825
        } finally {
1826
            // Return database connection to the pool
1827
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1828
        }
1829
    }
1830
    
1831
    /**
1832
     * create the systemmetadata record
1833
     * @param guid
1834
     * @param dbConn 
1835
     * @throws SQLException 
1836
     */
1837
    private void insertSystemMetadata(String guid, DBConnection dbConn) throws SQLException
1838
    {        
1839

    
1840
        // Execute the insert statement
1841
        String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1842
        PreparedStatement stmt = dbConn.prepareStatement(query);
1843
        stmt.setString(1, guid);
1844
        logMetacat.debug("system metadata query: " + stmt.toString());
1845
        int rows = stmt.executeUpdate();
1846

    
1847
        stmt.close();
1848
        
1849
    }
1850
    
1851
    public boolean deleteSystemMetadata(String guid)
1852
    {        
1853
        boolean success = false;
1854
        int serialNumber = -1;
1855
        DBConnection dbConn = null;
1856
        String query = null;
1857
        PreparedStatement stmt = null;
1858
        int rows = 0;
1859
        try {
1860

    
1861
        	 // Get a database connection from the pool
1862
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.deleteSystemMetadata");
1863
            serialNumber = dbConn.getCheckOutSerialNumber();
1864
            dbConn.setAutoCommit(false);
1865
        	
1866
            // remove the smReplicationPolicy
1867
            query = "delete from smReplicationPolicy " + 
1868
            "where guid = ?";
1869
            stmt = dbConn.prepareStatement(query);
1870
            stmt.setString(1, guid);
1871
            logMetacat.debug("delete smReplicationPolicy: " + stmt.toString());
1872
            rows = stmt.executeUpdate();
1873
            stmt.close();
1874
            
1875
            // remove the smReplicationStatus
1876
            query = "delete from smReplicationStatus " + 
1877
            "where guid = ?";
1878
            stmt = dbConn.prepareStatement(query);
1879
            stmt.setString(1, guid);
1880
            logMetacat.debug("delete smReplicationStatus: " + stmt.toString());
1881
            rows = stmt.executeUpdate();
1882
            stmt.close();
1883
            
1884
            // remove main system metadata entry
1885
            query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
1886
            stmt = dbConn.prepareStatement(query);
1887
            stmt.setString(1, guid);
1888
            logMetacat.debug("delete system metadata: " + stmt.toString());
1889
            rows = stmt.executeUpdate();
1890
            stmt.close();
1891
            
1892
            dbConn.commit();
1893
            dbConn.setAutoCommit(true);
1894
            success = true;
1895
            // TODO: remove the access?
1896
            // Metacat keeps "deleted" documents so we should not remove access rules.
1897
            
1898
        } catch (Exception e) {
1899
            e.printStackTrace();
1900
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1901
            try {
1902
				dbConn.rollback();
1903
			} catch (SQLException sqle) {
1904
	            logMetacat.error("Error while rolling back delete for record: " + guid, sqle );
1905
			}
1906
        } finally {
1907
            // Return database connection to the pool
1908
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1909
        }
1910
        return success;
1911
    }
1912
    
1913
    public void updateAuthoritativeMemberNodeId(String existingMemberNodeId, String newMemberNodeId)
1914
    {
1915
        DBConnection dbConn = null;
1916
        int serialNumber = -1;
1917
        
1918
        try {
1919
            // Get a database connection from the pool
1920
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.updateAuthoritativeMemberNodeId");
1921
            serialNumber = dbConn.getCheckOutSerialNumber();
1922

    
1923
            // Execute the insert statement
1924
            String query = "update " + TYPE_SYSTEM_METADATA + 
1925
                " set authoritive_member_node = ? " +
1926
                " where authoritive_member_node = ?";
1927
            PreparedStatement stmt = dbConn.prepareStatement(query);
1928
            
1929
            //data values
1930
            stmt.setString(1, newMemberNodeId);
1931
            stmt.setString(2, existingMemberNodeId);
1932

    
1933
            logMetacat.debug("stmt: " + stmt.toString());
1934
            //execute
1935
            int rows = stmt.executeUpdate();
1936

    
1937
            stmt.close();
1938
        } catch (SQLException e) {
1939
            e.printStackTrace();
1940
            logMetacat.error("updateSystemMetadataFields: SQL error while updating system metadata: " 
1941
                    + e.getMessage());
1942
        } catch (NumberFormatException e) {
1943
            e.printStackTrace();
1944
            logMetacat.error("updateSystemMetadataFields: NumberFormat error while updating system metadata: " 
1945
                    + e.getMessage());
1946
        } finally {
1947
            // Return database connection to the pool
1948
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1949
        }
1950
    }
1951
}
1952

    
(36-36/63)