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 = systemMetadataGUIDExists(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)
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
     * @param sid specified sid which should match.
931
     * @return the pid of the head version. The null will be returned if there is no pid found.
932
     * @throws SQLException 
933
     */
934
    public Identifier getHeadPID(Identifier sid) throws SQLException {
935
        Identifier pid = null;
936
        if(sid != null && sid.getValue() != null && !sid.getValue().trim().equals("")) {
937
            logMetacat.debug("getting pid of the head version for matching the sid: " + sid.getValue());
938
            String sql = "select guid from systemMetadata where obsoleted_by is null and series_id = ?";
939
            DBConnection dbConn = null;
940
            int serialNumber = -1;
941
            try {
942
                // Get a database connection from the pool
943
                dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getHeadPID");
944
                serialNumber = dbConn.getCheckOutSerialNumber();
945
                // Execute the insert statement
946
                PreparedStatement stmt = dbConn.prepareStatement(sql);
947
                stmt.setString(1, sid.getValue());
948
                ResultSet rs = stmt.executeQuery();
949
                if (rs.next()) 
950
                {
951
                    pid = new Identifier();
952
                    pid.setValue(rs.getString(1));
953
                   
954
                } 
955
                
956
            } catch (SQLException e) {
957
                logMetacat.error("Error while get the head pid for the sid "+sid.getValue()+" : " 
958
                        + e.getMessage());
959
                throw e;
960
            } finally {
961
                // Return database connection to the pool
962
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
963
            }
964
        }
965
        return pid;
966
    }
967
    
968
    /**
969
     * Check if the specified sid exists on the serial id field on the system metadata table
970
     * @param id
971
     * @return true if it exists; false otherwise.
972
     */
973
    public boolean systemMetadataSIDExists(String sid) throws SQLException {
974
        boolean exists = false;
975
        if(sid != null && !sid.trim().equals("")) {
976
            logMetacat.debug("Check if the  sid: " + sid +" exists on the series_id field of the system metadata table.");
977
            String sql = "select guid from systemMetadata where series_id = ?";
978
            DBConnection dbConn = null;
979
            int serialNumber = -1;
980
            try {
981
                // Get a database connection from the pool
982
                dbConn = DBConnectionPool.getDBConnection("IdentifierManager.serialIdExists");
983
                serialNumber = dbConn.getCheckOutSerialNumber();
984
                // Execute the insert statement
985
                PreparedStatement stmt = dbConn.prepareStatement(sql);
986
                stmt.setString(1, sid);
987
                ResultSet rs = stmt.executeQuery();
988
                if (rs.next()) 
989
                {
990
                    exists = true;
991
                } 
992
                
993
            } catch (SQLException e) {
994
                logMetacat.error("Error while checking if the sid "+sid+" exists on the series_id field of the system metadata table: " 
995
                        + e.getMessage());
996
                throw e;
997
            } finally {
998
                // Return database connection to the pool
999
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1000
            }
1001
        }
1002
        return exists;
1003
    }
1004
    
1005
    public boolean systemMetadataGUIDExists(String guid) throws SQLException {
1006
		logMetacat.debug("looking up system metadata for guid " + guid);
1007
		boolean exists = false;
1008
		String query = "select guid from systemmetadata where guid = ?";
1009

    
1010
		DBConnection dbConn = null;
1011
		int serialNumber = -1;
1012
		try {
1013
			// Get a database connection from the pool
1014
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
1015
			serialNumber = dbConn.getCheckOutSerialNumber();
1016

    
1017
			// Execute the insert statement
1018
			PreparedStatement stmt = dbConn.prepareStatement(query);
1019
			stmt.setString(1, guid);
1020
			ResultSet rs = stmt.executeQuery();
1021
			if (rs.next()) {
1022
				exists = true;
1023
			}
1024

    
1025
		} catch (SQLException e) {
1026
			logMetacat.error("Error while looking up the system metadata: "
1027
					+ e.getMessage());
1028
			throw e;
1029
		} finally {
1030
			// Return database connection to the pool
1031
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1032
		}
1033

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

    
1102
            // Get a database connection from the pool
1103
            dbConn = 
1104
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1105
            serialNumber = dbConn.getCheckOutSerialNumber();
1106

    
1107
            // Execute the update statement
1108
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid = ?";
1109
            PreparedStatement stmt = dbConn.prepareStatement(query);
1110
            stmt.setString(1, docid);
1111
            stmt.setInt(2, rev);
1112
            stmt.setString(3, guid);
1113
            int rows = stmt.executeUpdate();
1114

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

    
1170

    
1171
        //where clause
1172
        stmt.setString(18, guid);
1173
        logMetacat.debug("stmt: " + stmt.toString());
1174
        //execute
1175
        int rows = stmt.executeUpdate();
1176

    
1177
        stmt.close();
1178
               
1179
    }
