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.HashMap;
35
import java.util.Hashtable;
36
import java.util.List;
37
import java.util.Vector;
38

    
39
import org.apache.log4j.Logger;
40
import org.dataone.client.v2.formats.ObjectFormatCache;
41
import org.dataone.service.exceptions.BaseException;
42
import org.dataone.service.exceptions.InvalidSystemMetadata;
43
import org.dataone.service.types.v1.AccessPolicy;
44
import org.dataone.service.types.v1.AccessRule;
45
import org.dataone.service.types.v1.Checksum;
46
import org.dataone.service.types.v1.Identifier;
47
import org.dataone.service.types.v1.NodeReference;
48
import org.dataone.service.types.v1.ObjectFormatIdentifier;
49
import org.dataone.service.types.v1.ObjectInfo;
50
import org.dataone.service.types.v1.ObjectList;
51
import org.dataone.service.types.v1.Permission;
52
import org.dataone.service.types.v1.Replica;
53
import org.dataone.service.types.v1.ReplicationPolicy;
54
import org.dataone.service.types.v1.ReplicationStatus;
55
import org.dataone.service.types.v1.Subject;
56
import org.dataone.service.types.v2.MediaType;
57
import org.dataone.service.types.v2.MediaTypeProperty;
58
import org.dataone.service.types.v2.SystemMetadata;
59

    
60
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
61
import edu.ucsb.nceas.metacat.database.DBConnection;
62
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
63
import edu.ucsb.nceas.metacat.database.DatabaseService;
64
import edu.ucsb.nceas.metacat.dataone.hazelcast.HazelcastService;
65
import edu.ucsb.nceas.metacat.properties.PropertyService;
66
import edu.ucsb.nceas.metacat.shared.AccessException;
67
import edu.ucsb.nceas.metacat.shared.ServiceException;
68
import edu.ucsb.nceas.metacat.util.DocumentUtil;
69
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
70
import edu.ucsb.nceas.utilities.access.AccessControlInterface;
71
import edu.ucsb.nceas.utilities.access.XMLAccessDAO;
72

    
73
/**
74
 * Manage the relationship between Metacat local identifiers (LocalIDs) that are
75
 * codified as the (docid, rev) pair with globally unique string identifiers
76
 * (GUIDs) that are opaque strings.  This class provides methods to manage these
77
 * identifiers, and to search for and look up LocalIDs based on their GUID and
78
 * vice versa. IdentifierManager is a singleton.
79
 * 
80
 * @author Matthew Jones
81
 */
