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.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.v1.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
                Subject submitterSubject = new Subject();
315
                submitterSubject.setValue(submitter);
316
                sysMeta.setSubmitter(submitterSubject);
317
                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
318
                fmtid.setValue(fmtidStr);
319
            	sysMeta.setFormatId(fmtid);
320
                sysMeta.setSize(size);
321
                if (obsoletes != null) {
322
	                Identifier obsoletesId = new Identifier();
323
	                obsoletesId.setValue(obsoletes);
324
	                sysMeta.setObsoletes(obsoletesId);
325
                }
326
                if (obsoletedBy != null) {
327
		            Identifier obsoletedById = new Identifier();
328
		            obsoletedById.setValue(obsoletedBy);
329
		            sysMeta.setObsoletedBy(obsoletedById);
330
                }
331
                sysMeta.setArchived(archived);
332
                stmt.close();
333
            } 
334
            else
335
            {
336
                stmt.close();
337
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
338
                throw new McdbDocNotFoundException("Could not find " + guid);
339
            }
340
            
341
        } 
342
        catch (SQLException e) 
343
        {
344
            e.printStackTrace();
345
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "  
346
                    + e.getMessage());
347
        } 
348
        finally 
349
        {
350
            // Return database connection to the pool
351
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
352
        }
353

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

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

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

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

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

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

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

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

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

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

    
926
		DBConnection dbConn = null;
927
		int serialNumber = -1;
928
		try {
929
			// Get a database connection from the pool
930
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
931
			serialNumber = dbConn.getCheckOutSerialNumber();
932

    
933
			// Execute the insert statement
934
			PreparedStatement stmt = dbConn.prepareStatement(query);
935
			stmt.setString(1, guid);
936
			ResultSet rs = stmt.executeQuery();
937
			if (rs.next()) {
938
				exists = true;
939
			}
940

    
941
		} catch (SQLException e) {
942
			logMetacat.error("Error while looking up the system metadata: "
943
					+ e.getMessage());
944
		} finally {
945
			// Return database connection to the pool
946
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
947
		}
948

    
949
		return exists;
950
	}
951
    
952
    /**
953
     * creates a system metadata mapping and adds additional fields from sysmeta
954
     * to the table for quick searching.
955
     * 
956
     * @param guid the id to insert
957
     * @param localId the systemMetadata object to get the local id for
958
     * @throws McdbDocNotFoundException 
959
     * @throws SQLException 
960
     * @throws InvalidSystemMetadata 
961
     */
962
    public void insertOrUpdateSystemMetadata(SystemMetadata sysmeta) 
963
        throws McdbDocNotFoundException, SQLException, InvalidSystemMetadata {
964
    	String guid = sysmeta.getIdentifier().getValue();
965
    	
966
    	 // Get a database connection from the pool
967
        DBConnection dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
968
        int serialNumber = dbConn.getCheckOutSerialNumber();
969
        
970
        try {
971
        	// use a single transaction for it all
972
        	dbConn.setAutoCommit(false);
973
        	
974
	    	// insert the record if needed
975
        	if (!IdentifierManager.getInstance().systemMetadataExists(guid)) {
976
    	        insertSystemMetadata(guid, dbConn);
977
			}
978
	        // update with the values
979
	        updateSystemMetadata(sysmeta, dbConn);
980
	        
981
	        // commit if we got here with no errors
982
	        dbConn.commit();
983
        } catch (Exception e) {
984
            e.printStackTrace();
985
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
986
            dbConn.rollback();
987
        } finally {
988
            // Return database connection to the pool
989
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
990
        }
991
        
992
        
993
    }
994
        
995
    
996
    /**
997
     * update a mapping
998
     * @param guid
999
     * @param localId
1000
     */
1001
    public void updateMapping(String guid, String localId)