1180
    
1181
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes, DBConnection dbConn) throws SQLException
1182
    {
1183
           
1184
        // remove existing values first
1185
        String delete = "delete from smReplicationPolicy " + 
1186
        "where guid = ? and policy = ?";
1187
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1188
        //data values
1189
        stmt.setString(1, guid);
1190
        stmt.setString(2, policy);
1191
        //execute
1192
        int deletedCount = stmt.executeUpdate();
1193
        stmt.close();
1194
        
1195
        for (String memberNode: memberNodes) {
1196
            // Execute the insert statement
1197
            String insert = "insert into smReplicationPolicy " + 
1198
                "(guid, policy, member_node) " +
1199
                "values (?, ?, ?)";
1200
            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1201
            
1202
            //data values
1203
            insertStatement.setString(1, guid);
1204
            insertStatement.setString(2, policy);
1205
            insertStatement.setString(3, memberNode);
1206
            
1207
            logMetacat.debug("smReplicationPolicy sql: " + insertStatement.toString());
1208

    
1209
            //execute
1210
            int rows = insertStatement.executeUpdate();
1211
            insertStatement.close();
1212
        }
1213
        
1214
    }
1215
    
1216
    private void insertReplicationStatus(String guid, List<Replica> replicas, DBConnection dbConn) throws SQLException {
1217
       
1218
        // remove existing values first
1219
        String delete = "delete from smReplicationStatus " + 
1220
        "where guid = ?";
1221
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1222
        //data values
1223
        stmt.setString(1, guid);
1224
        //execute
1225
        int deletedCount = stmt.executeUpdate();
1226
        stmt.close();
1227
        
1228
        if (replicas != null) {
1229
            for (Replica replica: replicas) {
1230
	            // Execute the insert statement
1231
	            String insert = "insert into smReplicationStatus " + 
1232
	                "(guid, member_node, status, date_verified) " +
1233
	                "values (?, ?, ?, ?)";
1234
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1235
	            
1236
	            //data values
1237
	            String memberNode = replica.getReplicaMemberNode().getValue();
1238
	            String status = replica.getReplicationStatus().toString();
1239
	            java.sql.Timestamp sqlDate = new java.sql.Timestamp(replica.getReplicaVerified().getTime());
1240
	            insertStatement.setString(1, guid);
1241
	            insertStatement.setString(2, memberNode);
1242
	            insertStatement.setString(3, status);
1243
	            insertStatement.setTimestamp(4, sqlDate);
1244

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

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

    
1518
        try {
1519
            String fieldSql = "select guid, date_uploaded, rights_holder, checksum, "
1520
                    + "checksum_algorithm, origin_member_node, authoritive_member_node, "
1521
                    + "date_modified, submitter, object_format, size from systemmetadata";
1522
            
1523
            // handle special case quickly
1524
            String countSql = "select count(guid) from systemmetadata";
1525
            
1526
            // the clause
1527
            String whereClauseSql = "";
1528

    
1529
            boolean f1 = false;
1530
            boolean f2 = false;
1531
            boolean f3 = false;
1532

    
1533
            if (startTime != null) {
1534
                whereClauseSql += " where systemmetadata.date_modified >= ?";
1535
                f1 = true;
1536
            }
1537

    
1538
            if (endTime != null) {
1539
                if (!f1) {
1540
                    whereClauseSql += " where systemmetadata.date_modified < ?";
1541
                } else {
1542
                    whereClauseSql += " and systemmetadata.date_modified < ?";
1543
                }
1544
                f2 = true;
1545
            }
1546

    
1547
            if (objectFormatId != null) {
1548
                if (!f1 && !f2) {
1549
                    whereClauseSql += " where object_format = ?";
1550
                } else {
1551
                    whereClauseSql += " and object_format = ?";
1552
                }
1553
                f3 = true;
1554
            }
1555

    
1556
            if (!replicaStatus) {
1557
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.nodeId");
1558
                if (!f1 && !f2 && !f3) {
1559
                    whereClauseSql += " where authoritive_member_node = '" +
1560
                        currentNodeId.trim() + "'";
1561
                } else {
1562
                    whereClauseSql += " and authoritive_member_node = '" +
1563
                        currentNodeId.trim() + "'";
1564
                }
1565
            }
1566
            
1567
            // connection
1568
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1569
            serialNumber = dbConn.getCheckOutSerialNumber();
1570

    
1571
            // the field query
1572
            String orderBySql = " order by guid ";
1573
            String fieldQuery = fieldSql + whereClauseSql + orderBySql;
1574
            String finalQuery = DatabaseService.getInstance().getDBAdapter().getPagedQuery(fieldQuery, start, count);
1575
            PreparedStatement fieldStmt = dbConn.prepareStatement(finalQuery);
1576
            
1577
            // construct the count query and statment
1578
            String countQuery = countSql + whereClauseSql;
1579
            PreparedStatement countStmt = dbConn.prepareStatement(countQuery);
1580

    
1581
            if (f1 && f2 && f3) {
1582
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1583
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1584
                fieldStmt.setString(3, objectFormatId.getValue());
1585
                // count
1586
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1587
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1588
                countStmt.setString(3, objectFormatId.getValue());
1589
            } else if (f1 && f2 && !f3) {
1590
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1591
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1592
                // count
1593
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1594
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1595
            } else if (f1 && !f2 && f3) {
1596
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1597
                fieldStmt.setString(2, objectFormatId.getValue());
1598
                // count
1599
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1600
                countStmt.setString(2, objectFormatId.getValue());
1601
            } else if (f1 && !f2 && !f3) {
1602
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1603
                // count
1604
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1605
            } else if (!f1 && f2 && f3) {
1606
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1607
                fieldStmt.setString(2, objectFormatId.getValue());
1608
                // count
1609
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1610
                countStmt.setString(2, objectFormatId.getValue());
1611
            } else if (!f1 && !f2 && f3) {
1612
                fieldStmt.setString(1, objectFormatId.getValue());
1613
                // count
1614
                countStmt.setString(1, objectFormatId.getValue());
1615
            } else if (!f1 && f2 && !f3) {
1616
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1617
                // count
1618
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1619
            }
1620

    
1621
            logMetacat.debug("list objects fieldStmt: " + fieldStmt.toString());
1622
            
1623
            logMetacat.debug("list objects countStmt: " + countStmt.toString());
1624
            
1625
            // get the total object count no matter what
1626
            int total = 0;
1627
            ResultSet totalResult = countStmt.executeQuery();
1628
            if (totalResult.next()) {
1629
            	total = totalResult.getInt(1);
1630
            }
1631
            
1632
            logMetacat.debug("list objects total: " + total);
1633

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

    
1693
	            }
1694
	            
1695
	            logMetacat.debug("list objects count: " + ol.sizeObjectInfoList());
1696

    
1697
	            // set the actual count retrieved
1698
	            ol.setCount(ol.sizeObjectInfoList());
1699
	
1700
	        }
1701
            
1702
        }
1703

    
1704
        finally {
1705
            // Return database connection to the pool
1706
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1707
        }
1708

    
1709
        return ol;
1710
    }