82
public class IdentifierManager {
83
    
84
    public static final String TYPE_SYSTEM_METADATA = "systemmetadata";
85
    public static final String TYPE_IDENTIFIER = "identifier";
86
  
87
    /**
88
     * The single instance of the manager that is always returned.
89
     */
90
    private static IdentifierManager self = null;
91
    private Logger logMetacat = Logger.getLogger(IdentifierManager.class);
92

    
93
    /**
94
     * A private constructor that initializes the class when getInstance() is
95
     * called.
96
     */
97
    private IdentifierManager() {}
98

    
99
    /**
100
     * Return the single instance of the manager after initializing it if it
101
     * wasn't previously initialized.
102
     * 
103
     * @return the single IdentifierManager instance
104
     */
105
    public static IdentifierManager getInstance()
106
    {
107
        if (self == null) {
108
            self = new IdentifierManager();
109
        }
110
        return self;
111
    }
112
    
113
    /*public SystemMetadata asSystemMetadata(Date dateUploaded, String rightsHolder,
114
            String checksum, String checksumAlgorithm, String originMemberNode,
115
            String authoritativeMemberNode, Date dateModified, String submitter, 
116
            String guid, String fmtidStr, BigInteger size, BigInteger serialVersion) {
117
        SystemMetadata sysMeta = new SystemMetadata();
118

    
119
        Identifier sysMetaId = new Identifier();
120
        sysMetaId.setValue(guid);
121
        sysMeta.setIdentifier(sysMetaId);
122
        sysMeta.setDateUploaded(dateUploaded);
123
        Subject rightsHolderSubject = new Subject();
124
        rightsHolderSubject.setValue(rightsHolder);
125
        sysMeta.setRightsHolder(rightsHolderSubject);
126
        Checksum checksumObject = new Checksum();
127
        checksumObject.setValue(checksum);
128
        checksumObject.setAlgorithm(checksumAlgorithm);
129
        sysMeta.setChecksum(checksumObject);
130
        NodeReference omn = new NodeReference();
131
        omn.setValue(originMemberNode);
132
        sysMeta.setOriginMemberNode(omn);
133
        NodeReference amn = new NodeReference();
134
        amn.setValue(authoritativeMemberNode);
135
        sysMeta.setAuthoritativeMemberNode(amn);
136
        sysMeta.setDateSysMetadataModified(dateModified);
137
        Subject submitterSubject = new Subject();
138
        submitterSubject.setValue(submitter);
139
        sysMeta.setSubmitter(submitterSubject);
140
        ObjectFormatIdentifier fmtid = null;
141
        try {
142
        	ObjectFormatIdentifier formatId = new ObjectFormatIdentifier();
143
        	formatId.setValue(fmtidStr);
144
        	fmtid = ObjectFormatCache.getInstance().getFormat(formatId).getFormatId();
145
        	sysMeta.setFormatId(fmtid);
146
        	
147
        } catch (BaseException nfe) {
148
            logMetacat.error("The objectFormat " + fmtidStr +
149
          	" is not registered. Setting the default format id.");
150
            fmtid = new ObjectFormatIdentifier();
151
            fmtid.setValue("application/octet-stream");
152
            sysMeta.setFormatId(fmtid);
153
            
154
        }
155
        sysMeta.setSize(size);
156
        sysMeta.setSerialVersion(serialVersion);
157
        
158
        return sysMeta;
159
    }*/
160
    
161
    /**
162
     * return a hash of all of the info that is in the systemmetadata table
163
     * @param localId
164
     * @return
165
     */
166
    /*public Hashtable<String, String> getSystemMetadataInfo(String localId)
167
    throws McdbDocNotFoundException
168
    {
169
        try
170
        {
171
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
172
            localId = acc.getDocid();
173
        }
174
        catch(Exception e)
175
        {
176
            //do nothing. just try the localId as it is
177
        }
178
        Hashtable<String, String> h = new Hashtable<String, String>();
179
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
180
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size " +
181
          "from systemmetadata where docid = ?";
182
        DBConnection dbConn = null;
183
        int serialNumber = -1;
184
        try 
185
        {
186
            // Get a database connection from the pool
187
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
188
            serialNumber = dbConn.getCheckOutSerialNumber();
189

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

    
266
        try 
267
        {
268
            // Get a database connection from the pool
269
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getSystemMetadata");
270
            serialNumber = dbConn.getCheckOutSerialNumber();
271

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

    
298
                Identifier sysMetaId = new Identifier();
299
                sysMetaId.setValue(guid);
300
                sysMeta.setIdentifier(sysMetaId);
301
                sysMeta.setSerialVersion(serialVersion);
302
                sysMeta.setDateUploaded(dateUploaded);
303
                Subject rightsHolderSubject = new Subject();
304
                rightsHolderSubject.setValue(rightsHolder);
305
                sysMeta.setRightsHolder(rightsHolderSubject);
306
                Checksum checksumObject = new Checksum();
307
                checksumObject.setValue(checksum);
308
                checksumObject.setAlgorithm(checksumAlgorithm);
309
                sysMeta.setChecksum(checksumObject);
310
                if (originMemberNode != null) {
311
	                NodeReference omn = new NodeReference();
312
	                omn.setValue(originMemberNode);
313
	                sysMeta.setOriginMemberNode(omn);
314
                }
315
                if (authoritativeMemberNode != null) {
316
	                NodeReference amn = new NodeReference();
317
	                amn.setValue(authoritativeMemberNode);
318
	                sysMeta.setAuthoritativeMemberNode(amn);
319
                }
320
                sysMeta.setDateSysMetadataModified(dateModified);
321
                if (submitter != null) {
322
	                Subject submitterSubject = new Subject();
323
	                submitterSubject.setValue(submitter);
324
	                sysMeta.setSubmitter(submitterSubject);
325
                }
326
                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
327
                fmtid.setValue(fmtidStr);
328
            	sysMeta.setFormatId(fmtid);
329
                sysMeta.setSize(size);
330
                if (obsoletes != null) {
331
	                Identifier obsoletesId = new Identifier();
332
	                obsoletesId.setValue(obsoletes);
333
	                sysMeta.setObsoletes(obsoletesId);
334
                }
335
                if (obsoletedBy != null) {
336
		            Identifier obsoletedById = new Identifier();
337
		            obsoletedById.setValue(obsoletedBy);
338
		            sysMeta.setObsoletedBy(obsoletedById);
339
                }
340
                sysMeta.setArchived(archived);
341
                if(series_id != null) {
342
                    Identifier seriesId = new Identifier();
343
                    seriesId.setValue(series_id);
344
                    sysMeta.setSeriesId(seriesId);
345
                }
346
                if(file_name != null ) {
347
                    sysMeta.setFileName(file_name);
348
                }
349
                
350
                if(media_type != null ) {
351
                    MediaType mediaType = new MediaType();
352
                    mediaType.setName(media_type);
353
                    // get media type properties from another table.
354
                    String mediaTypePropertyQuery = "select name, value from smmediatypeproperties where guid = ?";
355
                    PreparedStatement stmt2 = dbConn.prepareStatement(mediaTypePropertyQuery);
356
                    stmt2.setString(1, guid);
357
                    ResultSet rs2 = stmt2.executeQuery();
358
                    while (rs2.next()) {
359
                        String name = rs2.getString(1);
360
                        String value = rs2.getString(2);
361
                        MediaTypeProperty property = new MediaTypeProperty();
362
                        property.setName(name);
363
                        property.setValue(value);
364
                        mediaType.addProperty(property);
365
                    }
366
                    sysMeta.setMediaType(mediaType);
367
                    rs2.close();
368
                    stmt2.close();
369
                }
370
                stmt.close();
371
            } 
372
            else
373
            {
374
                stmt.close();
375
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
376
                throw new McdbDocNotFoundException("Could not find " + guid);
377
            }
378
            
379
        } 
380
        catch (SQLException e) 
381
        {
382
            e.printStackTrace();
383
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "  
384
                    + e.getMessage());
385
        } 
386
        finally 
387
        {
388
            // Return database connection to the pool
389
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
390
        }
391

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

    
531
            // Execute the insert statement
532
            PreparedStatement stmt = dbConn.prepareStatement(sql);
533
            stmt.setString(1, localId);
534
            ResultSet rs = stmt.executeQuery();
535
            if (rs.next()) 
536
            {
537
                rev = rs.getInt(1);
538
                stmt.close();
539
            } 
540
            else
541
            {
542
                stmt.close();
543
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
544
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
545
            }
546
        } 
547
        catch (SQLException e) 
548
        {
549
            logMetacat.error("Error while looking up the guid: " 
550
                    + e.getMessage());
551
        } 
552
        finally 
553
        {
554
            // Return database connection to the pool
555
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
556
        }
557
        return rev;
558
    }
559
    
560
    /**
561
     * return all local ids in the object store that do not have associated
562
     * system metadata
563
     */
564
    public List<String> getLocalIdsWithNoSystemMetadata(boolean includeRevisions, int serverLocation)
565
    {
566
        Vector<String> ids = new Vector<String>();
567
        String sql = "select docid, rev from xml_documents " +
568
        		"where docid not in " +
569
        		"(select docid from identifier where guid in (select guid from systemmetadata))";
570
        if (serverLocation > 0) {
571
        	sql = sql + " and server_location = ? ";
572
        }
573
        
574
        String revisionSql = "select docid, rev from xml_revisions " +
575
				"where docid not in " +
576
				"(select docid from identifier where guid in (select guid from systemmetadata))";
577
        if (serverLocation > 0) {
578
        	revisionSql = revisionSql + " and server_location = ? ";
579
        }
580
        
581
        if (includeRevisions) {
582
        	sql = sql + " UNION ALL " + revisionSql;
583
        }
584
        
585
        DBConnection dbConn = null;
586
        int serialNumber = -1;
587
        try 
588
        {
589
            // Get a database connection from the pool
590
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
591
            serialNumber = dbConn.getCheckOutSerialNumber();
592

    
593
            // Execute the insert statement
594
            PreparedStatement stmt = dbConn.prepareStatement(sql);
595
            // set params based on what we have in the query string
596
            if (serverLocation > 0) {
597
            	stmt.setInt(1, serverLocation);
598
            	if (includeRevisions) {
599
            		stmt.setInt(2, serverLocation);
600
            	}
601
            }
602
            ResultSet rs = stmt.executeQuery();
603
            while (rs.next()) 
604
            {
605
                String localid = rs.getString(1);
606
                String rev = rs.getString(2);
607
                localid += "." + rev;
608
                logMetacat.debug("id to add SM for: " + localid);
609
                ids.add(localid);
610
            } 
611
            stmt.close();
612
        } 
613
        catch (SQLException e) 
614
        {
615
            logMetacat.error("Error while looking up the guid: " 
616
                    + e.getMessage());
617
        } 
618
        finally 
619
        {
620
            // Return database connection to the pool
621
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
622
        }
623
        
624
        return ids;
625
    }
626
    
627
    /**
628
     * return a listing of all local ids in the object store
629
     * @return a list of all local ids in metacat
630
     */
631
    public List<String> getAllLocalIds()
632
    // seems to be an unnecessary and restrictive throw -rnahf 13-Sep-2011
633
    //    throws Exception
634
    {
635
        Vector<String> ids = new Vector<String>();
636
        String sql = "select docid from xml_documents";
637
        DBConnection dbConn = null;
638
        int serialNumber = -1;
639
        try 
640
        {
641
            // Get a database connection from the pool
642
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
643
            serialNumber = dbConn.getCheckOutSerialNumber();
644

    
645
            // Execute the insert statement
646
            PreparedStatement stmt = dbConn.prepareStatement(sql);
647
            ResultSet rs = stmt.executeQuery();
648
            while (rs.next()) 
649
            {
650
                String localid = rs.getString(1);
651
                ids.add(localid);
652
            } 
653
            stmt.close();
654
        } 
655
        catch (SQLException e) 
656
        {
657
            logMetacat.error("Error while looking up the guid: " 
658
                    + e.getMessage());
659
        } 
660
        finally 
661
        {
662
            // Return database connection to the pool
663
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
664
        }
665
        return ids;
666
    }
667
    
668
    
669
    /**
670
     * return a listing of all guids in the object store
671
     * @return a list of all GUIDs in metacat
672
     */
673
    public List<String> getAllSystemMetadataGUIDs()
674
    {
675
        Vector<String> guids = new Vector<String>();
676
        String sql = "select guid from systemmetadata";
677
        DBConnection dbConn = null;
678
        int serialNumber = -1;
679
        try 
680
        {
681
            // Get a database connection from the pool
682
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllGUIDs");
683
            serialNumber = dbConn.getCheckOutSerialNumber();
684

    
685
            // Execute the insert statement
686
            PreparedStatement stmt = dbConn.prepareStatement(sql);
687
            ResultSet rs = stmt.executeQuery();
688
            while (rs.next()) 
689
            {
690
                String guid = rs.getString(1);
691
                guids.add(guid);
692
            } 
693
            stmt.close();
694
        } 
695
        catch (SQLException e) 
696
        {
697
            logMetacat.error("Error while retrieving the guid: " 
698
                    + e.getMessage());
699
        } 
700
        finally 
701
        {
702
            // Return database connection to the pool
703
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
704
        }
705
        return guids;
706
    }
707
    
708
    
709
    
710
    /**
711
     * returns a list of system metadata-only guids since the given date
712
     * @return a list of system ids in metacat that do not correspond to objects
713
     * TODO: need to check which server they are on
714
     */
715
    public List<String> getUpdatedSystemMetadataIds(Date since)
716
       throws Exception
717
    {
718
        List<String> ids = new Vector<String>();
719
        String sql = 
720
        	"select guid from " + TYPE_SYSTEM_METADATA +
721
        	" where guid not in " +
722
        	" (select guid from " + TYPE_IDENTIFIER + ") " +
723
        	" and date_modified > ?";
724
        DBConnection dbConn = null;
725
        int serialNumber = -1;
726
        try 
727
        {
728
            // Get a database connection from the pool
729
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getUpdatedSystemMetadataIds");
730
            serialNumber = dbConn.getCheckOutSerialNumber();
731

    
732
            // Execute the insert statement
733
            PreparedStatement stmt = dbConn.prepareStatement(sql);
734
            stmt.setDate(1, new java.sql.Date(since.getTime()));
735
            ResultSet rs = stmt.executeQuery();
736
            while (rs.next()) 
737
            {
738
                String guid = rs.getString(1);
739
                ids.add(guid);
740
            } 
741
            stmt.close();
742
        } 
743
        catch (SQLException e) 
744
        {
745
            logMetacat.error("Error while looking up the updated guids: " 
746
                    + e.getMessage());
747
        } 
748
        finally 
749
        {
750
            // Return database connection to the pool
751
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
752
        }
753
        return ids;
754
    }
755
    
756
    /**
757
     * returns a list of system metadata-only guids since the given date
758
     * @return a list of system ids in metacat that do not correspond to objects
759
     * TODO: need to check which server they are on
760
     */
761
    public Date getLastModifiedDate() throws Exception {
762
        Date maxDate = null;
763

    
764
        List<String> ids = new Vector<String>();
765
        String sql = 
766
        	"select max(date_modified) from " + TYPE_SYSTEM_METADATA;
767
        DBConnection dbConn = null;
768
        int serialNumber = -1;
769
        try 
770
        {
771
            // Get a database connection from the pool
772
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLastModifiedDate");
773
            serialNumber = dbConn.getCheckOutSerialNumber();
774

    
775
            // Execute the insert statement
776
            PreparedStatement stmt = dbConn.prepareStatement(sql);
777
            ResultSet rs = stmt.executeQuery();
778
            if (rs.next()) {
779
            	maxDate = rs.getDate(1);
780
            } 
781
            stmt.close();
782
        } 
783
        catch (SQLException e) 
784
        {
785
            logMetacat.error("Error while looking up the latest update date: " 
786
                    + e.getMessage());
787
        } 
788
        finally 
789
        {
790
            // Return database connection to the pool
791
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
792
        }
793
        return maxDate;
794
    }
795

    
796
    
797
    /**
798
     * Determine if an identifier exists already, returning true if so.
799
     * NOTE: looks in the identifier and system metadata table for a match
800
     * (in that order)
801
     * 
802
     * @param guid the global identifier to look up
803
     * @return boolean true if the identifier exists
804
     */
805
    public boolean identifierExists(String guid) throws SQLException
806
    {
807
        boolean idExists = false;
808
        try {
809
            String id = getLocalId(guid);
810
            if (id != null) {
811
                idExists = true;
812
            }
813
        } catch (McdbDocNotFoundException e) {
814
        	// try system metadata only
815
        	    //this will check if the guid field on the system metadata table has the id
816
        		idExists = systemMetadataPIDExists(guid);
817
        		if(!idExists) {
818
        		    //if the guid field of the system metadata table doesn't have the id,
819
        		    //we will check if the serial_id field of the system metadata table has it
820
        		    idExists=systemMetadataSIDExists(guid);
821
        		}
822
            
823
        }
824
        return idExists;
825
    }
826
    
827
    /**
828
     * Determine if an identifier mapping exists already, 
829
     * returning true if so.
830
     * 
831
     * @param guid the global identifier to look up
832
     * @return boolean true if the identifier exists
833
     */
834
    public boolean mappingExists(String guid) throws SQLException
835
    {
836
        boolean idExists = false;
837
        try {
838
            String id = getLocalId(guid);
839
            if (id != null) {
840
                idExists = true;
841
            }
842
        } catch (McdbDocNotFoundException e) {
843
        	// nope!
844
        }
845
        return idExists;
846
    }
847
    
848
    /**
849
     * 
850
     * @param guid
851
     * @param rev
852
     * @return
853
     */
854
    public String generateLocalId(String guid, int rev)
855
    {
856
        return generateLocalId(guid, rev, false);
857
    }
858

    
859
    /**
860
     * Given a global identifier (guid), create a suitable local identifier that
861
     * follows Metacat's docid semantics and format (scope.id.rev), and create
862
     * a mapping between these two identifiers.  This effectively reserves both
863
     * the global and the local identifier, as they will now be present in the
864
     * identifier mapping table.  
865
     * 
866
     * REMOVED feature: If the incoming guid has the syntax of a
867
     * Metacat docid (scope.id.rev), then simply use it.
868
     * WHY: because "test.1.001" becomes "test.1.1" which is not correct for DataONE
869
     * identifier use (those revision numbers are just chartacters and should not be interpreted)
870
     * 
871
     * @param guid the global string identifier
872
     * @param rev the revision number to be used in the localId
873
     * @return String containing the localId to be used for Metacat operations
874
     */
875
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata) 
876
    {
877
        String localId = "";
878
        boolean conformsToDocidFormat = false;
879
        
880
        // BRL -- do not allow Metacat-conforming IDs to be used:
881
        // test.1.001 becomes test.1.1 which is NOT correct for DataONE identifiers
882
        // Check if the guid passed in is already in docid (scope.id.rev) format
883
//        try {
884
//            AccessionNumber acc = new AccessionNumber(guid, "NONE");
885
//            if (new Integer(acc.getRev()).intValue() > 0) {
886
//                conformsToDocidFormat = true;
887
//            }
888
//        } catch (NumberFormatException e) {
889
//            // No action needed, simply detecting invalid AccessionNumbers
890
//        } catch (AccessionNumberException e) {
891
//            // No action needed, simply detecting invalid AccessionNumbers
892
//        } catch (SQLException e) {
893
//            // No action needed, simply detecting invalid AccessionNumbers
894
//        }
895
        
896
        if (conformsToDocidFormat) {
897
            // if it conforms, use it for both guid and localId
898
            localId = guid;
899
        } else {
900
            // if not, then generate a new unique localId
901
            localId = DocumentUtil.generateDocumentId(rev);
902
        }
903
        
904
        // Register this new pair in the identifier mapping table
905
        logMetacat.debug("creating mapping in generateLocalId");
906
        if(!isSystemMetadata)
907
        { //don't do this if we're generating for system metadata
908
            createMapping(guid, localId);
909
        }
910
        
911
        return localId;
912
    }