1002
    {
1003
    	
1004
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
1005
        int serialNumber = -1;
1006
        DBConnection dbConn = null;
1007
        try {
1008
            // Parse the localId into scope and rev parts
1009
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1010
            String docid = acc.getDocid();
1011
            int rev = 1;
1012
            if(acc.getRev() != null)
1013
            {
1014
              rev = (new Integer(acc.getRev()).intValue());
1015
            }
1016

    
1017
            // Get a database connection from the pool
1018
            dbConn = 
1019
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1020
            serialNumber = dbConn.getCheckOutSerialNumber();
1021

    
1022
            // Execute the update statement
1023
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid = ?";
1024
            PreparedStatement stmt = dbConn.prepareStatement(query);
1025
            stmt.setString(1, docid);
1026
            stmt.setInt(2, rev);
1027
            stmt.setString(3, guid);
1028
            int rows = stmt.executeUpdate();
1029

    
1030
            stmt.close();
1031
        } catch (SQLException e) {
1032
            e.printStackTrace();
1033
            logMetacat.error("SQL error while updating a mapping identifier: " 
1034
                    + e.getMessage());
1035
        } catch (NumberFormatException e) {
1036
            e.printStackTrace();
1037
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
1038
                    + e.getMessage());
1039
        } catch (AccessionNumberException e) {
1040
            e.printStackTrace();
1041
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
1042
                    + e.getMessage());
1043
        } finally {
1044
            // Return database connection to the pool
1045
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1046
        }
1047
        logMetacat.debug("done updating mapping");
1048
    }
1049
        
1050
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1051
        String checksum, String checksumAlgorithm, String originMemberNode, 
1052
        String authoritativeMemberNode, long modifiedDate, String submitter, 
1053
        String guid, String objectFormat, BigInteger size, boolean archived,
1054
        boolean replicationAllowed, int numberReplicas, String obsoletes,
1055
        String obsoletedBy, BigInteger serialVersion, DBConnection dbConn) throws SQLException  {
1056
  
1057
        // Execute the insert statement
1058
        String query = "update " + TYPE_SYSTEM_METADATA + 
1059
            " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1060
            "origin_member_node, authoritive_member_node, date_modified, " +
1061
            "submitter, object_format, size, archived, replication_allowed, number_replicas, " +
1062
            "obsoletes, obsoleted_by, serial_version) " +
1063
            "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1064
        PreparedStatement stmt = dbConn.prepareStatement(query);
1065
        
1066
        //data values
1067
        stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1068
        stmt.setString(2, rightsHolder);
1069
        stmt.setString(3, checksum);
1070
        stmt.setString(4, checksumAlgorithm);
1071
        stmt.setString(5, originMemberNode);
1072
        stmt.setString(6, authoritativeMemberNode);
1073
        stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1074
        stmt.setString(8, submitter);
1075
        stmt.setString(9, objectFormat);
1076
        stmt.setString(10, size.toString());
1077
        stmt.setBoolean(11, archived);
1078
        stmt.setBoolean(12, replicationAllowed);
1079
        stmt.setInt(13, numberReplicas);
1080
        stmt.setString(14, obsoletes);
1081
        stmt.setString(15, obsoletedBy);
1082
        stmt.setString(16, serialVersion.toString());
1083

    
1084
        //where clause
1085
        stmt.setString(17, guid);
1086
        logMetacat.debug("stmt: " + stmt.toString());
1087
        //execute
1088
        int rows = stmt.executeUpdate();
1089

    
1090
        stmt.close();
1091
               
1092
    }
1093
    
1094
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes, DBConnection dbConn) throws SQLException
1095
    {
1096
           
1097
        // remove existing values first
1098
        String delete = "delete from smReplicationPolicy " + 
1099
        "where guid = ? and policy = ?";
1100
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1101
        //data values
1102
        stmt.setString(1, guid);
1103
        stmt.setString(2, policy);
1104
        //execute
1105
        int deletedCount = stmt.executeUpdate();
1106
        stmt.close();
1107
        
1108
        for (String memberNode: memberNodes) {
1109
            // Execute the insert statement
1110
            String insert = "insert into smReplicationPolicy " + 
1111
                "(guid, policy, member_node) " +
1112
                "values (?, ?, ?)";
1113
            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1114
            
1115
            //data values
1116
            insertStatement.setString(1, guid);
1117
            insertStatement.setString(2, policy);
1118
            insertStatement.setString(3, memberNode);
1119
            
1120
            logMetacat.debug("smReplicationPolicy sql: " + insertStatement.toString());
1121

    
1122
            //execute
1123
            int rows = insertStatement.executeUpdate();
1124
            insertStatement.close();
1125
        }
1126
        
1127
    }
1128
    