1711
    
1712
    /**
1713
     * create a mapping in the identifier table
1714
     * @param guid
1715
     * @param localId
1716
     */
1717
    public void createMapping(String guid, String localId)
1718
    {        
1719
        
1720
        int serialNumber = -1;
1721
        DBConnection dbConn = null;
1722
        try {
1723

    
1724
            // Parse the localId into scope and rev parts
1725
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1726
            String docid = acc.getDocid();
1727
            int rev = 1;
1728
            if (acc.getRev() != null) {
1729
              rev = (new Integer(acc.getRev()).intValue());
1730
            }
1731

    
1732
            // Get a database connection from the pool
1733
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1734
            serialNumber = dbConn.getCheckOutSerialNumber();
1735

    
1736
            // Execute the insert statement
1737
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1738
            PreparedStatement stmt = dbConn.prepareStatement(query);
1739
            stmt.setString(1, guid);
1740
            stmt.setString(2, docid);
1741
            stmt.setInt(3, rev);
1742
            logMetacat.debug("mapping query: " + stmt.toString());
1743
            int rows = stmt.executeUpdate();
1744

    
1745
            stmt.close();
1746
        } catch (SQLException e) {
1747
            e.printStackTrace();
1748
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1749
                    + e.getMessage());
1750
        } catch (NumberFormatException e) {
1751
            e.printStackTrace();
1752
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1753
                    + e.getMessage());