913
    
914
    /**
915
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
916
     * if the docid, rev is not found in the identifiers or systemmetadata tables
917
     *
918
     * @param docid the docid to look up
919
     * @param rev the revision of the docid to look up
920
     * @return String containing the mapped guid
921
     * @throws McdbDocNotFoundException if the docid, rev is not found
922
     */
923
    public String getGUID(String docid, int rev)
924
      throws McdbDocNotFoundException
925
    {
926
        logMetacat.debug("getting guid for " + docid);
927
        String query = "select guid from identifier where docid = ? and rev = ?";
928
        String guid = null;
929
        
930
        DBConnection dbConn = null;
931
        int serialNumber = -1;
932
        PreparedStatement stmt = null;
933
        try {
934
            // Get a database connection from the pool
935
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
936
            serialNumber = dbConn.getCheckOutSerialNumber();
937
            
938
            // Execute the insert statement
939
            stmt = dbConn.prepareStatement(query);
940
            stmt.setString(1, docid);
941
            stmt.setInt(2, rev);
942
            ResultSet rs = stmt.executeQuery();
943
            if (rs.next()) 
944
            {
945
                guid = rs.getString(1);
946
            } 
947
            else
948
            {
949
            	throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
950
            }
951
            if(rs != null) {
952
                rs.close();
953
            }
954
        } catch (SQLException e) {
955
            logMetacat.error("Error while looking up the guid: " 
956
                    + e.getMessage());
957
        } finally {
958
            try {
959
                if(stmt != null) {
960
                    stmt.close();
961
                }
962
            } catch (Exception e) {
963
                logMetacat.warn("Couldn't close the prepared statement since "+e.getMessage());
964
            } finally {
965
                // Return database connection to the pool
966
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
967
            }
968
            
969
        }
970
        
971
        return guid;
972
    }
973
    
974
    /**
975
     * Get the pid of the head (current) version of objects match the specified sid.
976
     * 1. locate all candidate chain-ends for S1:
977
     *      determined by:  seriesId == S1 AND (obsoletedBy == null  OR obsoletedBy.seriesId != S1) // these are the type1 and type2 ends
978
     *      If obsoletedBy is missing, we generally consider it a type 2 end except:
979
     *      there is another object in the chain (has the same series id) that obsoletes the missing object. 
980
     * 2. if only 1 candidate chain-end, return it as the HEAD
981
     * 3. otherwise return the one in the chain with the latest dateUploaded value. However, we find that dateUpload doesn't refect the obsoletes information
982
     * (espically on the cn), so we will check osoletes information as well. https://redmine.dataone.org/issues/7624
983
     * @param sid specified sid which should match.
984
     * @return the pid of the head version. The null will be returned if there is no pid found.
985
     * @throws SQLException 
986
     */
987
    public Identifier getHeadPID(Identifier sid) throws SQLException {
988
        Identifier pid = null;
989
        if(sid != null && sid.getValue() != null && !sid.getValue().trim().equals("")) {
990
            logMetacat.debug("getting pid of the head version for matching the sid: " + sid.getValue());
991
            String sql = "select guid, obsoleted_by, obsoletes from systemMetadata where series_id = ? order by date_uploaded DESC";
992
            DBConnection dbConn = null;
993
            int serialNumber = -1;
994
            PreparedStatement stmt = null;
995
            PreparedStatement stmt2 = null;
996
            ResultSet rs = null;
997
            ResultSet result = null;
998
            //int endsCount = 0;
999
            boolean hasError = false;
1000
            HashMap<String, String> obsoletesIdGuidMap = new HashMap<String, String>();//the key is an obsoletes id, the value is an guid
1001
            Vector<Identifier> endsList = new Vector<Identifier>();//the vector storing ends
1002
            try {
1003
                // Get a database connection from the pool
1004
                dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getHeadPID");
1005
                serialNumber = dbConn.getCheckOutSerialNumber();
1006
                // Execute the insert statement
1007
                stmt = dbConn.prepareStatement(sql);
1008
                stmt.setString(1, sid.getValue());
1009
                rs = stmt.executeQuery();
1010
                boolean hasNext = rs.next();
1011
                boolean first = true;
1012
                Identifier firstOne = new Identifier();//since the sql using the desc order, the first one has the latest upload date.
1013
                if (hasNext) 
1014
                {
1015
                    while(hasNext) {
1016
                        String guidStr = rs.getString(1);
1017
                        String obsoletedByStr = rs.getString(2);
1018
                        String obsoletesStr = rs.getString(3);
1019
                        Identifier guid = new Identifier();
1020
                        guid.setValue(guidStr);
1021
                        if(obsoletesStr != null && !obsoletesStr.trim().equals("")) {
1022
                            if(obsoletesIdGuidMap.containsKey(obsoletesStr) && !guidStr.equals(obsoletesIdGuidMap.get(obsoletesStr))) {
1023
                                logMetacat.error("Both id "+guidStr+" and id "+obsoletesIdGuidMap.get(obsoletesStr)+" obsoletes the id"+obsoletesStr+
1024
                                        ". It is illegal. So the head pid maybe is wrong.");
1025
                                hasError = true;
1026
                            } 
1027
                            logMetacat.debug("Put "+guidStr+"(a value) Obsoletes "+obsoletesStr+" (a key) into the vector.");
1028
                            obsoletesIdGuidMap.put(obsoletesStr, guidStr);
1029
                        }
1030
                        if(first) {
1031
                            firstOne = guid;
1032
                            first =false;
1033
                        }
1034
                        //SystemMetadata sysmeta = HazelcastService.getInstance().getSystemMetadataMap().get(guid);
1035
                        //if(sysmeta.getObsoletedBy() == null) {
1036
                        if(obsoletedByStr == null || obsoletedByStr.trim().equals("")) {
1037
                            //type 1 end
1038
                            logMetacat.debug(""+guidStr+" is a type 1 end for sid "+sid.getValue());
1039
                            //pid = guid;
1040
                            //endsCount++;
1041
                            endsList.add(guid);
1042
                        } else {
1043
                            //Identifier obsoletedBy = sysmeta.getObsoletedBy();
1044
                            Identifier obsoletedBy = new Identifier();
1045
                            obsoletedBy.setValue(obsoletedByStr);
1046
                            //SystemMetadata obsoletedBySysmeta = HazelcastService.getInstance().getSystemMetadataMap().get(obsoletedBy);
1047
                            String sql2 = "select series_id, guid from systemMetadata where guid = ? ";
1048
                            stmt2 = dbConn.prepareStatement(sql2);
1049
                            stmt2.setString(1, obsoletedByStr);
1050
                            result = stmt2.executeQuery();
1051
                            boolean next = result.next();
1052
                            //if(obsoletedBySysmeta != null) {
1053
                            if(next) {
1054
                                logMetacat.debug("The object "+obsoletedBy+" which obsoletes "+guidStr+" does have a system metadata on the table.");
1055
                                //Identifier sidInObsoletedBy = obsoletedBySysmeta.getSeriesId();
1056
                                String sidInObsoletedBy = result.getString(1);
1057
                                if(sidInObsoletedBy == null|| !sidInObsoletedBy.equals(sid.getValue())) {
1058
                                    // type 2 end
1059
                                    logMetacat.debug(""+guidStr+" is a type 2 end for sid "+sid.getValue()+ "since it is obsoleted by the object "+sidInObsoletedBy+
1060
                                            " which has a different sid or no sids");
1061
                                    //pid = guid;
1062
                                    //endsCount++;
1063
                                    endsList.add(guid);
1064
                                }
1065
                            } else {
1066
                                logMetacat.debug("The object "+obsoletedBy+" which obsoletes "+guidStr+" is missing on the host.");
1067
                                //obsoletedBySysmeta doesn't exist; it means the object is missing
1068
                                //generally, we consider it we generally consider it a type 2 end except:
1069
                                 //there is another object in the chain (has the same series id) that obsoletes the missing object. 
1070
                                /*String sql2 = "select guid from systemMetadata where  obsoletes = ? and series_id = ?";
1071
                                PreparedStatement stmt2 = dbConn.prepareStatement(sql2);
1072
                                stmt2.setString(1, obsoletedBy.getValue());
1073
                                stmt2.setString(2, sid.getValue());
1074
                                ResultSet result = stmt2.executeQuery();
1075
                                boolean next = result.next();
1076
                                int count = 0;
1077
                                while(next) {
1078
                                    count++;
1079
                                    next = result.next();
1080
                                }
1081
                                if(count == 0) {
1082
                                    //the exception (another object in the chain (has the same series id) that obsoletes the missing object) doesn't exist
1083
                                    // it is a type 2 end
1084
                                    logMetacat.debug(""+guidStr+" is a type 2 end for sid "+sid.getValue());
1085
                                    pid = guid;
1086
                                    endsCount++;
1087
                                } else if (count ==1) {
1088
                                    // it is not end, do nothing;
1089
                                } else {
1090
                                    // something is wrong - there are more than one objects obsolete the missing object!
1091
                                    hasError = true;
1092
                                    break;
1093
                                }*/
1094
                                if(obsoletesIdGuidMap != null && obsoletesIdGuidMap.containsKey(obsoletedByStr)) {
1095
                                   //This is the exception - another object in the chain (has the same series id) that obsoletes the missing object
1096
                                    //The obsoletesIdGuidMap maintains the relationship (with the same  series id)
1097
                                    logMetacat.debug("Though the object "+obsoletedBy+" which obsoletes "+guidStr+" is missing."+
1098
                                            " However, there is another object "+obsoletesIdGuidMap.get(obsoletedByStr)+" in the chain obsoleting it. So it is not an end.");
1099
                                  
1100
                                } else {
1101
                                    //the exception (another object in the chain (has the same series id) that obsoletes the missing object) doesn't exist
1102
                                    // it is a type 2 end
1103
                                    logMetacat.debug(""+guidStr+" is a type 2 end for sid "+sid.getValue());
1104
                                    //pid = guid;
1105
                                    //endsCount++;
1106
                                    endsList.add(guid);
1107
                                }
1108
                            }
1109
                        }
1110
                        hasNext = rs.next();
1111
                    }
1112
                    if(hasError) {
1113
                        logMetacat.info("The sid chain "+sid.getValue()+" was messed up and we will return the object with the latest upload date.");
1114
                        pid = firstOne;
1115
                    } else {
1116
                        if(endsList.size() == 1) {
1117
                            //it has one end and it is an ideal chain. We already assign the guid to the pid. So do nothing.
1118
                            logMetacat.info("It is an ideal chain for sid "+sid.getValue());
1119
                            pid = endsList.get(0);
1120
                        } else if (endsList.size() ==0) {
1121
                            logMetacat.info("This is weird situation and we don't find any end. We use the latest DateOfupload");
1122
                            pid=checkObsoletesChain(firstOne, obsoletesIdGuidMap);
1123
                        } else if(endsList.size() >1) {
1124
                            // it is not an ideal chain, use the one with latest upload date(the first one in the result set since we have the desc order)
1125
                            logMetacat.info("It is NOT an ideal chain for sid "+sid.getValue());
1126
                            pid = checkObsoletesChain(endsList.get(0), obsoletesIdGuidMap);
1127
                        }
1128
                    }
1129
                    
1130
                } else {
1131
                    //it is not a sid or at least we don't have anything to match it.
1132
                    //do nothing, so null will be returned
1133
                    logMetacat.info("We don't find anything matching the id "+sid.getValue()+" as sid. The null will be returned since it is probably a pid");
1134
                }
1135
                
1136
                
1137
            } catch (SQLException e) {
1138
                logMetacat.error("Error while get the head pid for the sid "+sid.getValue()+" : " 
1139
                        + e.getMessage());
1140
                throw e;
1141
            } finally {
1142
                try {
1143
                    if(rs != null) {
1144
                        rs.close();
1145
                    }
1146
                    if(result != null) {
1147
                        result.close();
1148
                    }
1149
                    if(stmt != null) {
1150
                        stmt.close();
1151
                    }
1152
                    if(stmt2 != null) {
1153
                        stmt2.close();
1154
                    }
1155
                } catch (Exception e) {
1156
                    logMetacat.warn("Couldn't close the prepared statement since "+e.getMessage());
1157
                } finally {
1158
                    // Return database connection to the pool
1159
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1160
                }
1161
            }
1162
        }
1163
        if(pid != null && sid != null) {
1164
            logMetacat.info("The head of chain for sid "+sid.getValue()+"  --is--  "+pid.getValue());
1165
        } else if(pid == null && sid != null) {
1166
            logMetacat.info("The head of chain for sid "+sid.getValue()+" is null. So it is pid.");
1167
        }
1168
        
1169
        return pid;
1170
    }