1129
    private void insertReplicationStatus(String guid, List<Replica> replicas, DBConnection dbConn) throws SQLException {
1130
       
1131
        // remove existing values first
1132
        String delete = "delete from smReplicationStatus " + 
1133
        "where guid = ?";
1134
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1135
        //data values
1136
        stmt.setString(1, guid);
1137
        //execute
1138
        int deletedCount = stmt.executeUpdate();
1139
        stmt.close();
1140
        
1141
        if (replicas != null) {
1142
            for (Replica replica: replicas) {
1143
	            // Execute the insert statement
1144
	            String insert = "insert into smReplicationStatus " + 
1145
	                "(guid, member_node, status, date_verified) " +
1146
	                "values (?, ?, ?, ?)";
1147
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1148
	            
1149
	            //data values
1150
	            String memberNode = replica.getReplicaMemberNode().getValue();
1151
	            String status = replica.getReplicationStatus().toString();
1152
	            java.sql.Timestamp sqlDate = new java.sql.Timestamp(replica.getReplicaVerified().getTime());
1153
	            insertStatement.setString(1, guid);
1154
	            insertStatement.setString(2, memberNode);
1155
	            insertStatement.setString(3, status);
1156
	            insertStatement.setTimestamp(4, sqlDate);
1157

    
1158
	            logMetacat.debug("smReplicationStatus sql: " + insertStatement.toString());
1159
	            
1160
	            //execute
1161
	            int rows = insertStatement.executeUpdate();
1162
	            insertStatement.close();
1163
            }
1164
        }
1165
       
1166
    }
1167
    
1168
    /**
1169
     * Insert the system metadata fields into the db
1170
     * @param sm
1171
     * @throws McdbDocNotFoundException 
1172
     * @throws SQLException 
1173
     * @throws InvalidSystemMetadata 
1174
     * @throws AccessException 
1175
     */
1176
    public void updateSystemMetadata(SystemMetadata sm, DBConnection dbConn) 
1177
      throws McdbDocNotFoundException, SQLException, InvalidSystemMetadata, AccessException {
1178
    	
1179
      Boolean replicationAllowed = false;
1180
		  Integer numberReplicas = -1;
1181
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1182
    	if (replicationPolicy != null) {
1183
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1184
    		numberReplicas = replicationPolicy.getNumberReplicas();
1185
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1186
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1187
    	}
1188
    	
1189
    	// the main systemMetadata fields
1190
		  updateSystemMetadataFields(
1191
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1192
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(), 
1193
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(), 
1194
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm(), 
1195
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1196
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(), 
1197
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1198
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(), 
1199
		    sm.getIdentifier().getValue(),
1200
		    sm.getFormatId() == null ? null: sm.getFormatId().getValue(),
1201
		    sm.getSize(),
1202
		    sm.getArchived() == null ? false: sm.getArchived(),
1203
		    replicationAllowed, 
1204
		    numberReplicas,
1205
		    sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
1206
		    sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue(),
1207
		    sm.getSerialVersion(),
1208
		    dbConn
1209
        );
1210
        
1211
        String guid = sm.getIdentifier().getValue();
1212
        
1213
        // save replication policies
1214
        if (replicationPolicy != null) {
1215
		    List<String> nodes = null;
1216
		    String policy = null;
1217
		    
1218
		    // check for null 
1219
		    if (replicationPolicy.getBlockedMemberNodeList() != null) {
1220
			    nodes = new ArrayList<String>();
1221
			    policy = "blocked";
1222
			    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1223
			    	nodes.add(node.getValue());
1224
			    }
1225
			    this.insertReplicationPolicy(guid, policy, nodes, dbConn);
1226
		    }
1227
		    
1228
		    if (replicationPolicy.getPreferredMemberNodeList() != null) {
1229
			    nodes = new ArrayList<String>();
1230
			    policy = "preferred";
1231
			    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1232
			    	nodes.add(node.getValue());
1233
			    }
1234
		        this.insertReplicationPolicy(guid, policy, nodes, dbConn);
1235
		    }
1236
        }
1237
        
1238
        // save replica information
1239
        this.insertReplicationStatus(guid, sm.getReplicaList(), dbConn);
1240
        
1241
        // save access policy
1242
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1243
        if (accessPolicy != null) {
1244
			this.insertAccessPolicy(guid, accessPolicy);
1245
        }
1246
    }
1247
    
1248
    /**
1249
     * Creates Metacat access rules and inserts them
1250
     * @param accessPolicy
1251
     * @throws McdbDocNotFoundException
1252
     * @throws AccessException
1253
     */