1754
        } catch (AccessionNumberException e) {
1755
            e.printStackTrace();
1756
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1757
                    + e.getMessage());
1758
        } finally {
1759
            // Return database connection to the pool
1760
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1761
        }
1762
    }
1763
    
1764
    /**
1765
     * remove a mapping in the identifier table
1766
     * @param guid
1767
     * @param localId
1768
     */
1769
    public void removeMapping(String guid, String localId)
1770
    {        
1771
        
1772
        int serialNumber = -1;
1773
        DBConnection dbConn = null;
1774
        try {
1775

    
1776
            // Parse the localId into scope and rev parts
1777
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1778
            String docid = acc.getDocid();
1779
            int rev = 1;
1780
            if (acc.getRev() != null) {
1781
              rev = (new Integer(acc.getRev()).intValue());
1782
            }
1783

    
1784
            // Get a database connection from the pool
1785
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.removeMapping");
1786
            serialNumber = dbConn.getCheckOutSerialNumber();
1787

    
1788
            // Execute the insert statement
1789
            String query = "DELETE FROM " + TYPE_IDENTIFIER + " WHERE guid = ? AND docid = ? AND rev = ?";
1790
            PreparedStatement stmt = dbConn.prepareStatement(query);
1791
            stmt.setString(1, guid);
1792
            stmt.setString(2, docid);
1793
            stmt.setInt(3, rev);
1794
            logMetacat.debug("remove mapping query: " + stmt.toString());
1795
            int rows = stmt.executeUpdate();
1796

    
1797
            stmt.close();
1798
        } catch (SQLException e) {
1799
            e.printStackTrace();
1800
            logMetacat.error("removeMapping: SQL error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1801
                    + e.getMessage());
1802
        } catch (NumberFormatException e) {
1803
            e.printStackTrace();
1804
            logMetacat.error("removeMapping: NumberFormat error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1805
                    + e.getMessage());
1806
        } catch (AccessionNumberException e) {
1807
            e.printStackTrace();
1808
            logMetacat.error("removeMapping: AccessionNumber error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1809
                    + e.getMessage());
1810
        } finally {
1811
            // Return database connection to the pool
1812
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1813
        }
1814
    }
1815
    
1816
    /**
1817
     * create the systemmetadata record
1818
     * @param guid
1819
     * @param dbConn 
1820
     * @throws SQLException 
1821
     */
1822
    private void insertSystemMetadata(String guid, DBConnection dbConn) throws SQLException
1823
    {        
1824

    
1825
        // Execute the insert statement
1826
        String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1827
        PreparedStatement stmt = dbConn.prepareStatement(query);
1828
        stmt.setString(1, guid);
1829
        logMetacat.debug("system metadata query: " + stmt.toString());
1830
        int rows = stmt.executeUpdate();
1831

    
1832
        stmt.close();
1833
        
1834
    }
1835
    
1836
    public boolean deleteSystemMetadata(String guid)
1837
    {        
1838
        boolean success = false;
1839
        int serialNumber = -1;
1840
        DBConnection dbConn = null;
1841
        String query = null;
1842
        PreparedStatement stmt = null;
1843
        int rows = 0;
1844
        try {
1845

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

    
1908
            // Execute the insert statement
1909
            String query = "update " + TYPE_SYSTEM_METADATA + 
1910
                " set authoritive_member_node = ? " +
1911
                " where authoritive_member_node = ?";
1912
            PreparedStatement stmt = dbConn.prepareStatement(query);
1913
            
1914
            //data values
1915
            stmt.setString(1, newMemberNodeId);
1916
            stmt.setString(2, existingMemberNodeId);
1917

    
1918
            logMetacat.debug("stmt: " + stmt.toString());
1919
            //execute
1920
            int rows = stmt.executeUpdate();
1921

    
1922
            stmt.close();
1923
        } catch (SQLException e) {
1924
            e.printStackTrace();
1925
            logMetacat.error("updateSystemMetadataFields: SQL error while updating system metadata: " 
1926
                    + e.getMessage());
1927
        } catch (NumberFormatException e) {
1928
            e.printStackTrace();
1929
            logMetacat.error("updateSystemMetadataFields: NumberFormat error while updating system metadata: " 
1930
                    + e.getMessage());
1931
        } finally {
1932
            // Return database connection to the pool
1933
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1934
        }
1935
    }
1936
}
1937

    
(36-36/63)