1171
    
1172
    /*
1173
     * For the non-ideal chain, we used to return the latest Dateupload object as the head pid. However, Dateupload
1174
     * sometimes doesn't refect the obsoletes chain. We need to check if any other objects obsoletes it recursively.
1175
     * see ticket:https://redmine.dataone.org/issues/7624
1176
     */
1177
    private Identifier checkObsoletesChain(Identifier latestDateUpload, HashMap<String, String>obsoletesIdGuidMap) {
1178
        Identifier pid = latestDateUpload;
1179
        if(obsoletesIdGuidMap != null && latestDateUpload != null && obsoletesIdGuidMap.containsKey(latestDateUpload.getValue())) {
1180
            logMetacat.debug("Another object obsoletes the lasted uploaded object "+latestDateUpload.getValue());
1181
            //another object obsoletes the lastedDateUpload object
1182
            String pidStr = obsoletesIdGuidMap.get(latestDateUpload.getValue());
1183
            while (obsoletesIdGuidMap.containsKey(pidStr)) {
1184
                pidStr = obsoletesIdGuidMap.get(pidStr);
1185
                logMetacat.debug("Another object "+pidStr+" obsoletes the object ");
1186
            }
1187
            pid = new Identifier();
1188
            pid.setValue(pidStr);
1189
            
1190
        }
1191
        if(pid != null && latestDateUpload != null){
1192
            logMetacat.debug("IdnetifierManager.checkObsoletesChain - The final return value is "+pid.getValue()+ " for given value "+latestDateUpload.getValue());
1193
        }
1194
        return pid;
1195
    }
1196
    /**
1197
     * Check if the specified sid object exists on the serial id field on the system metadata table
1198
     * @param sid
1199
     * @return true if it exists; false otherwise.
1200
     * @throws SQLException
1201
     */
1202
    public boolean systemMetadataSIDExists(Identifier sid) throws SQLException {
1203
        if (sid != null && sid.getValue() != null && !sid.getValue().trim().equals("")) {
1204
            return systemMetadataSIDExists(sid.getValue());
1205
        } else {
1206
            return false;
1207
        }
1208
    }
1209
    
1210
    /**
1211
     * Check if the specified sid exists on the serial id field on the system metadata table
1212
     * @param id
1213
     * @return true if it exists; false otherwise.
1214
     */
1215
    public boolean systemMetadataSIDExists(String sid) throws SQLException {
1216
        boolean exists = false;
1217
        logMetacat.debug("Check if the  sid: " + sid +" exists on the series_id field of the system metadata table.");
1218
        if(sid != null && !sid.trim().equals("")) {
1219
            String sql = "select guid from systemMetadata where series_id = ?";
1220
            DBConnection dbConn = null;
1221
            int serialNumber = -1;
1222
            PreparedStatement stmt = null;
1223
            try {
1224
                // Get a database connection from the pool
1225
                dbConn = DBConnectionPool.getDBConnection("IdentifierManager.serialIdExists");
1226
                serialNumber = dbConn.getCheckOutSerialNumber();
1227
                // Execute the insert statement
1228
                stmt = dbConn.prepareStatement(sql);
1229
                stmt.setString(1, sid);
1230
                ResultSet rs = stmt.executeQuery();
1231
                if (rs.next()) 
1232
                {
1233
                    exists = true;
1234
                } 
1235
                if(rs != null) {
1236
                    rs.close();
1237
                }
1238
            } catch (SQLException e) {
1239
                logMetacat.error("Error while checking if the sid "+sid+" exists on the series_id field of the system metadata table: " 
1240
                        + e.getMessage());
1241
                throw e;
1242
            } finally {
1243
                try {
1244
                    if(stmt != null) {
1245
                        stmt.close();
1246
                    }
1247
                } catch (Exception e) {
1248
                    logMetacat.warn("Couldn't close the prepared statement since "+e.getMessage());
1249
                } finally {
1250
                    // Return database connection to the pool
1251
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1252
                }
1253
            }
1254
        }
1255
        return exists;
1256
    }
1257
    
1258
    /**
1259
     * Determine if the specified identifier object exists or not.
1260
     * @param pid - the specified identifier
1261
     * @return true if it is exists.
1262
     * @throws SQLException
1263
     * @throws NullPointerException
1264
     */
1265
    public boolean systemMetadataPIDExists(Identifier pid) throws SQLException {
1266
        if (pid != null && pid.getValue() != null && !pid.getValue().trim().equals("")) {
1267
            return systemMetadataPIDExists(pid.getValue());
1268
        } else {
1269
            return false;
1270
        }
1271
    }
1272
    