1254
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1255
    	
1256
    	// check for the existing permOrder so that we remain compatible with it (DataONE does not care)
1257
        XMLAccessAccess accessController  = new XMLAccessAccess();
1258
		String existingPermOrder = AccessControlInterface.ALLOWFIRST;
1259
        Vector<XMLAccessDAO> existingAccess = accessController.getXMLAccessForDoc(guid);
1260
        if (existingAccess != null && existingAccess.size() > 0) {
1261
        	existingPermOrder = existingAccess.get(0).getPermOrder();
1262
        }
1263
        
1264
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1265
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1266
        	List<Subject> subjects = accessRule.getSubjectList();
1267
        	List<Permission> permissions = accessRule.getPermissionList();
1268
        	for (Subject subject: subjects) {
1269
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1270
        		accessDAO.setPrincipalName(subject.getValue());
1271
    			accessDAO.setGuid(guid);
1272
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1273
				accessDAO.setPermOrder(existingPermOrder);
1274
    			if (permissions != null) {
1275
	    			for (Permission permission: permissions) {
1276
	    				Long metacatPermission = new Long(convertPermission(permission));
1277
	        			accessDAO.addPermission(metacatPermission);
1278
	    			}
1279
    			}
1280
    			accessDAOs.add(accessDAO);
1281
        	}
1282
        }
1283
        
1284
        
1285
        // remove all existing allow records
1286
        accessController.deleteXMLAccessForDoc(guid, AccessControlInterface.ALLOW);
1287
        // add the ones we can for this guid
1288
        accessController.insertAccess(guid, accessDAOs);
1289
        
1290
        
1291
    }
1292
    
1293
    /**
1294
     * Lookup access policy from Metacat
1295
     * @param guid
1296
     * @return
1297
     * @throws McdbDocNotFoundException
1298
     * @throws AccessException
1299
     */
1300
    public AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1301
        AccessPolicy accessPolicy = new AccessPolicy();
1302

    
1303
    	// use GUID to look up the access
1304
        XMLAccessAccess accessController  = new XMLAccessAccess();
1305
        List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1306
        
1307
        for (XMLAccessDAO accessDAO: accessDAOs) {
1308
        	// only add allow rule
1309
        	if (accessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
1310
	        	AccessRule accessRule = new AccessRule();    	
1311
	        	List <Permission> permissions = convertPermission(accessDAO.getPermission().intValue());
1312
	        	// cannot include if we have no permissions
1313
	        	if (permissions == null || permissions.isEmpty()) {
1314
	        		logMetacat.warn("skipping empty access rule permissions for " + guid);
1315
	        		continue;
1316
	        	}
1317
	        	accessRule.setPermissionList(permissions);
1318
	        	Subject subject = new Subject();
1319
	        	subject.setValue(accessDAO.getPrincipalName());
1320
	        	accessRule.addSubject(subject);
1321
	            accessPolicy.addAllow(accessRule);
1322
        	}
1323
        }
1324
        return accessPolicy;
1325
    }
1326
    
1327
    public int convertPermission(Permission permission) {
1328
    	if (permission.equals(Permission.READ)) {
1329
    		return AccessControlInterface.READ;
1330
    	}
1331
    	if (permission.equals(Permission.WRITE)) {
1332
    		return AccessControlInterface.WRITE;
1333
    	}
1334
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1335
    		return AccessControlInterface.CHMOD;
1336
    	}
1337
		return -1;
1338
    }
1339
    
1340
    public List<Permission> convertPermission(int permission) {
1341
    	
1342
    	List<Permission> permissions = new ArrayList<Permission>();
1343
    	if (permission == AccessControlInterface.ALL) {
1344
    		permissions.add(Permission.READ);
1345
    		permissions.add(Permission.WRITE);
1346
    		permissions.add(Permission.CHANGE_PERMISSION);
1347
    		return permissions;
1348
    	}
1349
    	
1350
    	if ((permission & AccessControlInterface.CHMOD) == AccessControlInterface.CHMOD) {
1351
    		permissions.add(Permission.CHANGE_PERMISSION);
1352
    	}
1353
    	if ((permission & AccessControlInterface.READ) == AccessControlInterface.READ) {
1354
    		permissions.add(Permission.READ);
1355
    	}
1356
    	if ((permission & AccessControlInterface.WRITE) == AccessControlInterface.WRITE) {
1357
    		permissions.add(Permission.WRITE);
1358
    	}
1359
    	
1360
		return permissions;
1361
    }
