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)
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
        	try {
780
        		idExists = systemMetadataExists(guid);
781
            } catch (Exception e2) {
782
            	idExists = false;
783
            }
784
        }
785
        return idExists;
786
    }
787
    
788
    /**
789
     * Determine if an identifier mapping exists already, 
790
     * returning true if so.
791
     * 
792
     * @param guid the global identifier to look up
793
     * @return boolean true if the identifier exists
794
     */
795
    public boolean mappingExists(String guid)
796
    {
797
        boolean idExists = false;
798
        try {
799
            String id = getLocalId(guid);
800
            if (id != null) {
801
                idExists = true;
802
            }
803
        } catch (McdbDocNotFoundException e) {
804
        	// nope!
805
        }
806
        return idExists;
807
    }
808
    
809
    /**
810
     * 
811
     * @param guid
812
     * @param rev
813
     * @return
814
     */
815
    public String generateLocalId(String guid, int rev)
816
    {
817
        return generateLocalId(guid, rev, false);
818
    }
819

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

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

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

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

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

    
1099
            // Get a database connection from the pool
1100
            dbConn = 
1101
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1102
            serialNumber = dbConn.getCheckOutSerialNumber();
1103

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

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

    
1167

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

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

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

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

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

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

    
1526
            boolean f1 = false;
1527
            boolean f2 = false;
1528
            boolean f3 = false;
1529

    
1530
            if (startTime != null) {
1531
                whereClauseSql += " where systemmetadata.date_modified >= ?";
1532
                f1 = true;
1533
            }
1534

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

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

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

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

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

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

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

    
1690
	            }
1691
	            
1692
	            logMetacat.debug("list objects count: " + ol.sizeObjectInfoList());
1693

    
1694
	            // set the actual count retrieved
1695
	            ol.setCount(ol.sizeObjectInfoList());
1696
	
1697
	        }
1698
            
1699
        }
1700

    
1701
        finally {
1702
            // Return database connection to the pool
1703
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1704
        }
1705

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

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

    
1729
            // Get a database connection from the pool
1730
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1731
            serialNumber = dbConn.getCheckOutSerialNumber();
1732

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

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

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

    
1781
            // Get a database connection from the pool
1782
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.removeMapping");
1783
            serialNumber = dbConn.getCheckOutSerialNumber();
1784

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

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

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

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

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

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

    
1915
            logMetacat.debug("stmt: " + stmt.toString());
1916
            //execute
1917
            int rows = stmt.executeUpdate();
1918

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

    
(36-36/63)