1273
    public boolean systemMetadataPIDExists(String guid) throws SQLException {
1274
		logMetacat.debug("looking up system metadata for guid " + guid);
1275
		boolean exists = false;
1276
		String query = "select guid from systemmetadata where guid = ?";
1277
		DBConnection dbConn = null;
1278
		int serialNumber = -1;
1279
		PreparedStatement stmt = null;
1280
		if(guid != null && !guid.trim().equals("")) {
1281
		    try {
1282
	            // Get a database connection from the pool
1283
	            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
1284
	            serialNumber = dbConn.getCheckOutSerialNumber();
1285

    
1286
	            // Execute the insert statement
1287
	            stmt = dbConn.prepareStatement(query);
1288
	            stmt.setString(1, guid);
1289
	            ResultSet rs = stmt.executeQuery();
1290
	            if (rs.next()) {
1291
	                exists = true;
1292
	            }
1293
	            if(rs != null) {
1294
	                rs.close();
1295
	            }
1296

    
1297
	        } catch (SQLException e) {
1298
	            logMetacat.error("Error while looking up the system metadata: "
1299
	                    + e.getMessage());
1300
	            throw e;
1301
	        } finally {
1302
	            try {
1303
	                if(stmt != null) {
1304
	                    stmt.close();
1305
	                }
1306
	            } catch (Exception e) {
1307
	                logMetacat.warn("Couldn't close the prepared statement since "+e.getMessage());
1308
	            } finally {
1309
	                // Return database connection to the pool
1310
	                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1311
	            }
1312
	        }
1313
		}
1314
		return exists;
1315
	}
1316
    
1317
    /**
1318
     * creates a system metadata mapping and adds additional fields from sysmeta
1319
     * to the table for quick searching.
1320
     * 
1321
     * @param guid the id to insert
1322
     * @param localId the systemMetadata object to get the local id for
1323
     * @throws McdbDocNotFoundException 
1324
     * @throws SQLException 
1325
     * @throws InvalidSystemMetadata 
1326
     */
1327
    public void insertOrUpdateSystemMetadata(SystemMetadata sysmeta) 
1328
        throws McdbDocNotFoundException, SQLException, InvalidSystemMetadata {
1329
    	String guid = sysmeta.getIdentifier().getValue();
1330
    	
1331
    	 // Get a database connection from the pool
1332
        DBConnection dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1333
        int serialNumber = dbConn.getCheckOutSerialNumber();
1334
        
1335
        try {
1336
        	// use a single transaction for it all
1337
        	dbConn.setAutoCommit(false);
1338
        	
1339
	    	// insert the record if needed
1340
        	if (!IdentifierManager.getInstance().systemMetadataPIDExists(guid)) {
1341
    	        insertSystemMetadata(guid, dbConn);
1342
			}
1343
	        // update with the values
1344
	        updateSystemMetadata(sysmeta, dbConn);
1345
	        
1346
	        // commit if we got here with no errors
1347
	        dbConn.commit();
1348
        } catch (Exception e) {
1349
            e.printStackTrace();
1350
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1351
            dbConn.rollback();
1352
            throw new SQLException("Can't save system metadata "+e.getMessage());
1353
        } finally {
1354
            // Return database connection to the pool
1355
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1356
        }
1357
        
1358
        
1359
    }
1360
        
1361
    
1362
    /**
1363
     * update a mapping
1364
     * @param guid
1365
     * @param localId
1366
     */
1367
    public void updateMapping(String guid, String localId)
1368
    {
1369
    	
1370
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
1371
        int serialNumber = -1;
1372
        DBConnection dbConn = null;
1373
        try {
1374
            // Parse the localId into scope and rev parts
1375
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1376
            String docid = acc.getDocid();
1377
            int rev = 1;
1378
            if(acc.getRev() != null)
1379
            {
1380
              rev = (new Integer(acc.getRev()).intValue());
1381
            }
1382

    
1383
            // Get a database connection from the pool
1384
            dbConn = 
1385
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1386
            serialNumber = dbConn.getCheckOutSerialNumber();
1387

    
1388
            // Execute the update statement
1389
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid = ?";
1390
            PreparedStatement stmt = dbConn.prepareStatement(query);
1391
            stmt.setString(1, docid);
1392
            stmt.setInt(2, rev);
1393
            stmt.setString(3, guid);
1394
            int rows = stmt.executeUpdate();
1395

    
1396
            stmt.close();
1397
        } catch (SQLException e) {
1398
            e.printStackTrace();
1399
            logMetacat.error("SQL error while updating a mapping identifier: " 
1400
                    + e.getMessage());
1401
        } catch (NumberFormatException e) {
1402
            e.printStackTrace();
1403
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
1404
                    + e.getMessage());
1405
        } catch (AccessionNumberException e) {
1406
            e.printStackTrace();
1407
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
1408
                    + e.getMessage());
1409
        } finally {
1410
            // Return database connection to the pool
1411
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1412
        }
1413
        logMetacat.debug("done updating mapping");
1414
    }
1415
        
1416
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1417
        String checksum, String checksumAlgorithm, String originMemberNode, 
1418
        String authoritativeMemberNode, long modifiedDate, String submitter, 
1419
        String guid, String objectFormat, BigInteger size, boolean archived,
1420
        boolean replicationAllowed, int numberReplicas, String obsoletes,
1421
        String obsoletedBy, BigInteger serialVersion, String seriesId, 
1422
        String fileName, MediaType mediaType, DBConnection dbConn) throws SQLException  {
1423
        PreparedStatement stmt = null;
1424
        PreparedStatement stmt2 = null;
1425
        try {
1426
            dbConn.setAutoCommit(false);
1427
            // Execute the insert statement
1428
            String query = "update " + TYPE_SYSTEM_METADATA + 
1429
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1430
                "origin_member_node, authoritive_member_node, date_modified, " +
1431
                "submitter, object_format, size, archived, replication_allowed, number_replicas, " +
1432
                "obsoletes, obsoleted_by, serial_version, series_id, file_name, media_type) " +
1433
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?) where guid = ?";
1434
            stmt = dbConn.prepareStatement(query);
1435
            
1436
            //data values
1437
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1438
            stmt.setString(2, rightsHolder);
1439
            stmt.setString(3, checksum);
1440
            stmt.setString(4, checksumAlgorithm);
1441
            stmt.setString(5, originMemberNode);
1442
            stmt.setString(6, authoritativeMemberNode);
1443
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1444
            stmt.setString(8, submitter);
1445
            stmt.setString(9, objectFormat);
1446
            stmt.setString(10, size.toString());
1447
            stmt.setBoolean(11, archived);
1448
            stmt.setBoolean(12, replicationAllowed);
1449
            stmt.setInt(13, numberReplicas);
1450
            stmt.setString(14, obsoletes);
1451
            stmt.setString(15, obsoletedBy);
1452
            if(serialVersion != null) {
1453
                stmt.setString(16, serialVersion.toString());
1454
            } else {
1455
                stmt.setString(16, null);
1456
            }
1457
            
1458
            stmt.setString(17, seriesId);
1459
            stmt.setString(18, fileName);
1460
            if (mediaType == null) {
1461
                stmt.setString(19, null);
1462
            } else {
1463
                stmt.setString(19, mediaType.getName());
1464
            }
1465
            //where clause
1466
            stmt.setString(20, guid);
1467
            logMetacat.debug("stmt: " + stmt.toString());
1468
            //execute
1469
            int rows = stmt.executeUpdate();
1470
            
1471
            //insert media type properties into another table
1472
            if(mediaType != null && mediaType.getPropertyList() != null) {
1473
                String sql2 = "insert into smmediatypeproperties " + 
1474
                        "(guid, name, value) " + "values (?, ?, ?)";
1475
                stmt2 = dbConn.prepareStatement(sql2);
1476
                for(MediaTypeProperty item : mediaType.getPropertyList()) {
1477
                    if(item != null) {
1478
                        String name = item.getName();
1479
                        String value = item.getValue();
1480
                        stmt2.setString(1, guid);
1481
                        stmt2.setString(2, name);
1482
                        stmt2.setString(3, value);
1483
                        logMetacat.debug("insert media type properties query: " + stmt2.toString());
1484
                        int row =stmt2.executeUpdate();
1485
                    }
1486
                    
1487
                }
1488
            }
1489
            dbConn.commit();
1490
            dbConn.setAutoCommit(true);
1491
        } catch (Exception e) {
1492
            dbConn.rollback();
1493
            dbConn.setAutoCommit(true);
1494
            e.printStackTrace();
1495
            throw new SQLException(e.getMessage());
1496
        } finally {
1497
            if(stmt != null) {
1498
                stmt.close();
1499
            }
1500
            if(stmt2 != null) {
1501
                stmt2.close();
1502
            }
1503
        }
1504
        
1505
               
1506
    }
1507
    
1508
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes, DBConnection dbConn) throws SQLException
1509
    {
1510
           
1511
        // remove existing values first
1512
        String delete = "delete from smReplicationPolicy " + 
1513
        "where guid = ? and policy = ?";
1514
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1515
        //data values
1516
        stmt.setString(1, guid);
1517
        stmt.setString(2, policy);
1518
        //execute
1519
        int deletedCount = stmt.executeUpdate();
1520
        stmt.close();
1521
        
1522
        for (String memberNode: memberNodes) {
1523
            // Execute the insert statement
1524
            String insert = "insert into smReplicationPolicy " + 
1525
                "(guid, policy, member_node) " +
1526
                "values (?, ?, ?)";
1527
            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1528
            
1529
            //data values
1530
            insertStatement.setString(1, guid);
1531
            insertStatement.setString(2, policy);
1532
            insertStatement.setString(3, memberNode);
1533
            
1534
            logMetacat.debug("smReplicationPolicy sql: " + insertStatement.toString());
1535

    
1536
            //execute
1537
            int rows = insertStatement.executeUpdate();
1538
            insertStatement.close();
1539
        }
1540
        
1541
    }
1542
    
1543
    private void insertReplicationStatus(String guid, List<Replica> replicas, DBConnection dbConn) throws SQLException {
1544
       
1545
        // remove existing values first
1546
        String delete = "delete from smReplicationStatus " + 
1547
        "where guid = ?";
1548
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1549
        //data values
1550
        stmt.setString(1, guid);
1551
        //execute
1552
        int deletedCount = stmt.executeUpdate();
1553
        stmt.close();
1554
        
1555
        if (replicas != null) {
1556
            for (Replica replica: replicas) {
1557
	            // Execute the insert statement
1558
	            String insert = "insert into smReplicationStatus " + 
1559
	                "(guid, member_node, status, date_verified) " +
1560
	                "values (?, ?, ?, ?)";
1561
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1562
	            
1563
	            //data values
1564
	            String memberNode = replica.getReplicaMemberNode().getValue();
1565
	            String status = replica.getReplicationStatus().toString();
1566
	            java.sql.Timestamp sqlDate = new java.sql.Timestamp(replica.getReplicaVerified().getTime());
1567
	            insertStatement.setString(1, guid);
1568
	            insertStatement.setString(2, memberNode);
1569
	            insertStatement.setString(3, status);
1570
	            insertStatement.setTimestamp(4, sqlDate);
1571

    
1572
	            logMetacat.debug("smReplicationStatus sql: " + insertStatement.toString());
1573
	            
1574
	            //execute
1575
	            int rows = insertStatement.executeUpdate();
1576
	            insertStatement.close();
1577
            }
1578
        }
1579
       
1580
    }