1362
    
1363
    /**
1364
     * Lookup a localId given the GUID. If
1365
     * the identifier is not found, throw an exception.
1366
     * 
1367
     * @param guid the global identifier to look up
1368
     * @return String containing the corresponding LocalId
1369
     * @throws McdbDocNotFoundException if the identifier is not found
1370
     */
1371
    public String getLocalId(String guid) throws McdbDocNotFoundException {
1372
      
1373
      String db_guid = "";
1374
      String docid = "";
1375
      int rev = 0;
1376
      
1377
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1378
      
1379
      DBConnection dbConn = null;
1380
      int serialNumber = -1;
1381
      try {
1382
          // Get a database connection from the pool
1383
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1384
          serialNumber = dbConn.getCheckOutSerialNumber();
1385
          
1386
          // Execute the insert statement
1387
          PreparedStatement stmt = dbConn.prepareStatement(query);
1388
          stmt.setString(1, guid);
1389
          ResultSet rs = stmt.executeQuery();
1390
          if (rs.next()) {
1391
              db_guid = rs.getString(1);
1392
              docid = rs.getString(2);
1393
              rev = rs.getInt(3);
1394
              assert(db_guid.equals(guid));
1395
          } else {
1396
              throw new McdbDocNotFoundException("Document not found:" + guid);
1397
          }
1398
          stmt.close();
1399
      } catch (SQLException e) {
1400
          logMetacat.error("Error while looking up the local identifier: " 
1401
                  + e.getMessage());
1402
      } finally {
1403
          // Return database connection to the pool
1404
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1405
      }
1406
      return docid + "." + rev;
1407
    }
1408
    
1409
    /**
1410
     * query the systemmetadata table based on the given parameters
1411
     * @param startTime
1412
     * @param endTime
1413
     * @param objectFormat
1414
     * @param replicaStatus
1415
     * @param start
1416
     * @param count
1417
     * @return ObjectList
1418
     * @throws SQLException 
1419
     * @throws ServiceException 
1420
     * @throws PropertyNotFoundException 
1421
     */
1422
    public ObjectList querySystemMetadata(Date startTime, Date endTime,
1423
        ObjectFormatIdentifier objectFormatId, boolean replicaStatus,
1424
        int start, int count) 