1581
    
1582
    /**
1583
     * Insert the system metadata fields into the db
1584
     * @param sm
1585
     * @throws McdbDocNotFoundException 
1586
     * @throws SQLException 
1587
     * @throws InvalidSystemMetadata 
1588
     * @throws AccessException 
1589
     */
1590
    public void updateSystemMetadata(SystemMetadata sm, DBConnection dbConn) 
1591
      throws McdbDocNotFoundException, SQLException, InvalidSystemMetadata, AccessException {
1592
    	
1593
      Boolean replicationAllowed = false;
1594
		  Integer numberReplicas = -1;
1595
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1596
    	if (replicationPolicy != null) {
1597
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1598
    		numberReplicas = replicationPolicy.getNumberReplicas();
1599
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1600
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1601
    	}
1602
    	
1603
    	// the main systemMetadata fields
1604
		  updateSystemMetadataFields(
1605
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1606
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(), 
1607
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(), 
1608
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm(), 
1609
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1610
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(), 
1611
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1612
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(), 
1613
		    sm.getIdentifier().getValue(),
1614
		    sm.getFormatId() == null ? null: sm.getFormatId().getValue(),
1615
		    sm.getSize(),
1616
		    sm.getArchived() == null ? false: sm.getArchived(),
1617
		    replicationAllowed, 
1618
		    numberReplicas,
1619
		    sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
1620
		    sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue(),
1621
		    sm.getSerialVersion(),
1622
		    sm.getSeriesId() == null ? null: sm.getSeriesId().getValue(),
1623
		    sm.getFileName() == null ? null: sm.getFileName(),
1624
		    sm.getMediaType() == null ? null: sm.getMediaType(),
1625
		    dbConn
1626
        );
1627
        
1628
        String guid = sm.getIdentifier().getValue();
1629
        
1630
        // save replication policies
1631
        if (replicationPolicy != null) {
1632
		    List<String> nodes = null;
1633
		    String policy = null;
1634
		    
1635
		    // check for null 
1636
		    if (replicationPolicy.getBlockedMemberNodeList() != null) {
1637
			    nodes = new ArrayList<String>();
1638
			    policy = "blocked";
1639
			    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1640
			    	nodes.add(node.getValue());
1641
			    }
1642
			    this.insertReplicationPolicy(guid, policy, nodes, dbConn);
1643
		    }
1644
		    
1645
		    if (replicationPolicy.getPreferredMemberNodeList() != null) {
1646
			    nodes = new ArrayList<String>();
1647
			    policy = "preferred";
1648
			    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1649
			    	nodes.add(node.getValue());
1650
			    }
1651
		        this.insertReplicationPolicy(guid, policy, nodes, dbConn);
1652
		    }
1653
        }
1654
        
1655
        // save replica information
1656
        this.insertReplicationStatus(guid, sm.getReplicaList(), dbConn);
1657
        
1658
        // save access policy
1659
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1660
        if (accessPolicy != null) {
1661
			this.insertAccessPolicy(guid, accessPolicy);
1662
        }
1663
    }
1664
    
1665
    /**
1666
     * Creates Metacat access rules and inserts them
1667
     * @param accessPolicy
1668
     * @throws McdbDocNotFoundException
1669
     * @throws AccessException
1670
     */
1671
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1672
    	
1673
    	// check for the existing permOrder so that we remain compatible with it (DataONE does not care)
1674
        XMLAccessAccess accessController  = new XMLAccessAccess();
1675
		String existingPermOrder = AccessControlInterface.ALLOWFIRST;
1676
        Vector<XMLAccessDAO> existingAccess = accessController.getXMLAccessForDoc(guid);
1677
        if (existingAccess != null && existingAccess.size() > 0) {
1678
        	existingPermOrder = existingAccess.get(0).getPermOrder();
1679
        }
1680
        
1681
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1682
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1683
        	List<Subject> subjects = accessRule.getSubjectList();
1684
        	List<Permission> permissions = accessRule.getPermissionList();
1685
        	for (Subject subject: subjects) {
1686
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1687
        		accessDAO.setPrincipalName(subject.getValue());
1688
    			accessDAO.setGuid(guid);
1689
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1690
				accessDAO.setPermOrder(existingPermOrder);
1691
    			if (permissions != null) {
1692
	    			for (Permission permission: permissions) {
1693
	    				Long metacatPermission = new Long(convertPermission(permission));
1694
	        			accessDAO.addPermission(metacatPermission);
1695
	    			}
1696
    			}
1697
    			accessDAOs.add(accessDAO);
1698
        	}
1699
        }
1700
        
1701
        
1702
        // remove all existing allow records
1703
        accessController.deleteXMLAccessForDoc(guid, AccessControlInterface.ALLOW);
1704
        // add the ones we can for this guid
1705
        accessController.insertAccess(guid, accessDAOs);
1706
        
1707
        
1708
    }
1709
    
1710
    /**
1711
     * Lookup access policy from Metacat
1712
     * @param guid
1713
     * @return
1714
     * @throws McdbDocNotFoundException
1715
     * @throws AccessException
1716
     */
1717
    public AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1718
        AccessPolicy accessPolicy = new AccessPolicy();
1719

    
1720
    	// use GUID to look up the access
1721
        XMLAccessAccess accessController  = new XMLAccessAccess();
1722
        List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1723
        
1724
        for (XMLAccessDAO accessDAO: accessDAOs) {
1725
        	// only add allow rule
1726
        	if (accessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
1727
	        	AccessRule accessRule = new AccessRule();    	
1728
	        	List <Permission> permissions = convertPermission(accessDAO.getPermission().intValue());
1729
	        	// cannot include if we have no permissions
1730
	        	if (permissions == null || permissions.isEmpty()) {
1731
	        		logMetacat.warn("skipping empty access rule permissions for " + guid);
1732
	        		continue;
1733
	        	}
1734
	        	accessRule.setPermissionList(permissions);
1735
	        	Subject subject = new Subject();
1736
	        	subject.setValue(accessDAO.getPrincipalName());
1737
	        	accessRule.addSubject(subject);
1738
	            accessPolicy.addAllow(accessRule);
1739
        	}
1740
        }
1741
        return accessPolicy;
1742
    }
1743
    
1744
    public int convertPermission(Permission permission) {
1745
    	if (permission.equals(Permission.READ)) {
1746
    		return AccessControlInterface.READ;
1747
    	}
1748
    	if (permission.equals(Permission.WRITE)) {
1749
    		return AccessControlInterface.WRITE;
1750
    	}
1751
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1752
    		return AccessControlInterface.CHMOD;
1753
    	}
1754
		return -1;
1755
    }
1756
    
1757
    public List<Permission> convertPermission(int permission) {
1758
    	
1759
    	List<Permission> permissions = new ArrayList<Permission>();
1760
    	if (permission == AccessControlInterface.ALL) {
1761
    		permissions.add(Permission.READ);
1762
    		permissions.add(Permission.WRITE);
1763
    		permissions.add(Permission.CHANGE_PERMISSION);
1764
    		return permissions;
1765
    	}
1766
    	
1767
    	if ((permission & AccessControlInterface.CHMOD) == AccessControlInterface.CHMOD) {
1768
    		permissions.add(Permission.CHANGE_PERMISSION);
1769
    	}
1770
    	if ((permission & AccessControlInterface.READ) == AccessControlInterface.READ) {
1771
    		permissions.add(Permission.READ);
1772
    	}
1773
    	if ((permission & AccessControlInterface.WRITE) == AccessControlInterface.WRITE) {
1774
    		permissions.add(Permission.WRITE);
1775
    	}
1776
    	
1777
		return permissions;
1778
    }
1779
    
1780
    /**
1781
     * Lookup a localId given the GUID. If
1782
     * the identifier is not found, throw an exception.
1783
     * 
1784
     * @param guid the global identifier to look up
1785
     * @return String containing the corresponding LocalId
1786
     * @throws McdbDocNotFoundException if the identifier is not found
1787
     */
1788
    public String getLocalId(String guid) throws McdbDocNotFoundException, SQLException {
1789
      
1790
      String db_guid = "";
1791
      String docid = "";
1792
      int rev = 0;
1793
      
1794
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1795
      
1796
      DBConnection dbConn = null;
1797
      int serialNumber = -1;
1798
      try {
1799
          // Get a database connection from the pool
1800
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1801
          serialNumber = dbConn.getCheckOutSerialNumber();
1802
          
1803
          // Execute the insert statement
1804
          PreparedStatement stmt = dbConn.prepareStatement(query);
1805
          stmt.setString(1, guid);
1806
          ResultSet rs = stmt.executeQuery();
1807
          if (rs.next()) {
1808
              db_guid = rs.getString(1);
1809
              docid = rs.getString(2);
1810
              rev = rs.getInt(3);
1811
              assert(db_guid.equals(guid));
1812
          } else {
1813
              throw new McdbDocNotFoundException("Document not found:" + guid);
1814
          }
1815
          stmt.close();
1816
      } catch (SQLException e) {
1817
          logMetacat.error("Error while looking up the local identifier: " 
1818
                  + e.getMessage());
1819
          throw e;
1820
      } finally {
1821
          // Return database connection to the pool
1822
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1823
      }
1824
      return docid + "." + rev;
1825
    }
1826
    
1827
    /**
1828
     * query the systemmetadata table based on the given parameters
1829
     * @param startTime
1830
     * @param endTime
1831
     * @param objectFormat
1832
     * @param nodeId
1833
     * @param start
1834
     * @param count
1835
     * @return ObjectList
1836
     * @throws SQLException 
1837
     * @throws ServiceException 
1838
     * @throws PropertyNotFoundException 
1839
     */
1840
    public ObjectList querySystemMetadata(Date startTime, Date endTime,
1841
        ObjectFormatIdentifier objectFormatId, NodeReference nodeId,
1842
        int start, int count, Identifier identifier, boolean isSID) 
1843
        throws SQLException, PropertyNotFoundException, ServiceException {
1844
        ObjectList ol = new ObjectList();
1845
        DBConnection dbConn = null;
1846
        int serialNumber = -1;
1847
        PreparedStatement countStmt=null;
1848
        ResultSet totalResult=null;
1849
        PreparedStatement fieldStmt = null;
1850
        ResultSet rs= null;
1851

    
1852
        try {
1853
            String fieldSql = "select guid, date_uploaded, rights_holder, checksum, "
1854
                    + "checksum_algorithm, origin_member_node, authoritive_member_node, "
1855
                    + "date_modified, submitter, object_format, size from systemmetadata";
1856
            
1857
            // handle special case quickly
1858
            String countSql = "select count(guid) from systemmetadata";
1859
            
1860
            // the clause
1861
            String whereClauseSql = "";
1862
            
1863

    
1864
            boolean f1 = false;
1865
            boolean f2 = false;
1866
            boolean f3 = false;
1867
            boolean f4 = false;
1868

    
1869

    
1870
            if (startTime != null) {
1871
                whereClauseSql += " where systemmetadata.date_modified >= ?";
1872
                f1 = true;
1873
            }
1874

    
1875
            if (endTime != null) {
1876
                if (!f1) {
1877
                    whereClauseSql += " where systemmetadata.date_modified < ?";
1878
                } else {
1879
                    whereClauseSql += " and systemmetadata.date_modified < ?";
1880
                }
1881
                f2 = true;
1882
            }
1883

    
1884
            if (objectFormatId != null) {
1885
                if (!f1 && !f2) {
1886
                    whereClauseSql += " where object_format = ?";
1887
                } else {
1888
                    whereClauseSql += " and object_format = ?";
1889
                }
1890
                f3 = true;
1891
            }
1892
            
1893
            if(identifier != null && identifier.getValue() != null && !identifier.getValue().equals("")) {
1894
                if (!f1 && !f2 && !f3 ) {
1895
                    if(isSID) {
1896
                        whereClauseSql += " where series_id = ?";
1897
                    } else {
1898
                        whereClauseSql += " where guid = ?";
1899
                    }
1900
                    
1901
                } else {
1902
                    if(isSID) {
1903
                        whereClauseSql += " and series_id = ?";
1904
                    } else {
1905
                        whereClauseSql += " and guid = ?";
1906
                    }
1907
                }
1908
                f4 = true;
1909
            }
1910

    
1911
            /*if (!replicaStatus) {
1912
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.nodeId");
1913
                if (!f1 && !f2 && !f3 && !f4) {
1914
                    whereClauseSql += " where authoritive_member_node = '" +
1915
                        currentNodeId.trim() + "'";
1916
                } else {
1917
                    whereClauseSql += " and authoritive_member_node = '" +
1918
                        currentNodeId.trim() + "'";
1919
                }
1920
            }*/
1921
            
1922
            if (nodeId != null && nodeId.getValue() != null && !nodeId.getValue().trim().equals("")) {
1923
                if (!f1 && !f2 && !f3 && !f4) {
1924
                    whereClauseSql += " where authoritive_member_node = '" +
1925
                        nodeId.getValue().trim() + "'";
1926
                } else {
1927
                    whereClauseSql += " and authoritive_member_node = '" +
1928
                        nodeId.getValue().trim() + "'";
1929
                }
1930
            }
1931
           
1932
            
1933
            // connection
1934
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1935
            serialNumber = dbConn.getCheckOutSerialNumber();
1936

    
1937
            // the field query
1938
            String orderBySql = " order by guid ";
1939
            String fieldQuery = fieldSql + whereClauseSql + orderBySql;
1940
            String finalQuery = DatabaseService.getInstance().getDBAdapter().getPagedQuery(fieldQuery, start, count);
1941
            fieldStmt = dbConn.prepareStatement(finalQuery);
1942
            
1943
            // construct the count query and statment
1944
            String countQuery = countSql + whereClauseSql;
1945
            countStmt = dbConn.prepareStatement(countQuery);
1946

    
1947
            if (f1 && f2 && f3 && f4) {
1948
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1949
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1950
                fieldStmt.setString(3, objectFormatId.getValue());
1951
                fieldStmt.setString(4, identifier.getValue());
1952
                // count
1953
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1954
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1955
                countStmt.setString(3, objectFormatId.getValue());
1956
                countStmt.setString(4, identifier.getValue());
1957
            } if (f1 && f2 && f3 && !f4) {
1958
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1959
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1960
                fieldStmt.setString(3, objectFormatId.getValue());
1961
                // count
1962
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1963
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1964
                countStmt.setString(3, objectFormatId.getValue());
1965
            } else if (f1 && f2 && !f3 && f4) {
1966
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1967
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1968
                fieldStmt.setString(3, identifier.getValue());
1969
                // count
1970
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1971
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1972
                countStmt.setString(3, identifier.getValue());
1973
            } else if (f1 && f2 && !f3 && !f4) {
1974
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1975
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1976
                // count
1977
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1978
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1979
            } else if (f1 && !f2 && f3 && f4) {
1980
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1981
                fieldStmt.setString(2, objectFormatId.getValue());
1982
                fieldStmt.setString(3, identifier.getValue());
1983
                // count
1984
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1985
                countStmt.setString(2, objectFormatId.getValue());
1986
                countStmt.setString(3, identifier.getValue());
1987
            } else if (f1 && !f2 && f3 && !f4) {
1988
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1989
                fieldStmt.setString(2, objectFormatId.getValue());
1990
                // count
1991
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1992
                countStmt.setString(2, objectFormatId.getValue());
1993
            } else if (f1 && !f2 && !f3 && f4) {
1994
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1995
                fieldStmt.setString(2, identifier.getValue());
1996
                // count
1997
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1998
                countStmt.setString(2, identifier.getValue());
1999
            } else if (f1 && !f2 && !f3 && !f4) {
2000
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2001
                // count
2002
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2003
            } else if (!f1 && f2 && f3 && f4) {
2004
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2005
                fieldStmt.setString(2, objectFormatId.getValue());
2006
                fieldStmt.setString(3, identifier.getValue());
2007
                // count
2008
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2009
                countStmt.setString(2, objectFormatId.getValue());
2010
                countStmt.setString(3, identifier.getValue());
2011
            } else if (!f1 && f2 && f3 && !f4) {
2012
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2013
                fieldStmt.setString(2, objectFormatId.getValue());
2014
                // count
2015
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2016
                countStmt.setString(2, objectFormatId.getValue());
2017
            } else if (!f1 && !f2 && f3 && f4) {
2018
                fieldStmt.setString(1, objectFormatId.getValue());
2019
                fieldStmt.setString(2, identifier.getValue());
2020
                // count
2021
                countStmt.setString(1, objectFormatId.getValue());
2022
                countStmt.setString(2, identifier.getValue());
2023
            } else if (!f1 && !f2 && f3 && !f4) {
2024
                fieldStmt.setString(1, objectFormatId.getValue());
2025
                // count
2026
                countStmt.setString(1, objectFormatId.getValue());
2027
            } else if (!f1 && f2 && !f3 && f4) {
2028
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2029
                fieldStmt.setString(2, identifier.getValue());
2030
                // count
2031
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2032
                countStmt.setString(2, identifier.getValue());
2033
            } else if (!f1 && f2 && !f3 && !f4) {
2034
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2035
                // count
2036
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2037
            } else if (!f1 && !f2 && !f3 && f4) {
2038
                fieldStmt.setString(1, identifier.getValue());
2039
                // count
2040
                countStmt.setString(1, identifier.getValue());
2041
            } else if (!f1 && !f2 && !f3 && !f4) {
2042
                //do nothing
2043
            }
2044

    
2045
            logMetacat.debug("list objects fieldStmt: " + fieldStmt.toString());
2046
            
2047
            logMetacat.debug("list objects countStmt: " + countStmt.toString());
2048
            
2049
            // get the total object count no matter what
2050
            int total = 0;
2051
            totalResult = countStmt.executeQuery();
2052
            if (totalResult.next()) {
2053
            	total = totalResult.getInt(1);
2054
            }
2055
            
2056
            logMetacat.debug("list objects total: " + total);
2057

    
2058
        	// set the totals
2059
        	ol.setStart(start);
2060
            ol.setCount(count);
2061
            
2062
            // retrieve the actual records if requested
2063
            if (count != 0) {
2064
            	
2065
                rs = fieldStmt.executeQuery();
2066
	            while (rs.next()) {                
2067
	                
2068
	                String guid = rs.getString(1);
2069
	                logMetacat.debug("query found object with guid " + guid);
2070
	                // Timestamp dateUploaded = rs.getTimestamp(2);
2071
	                // String rightsHolder = rs.getString(3);
2072
	                String checksum = rs.getString(4);
2073
	                String checksumAlgorithm = rs.getString(5);
2074
	                // String originMemberNode = rs.getString(6);
2075
	                // String authoritiveMemberNode = rs.getString(7);
2076
	                Timestamp dateModified = rs.getTimestamp(8);
2077
	                // String submitter = rs.getString(9);
2078
	                String fmtidStr = rs.getString(10);
2079
	                String sz = rs.getString(11);
2080
	                BigInteger size = new BigInteger("0");
2081
	
2082
	                if (sz != null && !sz.trim().equals("")) {
2083
	                    size = new BigInteger(rs.getString(11));
2084
	                }
2085
	
2086
	                ObjectInfo oi = new ObjectInfo();
2087
	
2088
	                Identifier id = new Identifier();
2089
	                id.setValue(guid);
2090
	                oi.setIdentifier(id);
2091
	
2092
	                if (dateModified != null) {
2093
	                    oi.setDateSysMetadataModified(dateModified);
2094
	                }
2095
	
2096
	                Checksum cs = new Checksum();
2097
	                cs.setValue(checksum);
2098
	                try {
2099
	                    // cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
2100
	                    cs.setAlgorithm(checksumAlgorithm);
2101
	                } catch (Exception e) {
2102
	                    logMetacat.error("could not parse checksum algorithm", e);
2103
	                    continue;
2104
	                }
2105
	                oi.setChecksum(cs);
2106
	
2107
	                // set the format type
2108
	                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
2109
	                fmtid.setValue(fmtidStr);
2110
	                oi.setFormatId(fmtid);
2111
	
2112
	                oi.setSize(size);
2113
	                
2114
	                ol.addObjectInfo(oi);                    
2115

    
2116
	            }
2117
	            
2118
	            logMetacat.debug("list objects count: " + ol.sizeObjectInfoList());
2119
	            // set the actual count retrieved
2120
	            ol.setCount(ol.sizeObjectInfoList());
2121
	            
2122
	
2123
	        }
2124
            ol.setTotal(total);
2125
        } finally {
2126
            // Return database connection to the pool
2127
            try {
2128
                if(totalResult !=null ){
2129
                    totalResult.close();
2130
                }
2131
                if(countStmt!=null ) {
2132
                    countStmt.close();
2133
                }
2134
                if(rs != null) {
2135
                    rs.close();
2136
                }
2137
                if(fieldStmt != null) {
2138
                    fieldStmt.close();
2139
                }
2140
                
2141
            } catch (SQLException sql) {
2142
                
2143
            }
2144
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2145
            
2146
        }
2147
        if(ol != null) {
2148
            logMetacat.debug("list objects start(before returning): " + ol.getStart());
2149
            logMetacat.debug("list objects count: " + ol.getCount());
2150
            logMetacat.debug("list objects total: " + ol.getTotal());
2151
        }
2152
        return ol;
2153
    }