1425
        throws SQLException, PropertyNotFoundException, ServiceException {
1426
        ObjectList ol = new ObjectList();
1427
        DBConnection dbConn = null;
1428
        int serialNumber = -1;
1429

    
1430
        try {
1431
            String fieldSql = "select guid, date_uploaded, rights_holder, checksum, "
1432
                    + "checksum_algorithm, origin_member_node, authoritive_member_node, "
1433
                    + "date_modified, submitter, object_format, size from systemmetadata";
1434
            
1435
            // handle special case quickly
1436
            String countSql = "select count(guid) from systemmetadata";
1437
            
1438
            // the clause
1439
            String whereClauseSql = "";
1440

    
1441
            boolean f1 = false;
1442
            boolean f2 = false;
1443
            boolean f3 = false;
1444

    
1445
            if (startTime != null) {
1446
                whereClauseSql += " where systemmetadata.date_modified >= ?";
1447
                f1 = true;
1448
            }
1449

    
1450
            if (endTime != null) {
1451
                if (!f1) {
1452
                    whereClauseSql += " where systemmetadata.date_modified < ?";
1453
                } else {
1454
                    whereClauseSql += " and systemmetadata.date_modified < ?";
1455
                }
1456
                f2 = true;
1457
            }
1458

    
1459
            if (objectFormatId != null) {
1460
                if (!f1 && !f2) {
1461
                    whereClauseSql += " where object_format = ?";
1462
                } else {
1463
                    whereClauseSql += " and object_format = ?";
1464
                }
1465
                f3 = true;
1466
            }
1467

    
1468
            if (!replicaStatus) {
1469
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.nodeId");
1470
                if (!f1 && !f2 && !f3) {
1471
                    whereClauseSql += " where authoritive_member_node = '" +
1472
                        currentNodeId.trim() + "'";
1473
                } else {
1474
                    whereClauseSql += " and authoritive_member_node = '" +
1475
                        currentNodeId.trim() + "'";
1476
                }
1477
            }
1478
            
1479
            // connection
1480
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1481
            serialNumber = dbConn.getCheckOutSerialNumber();
1482

    
1483
            // the field query
1484
            String orderBySql = " order by guid ";
1485
            String fieldQuery = fieldSql + whereClauseSql + orderBySql;
1486
            String finalQuery = DatabaseService.getInstance().getDBAdapter().getPagedQuery(fieldQuery, start, count);
1487
            PreparedStatement fieldStmt = dbConn.prepareStatement(finalQuery);
1488
            
1489
            // construct the count query and statment
1490
            String countQuery = countSql + whereClauseSql;
1491
            PreparedStatement countStmt = dbConn.prepareStatement(countQuery);
1492

    
1493
            if (f1 && f2 && f3) {
1494
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1495
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1496
                fieldStmt.setString(3, objectFormatId.getValue());
1497
                // count
1498
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1499
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1500
                countStmt.setString(3, objectFormatId.getValue());
1501
            } else if (f1 && f2 && !f3) {
1502
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1503
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1504
                // count
1505
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1506
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1507
            } else if (f1 && !f2 && f3) {
1508
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1509
                fieldStmt.setString(2, objectFormatId.getValue());
1510
                // count
1511
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1512
                countStmt.setString(2, objectFormatId.getValue());
1513
            } else if (f1 && !f2 && !f3) {
1514
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1515
                // count
1516
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1517
            } else if (!f1 && f2 && f3) {
1518
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1519
                fieldStmt.setString(2, objectFormatId.getValue());
1520
                // count
1521
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1522
                countStmt.setString(2, objectFormatId.getValue());
1523
            } else if (!f1 && !f2 && f3) {
1524
                fieldStmt.setString(1, objectFormatId.getValue());
1525
                // count
1526
                countStmt.setString(1, objectFormatId.getValue());
1527
            } else if (!f1 && f2 && !f3) {
1528
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1529
                // count
1530
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1531
            }
1532

    
1533
            logMetacat.debug("list objects fieldStmt: " + fieldStmt.toString());
1534
            
1535
            logMetacat.debug("list objects countStmt: " + countStmt.toString());
1536
            
1537
            // get the total object count no matter what
1538
            int total = 0;
1539
            ResultSet totalResult = countStmt.executeQuery();
1540
            if (totalResult.next()) {
1541
            	total = totalResult.getInt(1);
1542
            }
1543
            
1544
            logMetacat.debug("list objects total: " + total);
1545

    
1546
        	// set the totals
1547
        	ol.setStart(start);
1548
            ol.setCount(count);
1549
            ol.setTotal(total);
1550
            
1551
            // retrieve the actual records if requested
1552
            if (count != 0) {
1553
            	
1554
                ResultSet rs = fieldStmt.executeQuery();
1555
	            while (rs.next()) {                
1556
	                
1557
	                String guid = rs.getString(1);
1558
	                logMetacat.debug("query found object with guid " + guid);
1559
	                // Timestamp dateUploaded = rs.getTimestamp(2);
1560
	                // String rightsHolder = rs.getString(3);
1561
	                String checksum = rs.getString(4);
1562
	                String checksumAlgorithm = rs.getString(5);
1563
	                // String originMemberNode = rs.getString(6);
1564
	                // String authoritiveMemberNode = rs.getString(7);
1565
	                Timestamp dateModified = rs.getTimestamp(8);
1566
	                // String submitter = rs.getString(9);
1567
	                String fmtidStr = rs.getString(10);
1568
	                String sz = rs.getString(11);
1569
	                BigInteger size = new BigInteger("0");
1570
	
1571
	                if (sz != null && !sz.trim().equals("")) {
1572
	                    size = new BigInteger(rs.getString(11));
1573
	                }
1574
	
1575
	                ObjectInfo oi = new ObjectInfo();
1576
	
1577
	                Identifier id = new Identifier();
1578
	                id.setValue(guid);
1579
	                oi.setIdentifier(id);
1580
	
1581
	                if (dateModified != null) {
1582
	                    oi.setDateSysMetadataModified(dateModified);
1583
	                }
1584
	
1585
	                Checksum cs = new Checksum();
1586
	                cs.setValue(checksum);
1587
	                try {
1588
	                    // cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1589
	                    cs.setAlgorithm(checksumAlgorithm);
1590
	                } catch (Exception e) {
1591
	                    logMetacat.error("could not parse checksum algorithm", e);
1592
	                    continue;
1593
	                }
1594
	                oi.setChecksum(cs);
1595
	
1596
	                // set the format type
1597
	                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
1598
	                fmtid.setValue(fmtidStr);
1599
	                oi.setFormatId(fmtid);
1600
	
1601
	                oi.setSize(size);
1602
	
1603
	                ol.addObjectInfo(oi);                    
1604

    
1605
	            }
1606
	            
1607
	            logMetacat.debug("list objects count: " + ol.sizeObjectInfoList());
1608

    
1609
	            // set the actual count retrieved
1610
	            ol.setCount(ol.sizeObjectInfoList());
1611
	
1612
	        }
1613
            
1614
        }
1615

    
1616
        finally {
1617
            // Return database connection to the pool
1618
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1619
        }
1620

    
1621
        return ol;
1622
    }
1623
    
1624
    /**
1625
     * create a mapping in the identifier table
1626
     * @param guid
1627
     * @param localId
1628
     */
1629
    public void createMapping(String guid, String localId)
1630
    {        
1631
        
1632
        int serialNumber = -1;
1633
        DBConnection dbConn = null;
1634
        try {
1635

    
1636
            // Parse the localId into scope and rev parts
1637
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1638
            String docid = acc.getDocid();
1639
            int rev = 1;
1640
            if (acc.getRev() != null) {
1641
              rev = (new Integer(acc.getRev()).intValue());
1642
            }
1643

    
1644
            // Get a database connection from the pool
1645
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1646
            serialNumber = dbConn.getCheckOutSerialNumber();
1647

    
1648
            // Execute the insert statement
1649
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1650
            PreparedStatement stmt = dbConn.prepareStatement(query);
1651
            stmt.setString(1, guid);
1652
            stmt.setString(2, docid);
1653
            stmt.setInt(3, rev);
1654
            logMetacat.debug("mapping query: " + stmt.toString());
1655
            int rows = stmt.executeUpdate();
1656

    
1657
            stmt.close();
1658
        } catch (SQLException e) {
1659
            e.printStackTrace();
1660
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1661
                    + e.getMessage());
1662
        } catch (NumberFormatException e) {
1663
            e.printStackTrace();
1664
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1665
                    + e.getMessage());
1666
        } catch (AccessionNumberException e) {
1667
            e.printStackTrace();
1668
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1669
                    + e.getMessage());
1670
        } finally {
1671
            // Return database connection to the pool
1672
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1673
        }
1674
    }
1675
    
1676
    /**
1677
     * remove a mapping in the identifier table
1678
     * @param guid
1679
     * @param localId
1680
     */
1681
    public void removeMapping(String guid, String localId)
1682
    {        
1683
        
1684
        int serialNumber = -1;
1685
        DBConnection dbConn = null;
1686
        try {
1687

    
1688
            // Parse the localId into scope and rev parts
1689
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1690
            String docid = acc.getDocid();
1691
            int rev = 1;
1692
            if (acc.getRev() != null) {
1693
              rev = (new Integer(acc.getRev()).intValue());
1694
            }
1695

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

    
1700
            // Execute the insert statement
1701
            String query = "DELETE FROM " + TYPE_IDENTIFIER + " WHERE guid = ? AND docid = ? AND rev = ?";
1702
            PreparedStatement stmt = dbConn.prepareStatement(query);
1703
            stmt.setString(1, guid);
1704
            stmt.setString(2, docid);
1705
            stmt.setInt(3, rev);
1706
            logMetacat.debug("remove mapping query: " + stmt.toString());
1707
            int rows = stmt.executeUpdate();
1708

    
1709
            stmt.close();
1710
        } catch (SQLException e) {
1711
            e.printStackTrace();
1712
            logMetacat.error("removeMapping: SQL error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1713
                    + e.getMessage());
1714
        } catch (NumberFormatException e) {
1715
            e.printStackTrace();
1716
            logMetacat.error("removeMapping: NumberFormat error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1717
                    + e.getMessage());
1718
        } catch (AccessionNumberException e) {
1719
            e.printStackTrace();
1720
            logMetacat.error("removeMapping: AccessionNumber error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1721
                    + e.getMessage());
1722
        } finally {
1723
            // Return database connection to the pool
1724
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1725
        }
1726
    }
1727
    