2154
    
2155
    /**
2156
     * create a mapping in the identifier table
2157
     * @param guid
2158
     * @param localId
2159
     */
2160
    public void createMapping(String guid, String localId)
2161
    {        
2162
        
2163
        int serialNumber = -1;
2164
        DBConnection dbConn = null;
2165
        try {
2166

    
2167
            // Parse the localId into scope and rev parts
2168
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
2169
            String docid = acc.getDocid();
2170
            int rev = 1;
2171
            if (acc.getRev() != null) {
2172
              rev = (new Integer(acc.getRev()).intValue());
2173
            }
2174

    
2175
            // Get a database connection from the pool
2176
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
2177
            serialNumber = dbConn.getCheckOutSerialNumber();
2178

    
2179
            // Execute the insert statement
2180
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
2181
            PreparedStatement stmt = dbConn.prepareStatement(query);
2182
            stmt.setString(1, guid);
2183
            stmt.setString(2, docid);
2184
            stmt.setInt(3, rev);
2185
            logMetacat.debug("mapping query: " + stmt.toString());
2186
            int rows = stmt.executeUpdate();
2187

    
2188
            stmt.close();
2189
        } catch (SQLException e) {
2190
            e.printStackTrace();
2191
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
2192
                    + e.getMessage());
2193
        } catch (NumberFormatException e) {
2194
            e.printStackTrace();
2195
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
2196
                    + e.getMessage());
2197
        } catch (AccessionNumberException e) {
2198
            e.printStackTrace();
2199
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
2200
                    + e.getMessage());
2201
        } finally {
2202
            // Return database connection to the pool
2203
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2204
        }
2205
    }
2206
    
2207
    /**
2208
     * remove a mapping in the identifier table
2209
     * @param guid
2210
     * @param localId
2211
     */
2212
    public void removeMapping(String guid, String localId)
2213
    {        
2214
        
2215
        int serialNumber = -1;
2216
        DBConnection dbConn = null;
2217
        try {
2218

    
2219
            // Parse the localId into scope and rev parts
2220
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
2221
            String docid = acc.getDocid();
2222
            int rev = 1;
2223
            if (acc.getRev() != null) {
2224
              rev = (new Integer(acc.getRev()).intValue());
2225
            }
2226

    
2227
            // Get a database connection from the pool
2228
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.removeMapping");
2229
            serialNumber = dbConn.getCheckOutSerialNumber();
2230

    
2231
            // Execute the insert statement
2232
            String query = "DELETE FROM " + TYPE_IDENTIFIER + " WHERE guid = ? AND docid = ? AND rev = ?";
2233
            PreparedStatement stmt = dbConn.prepareStatement(query);
2234
            stmt.setString(1, guid);
2235
            stmt.setString(2, docid);
2236
            stmt.setInt(3, rev);
2237
            logMetacat.debug("remove mapping query: " + stmt.toString());
2238
            int rows = stmt.executeUpdate();
2239

    
2240
            stmt.close();
2241
        } catch (SQLException e) {
2242
            e.printStackTrace();
2243
            logMetacat.error("removeMapping: SQL error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
2244
                    + e.getMessage());
2245
        } catch (NumberFormatException e) {
2246
            e.printStackTrace();
2247
            logMetacat.error("removeMapping: NumberFormat error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
2248
                    + e.getMessage());
2249
        } catch (AccessionNumberException e) {
2250
            e.printStackTrace();
2251
            logMetacat.error("removeMapping: AccessionNumber error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
2252
                    + e.getMessage());
2253
        } finally {
2254
            // Return database connection to the pool
2255
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2256
        }
2257
    }
2258
    
2259
    /**
2260
     * create the systemmetadata record
2261
     * @param guid
2262
     * @param dbConn 
2263
     * @throws SQLException 
2264
     */
2265
    private void insertSystemMetadata(String guid, DBConnection dbConn) throws SQLException
2266
    {        
2267

    
2268
        // Execute the insert statement
2269
        String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
2270
        PreparedStatement stmt = dbConn.prepareStatement(query);
2271
        stmt.setString(1, guid);
2272
        logMetacat.debug("system metadata query: " + stmt.toString());
2273
        int rows = stmt.executeUpdate();
2274

    
2275
        stmt.close();
2276
        
2277
    }
2278
    
2279
    public boolean deleteSystemMetadata(String guid)
2280
    {        
2281
        boolean success = false;
2282
        int serialNumber = -1;
2283
        DBConnection dbConn = null;
2284
        String query = null;
2285
        PreparedStatement stmt = null;
2286
        int rows = 0;
2287
        try {
2288

    
2289
        	 // Get a database connection from the pool
2290
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.deleteSystemMetadata");
2291
            serialNumber = dbConn.getCheckOutSerialNumber();
2292
            dbConn.setAutoCommit(false);
2293
        	
2294
            // remove the smReplicationPolicy
2295
            query = "delete from smReplicationPolicy " + 
2296
            "where guid = ?";
2297
            stmt = dbConn.prepareStatement(query);
2298
            stmt.setString(1, guid);
2299
            logMetacat.debug("delete smReplicationPolicy: " + stmt.toString());
2300
            rows = stmt.executeUpdate();
2301
            stmt.close();
2302
            
2303
            // remove the smReplicationStatus
2304
            query = "delete from smReplicationStatus " + 
2305
            "where guid = ?";
2306
            stmt = dbConn.prepareStatement(query);
2307
            stmt.setString(1, guid);
2308
            logMetacat.debug("delete smReplicationStatus: " + stmt.toString());
2309
            rows = stmt.executeUpdate();
2310
            stmt.close();
2311
            
2312
            // remove the smmediatypeproperties
2313
            query = "delete from smmediatypeproperties " + 
2314
                    "where guid = ?";
2315
            stmt = dbConn.prepareStatement(query);
2316
            stmt.setString(1, guid);
2317
            logMetacat.debug("delete smmediatypeproperties: " + stmt.toString());
2318
            rows = stmt.executeUpdate();
2319
            stmt.close();
2320
            
2321
            // remove main system metadata entry
2322
            query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
2323
            stmt = dbConn.prepareStatement(query);
2324
            stmt.setString(1, guid);
2325
            logMetacat.debug("delete system metadata: " + stmt.toString());
2326
            rows = stmt.executeUpdate();
2327
            stmt.close();
2328
            
2329
            dbConn.commit();
2330
            dbConn.setAutoCommit(true);
2331
            success = true;
2332
            // TODO: remove the access?
2333
            // Metacat keeps "deleted" documents so we should not remove access rules.
2334
            
2335
        } catch (Exception e) {
2336
            e.printStackTrace();
2337
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
2338
            try {
2339
				dbConn.rollback();
2340
			} catch (SQLException sqle) {
2341
	            logMetacat.error("Error while rolling back delete for record: " + guid, sqle );
2342
			}
2343
        } finally {
2344
            // Return database connection to the pool
2345
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2346
        }
2347
        return success;
2348
    }
2349
    
2350
    public void updateAuthoritativeMemberNodeId(String existingMemberNodeId, String newMemberNodeId)
2351
    {
2352
        DBConnection dbConn = null;
2353
        int serialNumber = -1;
2354
        
2355
        try {
2356
            // Get a database connection from the pool
2357
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.updateAuthoritativeMemberNodeId");
2358
            serialNumber = dbConn.getCheckOutSerialNumber();
2359

    
2360
            // Execute the insert statement
2361
            String query = "update " + TYPE_SYSTEM_METADATA + 
2362
                " set authoritive_member_node = ? " +
2363
                " where authoritive_member_node = ?";
2364
            PreparedStatement stmt = dbConn.prepareStatement(query);
2365
            
2366
            //data values
2367
            stmt.setString(1, newMemberNodeId);
2368
            stmt.setString(2, existingMemberNodeId);
2369

    
2370
            logMetacat.debug("stmt: " + stmt.toString());
2371
            //execute
2372
            int rows = stmt.executeUpdate();
2373

    
2374
            stmt.close();
2375
        } catch (SQLException e) {
2376
            e.printStackTrace();
2377
            logMetacat.error("updateSystemMetadataFields: SQL error while updating system metadata: " 
2378
                    + e.getMessage());
2379
        } catch (NumberFormatException e) {
2380
            e.printStackTrace();
2381
            logMetacat.error("updateSystemMetadataFields: NumberFormat error while updating system metadata: " 
2382
                    + e.getMessage());
2383
        } finally {
2384
            // Return database connection to the pool
2385
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2386
        }
2387
    }
2388
}
2389

    
(36-36/64)