1728
    /**
1729
     * create the systemmetadata record
1730
     * @param guid
1731
     * @param dbConn 
1732
     * @throws SQLException 
1733
     */
1734
    private void insertSystemMetadata(String guid, DBConnection dbConn) throws SQLException
1735
    {        
1736

    
1737
        // Execute the insert statement
1738
        String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1739
        PreparedStatement stmt = dbConn.prepareStatement(query);
1740
        stmt.setString(1, guid);
1741
        logMetacat.debug("system metadata query: " + stmt.toString());
1742
        int rows = stmt.executeUpdate();
1743

    
1744
        stmt.close();
1745
        
1746
    }
1747
    
1748
    public void deleteSystemMetadata(String guid)
1749
    {        
1750
        
1751
        int serialNumber = -1;
1752
        DBConnection dbConn = null;
1753
        String query = null;
1754
        PreparedStatement stmt = null;
1755
        int rows = 0;
1756
        try {
1757

    
1758
            // Get a database connection from the pool
1759
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.deleteSystemMetadata");
1760
            serialNumber = dbConn.getCheckOutSerialNumber();
1761

    
1762
            // remove main system metadata entry
1763
            query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
1764
            stmt = dbConn.prepareStatement(query);
1765
            stmt.setString(1, guid);
1766
            logMetacat.debug("delete system metadata: " + stmt.toString());
1767
            rows = stmt.executeUpdate();
1768
            stmt.close();
1769
            
1770
            // remove the smReplicationPolicy
1771
            query = "delete from smReplicationPolicy " + 
1772
            "where guid = ?";
1773
            stmt = dbConn.prepareStatement(query);
1774
            stmt.setString(1, guid);
1775
            logMetacat.debug("delete smReplicationPolicy: " + stmt.toString());
1776
            rows = stmt.executeUpdate();
1777
            stmt.close();
1778
            
1779
            // remove the smReplicationStatus
1780
            query = "delete from smReplicationStatus " + 
1781
            "where guid = ?";
1782
            stmt = dbConn.prepareStatement(query);
1783
            stmt.setString(1, guid);
1784
            logMetacat.debug("delete smReplicationStatus: " + stmt.toString());
1785
            rows = stmt.executeUpdate();
1786
            stmt.close();
1787
            
1788
            // TODO: remove the access?
1789
            // Metacat keeps "deleted" documents so we should not remove access rules.
1790
            
1791
        } catch (Exception e) {
1792
            e.printStackTrace();
1793
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1794
            try {
1795
				dbConn.rollback();
1796
			} catch (SQLException sqle) {
1797
	            logMetacat.error("Error while rolling back delete for record: " + guid, sqle );
1798
			}
1799
        } finally {
1800
            // Return database connection to the pool
1801
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1802
        }
1803
    }
1804
    
1805
    public void updateAuthoritativeMemberNodeId(String existingMemberNodeId, String newMemberNodeId)
1806
    {
1807
        DBConnection dbConn = null;
1808
        int serialNumber = -1;
1809
        
1810
        try {
1811
            // Get a database connection from the pool
1812
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.updateAuthoritativeMemberNodeId");
1813
            serialNumber = dbConn.getCheckOutSerialNumber();
1814

    
1815
            // Execute the insert statement
1816
            String query = "update " + TYPE_SYSTEM_METADATA + 
1817
                " set authoritive_member_node = ? " +
1818
                " where authoritive_member_node = ?";
1819
            PreparedStatement stmt = dbConn.prepareStatement(query);
1820
            
1821
            //data values
1822
            stmt.setString(1, newMemberNodeId);
1823
            stmt.setString(2, existingMemberNodeId);
1824

    
1825
            logMetacat.debug("stmt: " + stmt.toString());
1826
            //execute
1827
            int rows = stmt.executeUpdate();
1828

    
1829
            stmt.close();
1830
        } catch (SQLException e) {
1831
            e.printStackTrace();
1832
            logMetacat.error("updateSystemMetadataFields: SQL error while updating system metadata: " 
1833
                    + e.getMessage());
1834
        } catch (NumberFormatException e) {
1835
            e.printStackTrace();
1836
            logMetacat.error("updateSystemMetadataFields: NumberFormat error while updating system metadata: " 
1837
                    + e.getMessage());
1838
        } finally {
1839
            // Return database connection to the pool
1840
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1841
        }
1842
    }
1843
}
1844

    
(36-36/63)