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
    		// implies all permission, rather than just CHMOD
1753
    		return AccessControlInterface.ALL;
1754
    	}
1755
		return -1;
1756
    }
1757
    
1758
    public List<Permission> convertPermission(int permission) {
1759
    	
1760
    	List<Permission> permissions = new ArrayList<Permission>();
1761
    	if (permission == AccessControlInterface.ALL) {
1762
    		permissions.add(Permission.READ);
1763
    		permissions.add(Permission.WRITE);
1764
    		permissions.add(Permission.CHANGE_PERMISSION);
1765
    		return permissions;
1766
    	}
1767
    	
1768
    	if ((permission & AccessControlInterface.CHMOD) == AccessControlInterface.CHMOD) {
1769
    		permissions.add(Permission.CHANGE_PERMISSION);
1770
    	}
1771
    	if ((permission & AccessControlInterface.READ) == AccessControlInterface.READ) {
1772
    		permissions.add(Permission.READ);
1773
    	}
1774
    	if ((permission & AccessControlInterface.WRITE) == AccessControlInterface.WRITE) {
1775
    		permissions.add(Permission.WRITE);
1776
    	}
1777
    	
1778
		return permissions;
1779
    }
1780
    
1781
    /**
1782
     * Lookup a localId given the GUID. If
1783
     * the identifier is not found, throw an exception.
1784
     * 
1785
     * @param guid the global identifier to look up
1786
     * @return String containing the corresponding LocalId
1787
     * @throws McdbDocNotFoundException if the identifier is not found
1788
     */
1789
    public String getLocalId(String guid) throws McdbDocNotFoundException, SQLException {
1790
      
1791
      String db_guid = "";
1792
      String docid = "";
1793
      int rev = 0;
1794
      
1795
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1796
      
1797
      DBConnection dbConn = null;
1798
      int serialNumber = -1;
1799
      try {
1800
          // Get a database connection from the pool
1801
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1802
          serialNumber = dbConn.getCheckOutSerialNumber();
1803
          
1804
          // Execute the insert statement
1805
          PreparedStatement stmt = dbConn.prepareStatement(query);
1806
          stmt.setString(1, guid);
1807
          ResultSet rs = stmt.executeQuery();
1808
          if (rs.next()) {
1809
              db_guid = rs.getString(1);
1810
              docid = rs.getString(2);
1811
              rev = rs.getInt(3);
1812
              assert(db_guid.equals(guid));
1813
          } else {
1814
              throw new McdbDocNotFoundException("Document not found:" + guid);
1815
          }
1816
          stmt.close();
1817
      } catch (SQLException e) {
1818
          logMetacat.error("Error while looking up the local identifier: " 
1819
                  + e.getMessage());
1820
          throw e;
1821
      } finally {
1822
          // Return database connection to the pool
1823
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1824
      }
1825
      return docid + "." + rev;
1826
    }
1827
    
1828
    /**
1829
     * query the systemmetadata table based on the given parameters
1830
     * @param startTime
1831
     * @param endTime
1832
     * @param objectFormat
1833
     * @param nodeId
1834
     * @param start
1835
     * @param count
1836
     * @return ObjectList
1837
     * @throws SQLException 
1838
     * @throws ServiceException 
1839
     * @throws PropertyNotFoundException 
1840
     */
1841
    public ObjectList querySystemMetadata(Date startTime, Date endTime,
1842
        ObjectFormatIdentifier objectFormatId, NodeReference nodeId,
1843
        int start, int count, Identifier identifier, boolean isSID) 
1844
        throws SQLException, PropertyNotFoundException, ServiceException {
1845
        ObjectList ol = new ObjectList();
1846
        DBConnection dbConn = null;
1847
        int serialNumber = -1;
1848
        PreparedStatement countStmt=null;
1849
        ResultSet totalResult=null;
1850
        PreparedStatement fieldStmt = null;
1851
        ResultSet rs= null;
1852

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

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

    
1870

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
2369
            // Execute the insert statement
2370
            String query = "update " + TYPE_SYSTEM_METADATA + 
2371
                " set authoritive_member_node = ? " +
2372
                " where authoritive_member_node = ?";
2373
            PreparedStatement stmt = dbConn.prepareStatement(query);
2374
            
2375
            //data values
2376
            stmt.setString(1, newMemberNodeId);
2377
            stmt.setString(2, existingMemberNodeId);
2378

    
2379
            logMetacat.debug("stmt: " + stmt.toString());
2380
            //execute
2381
            int rows = stmt.executeUpdate();
2382

    
2383
            stmt.close();
2384
        } catch (SQLException e) {
2385
            e.printStackTrace();
2386
            logMetacat.error("updateSystemMetadataFields: SQL error while updating system metadata: " 
2387
                    + e.getMessage());
2388
        } catch (NumberFormatException e) {
2389
            e.printStackTrace();
2390
            logMetacat.error("updateSystemMetadataFields: NumberFormat error while updating system metadata: " 
2391
                    + e.getMessage());
2392
        } finally {
2393
            // Return database connection to the pool
2394
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2395
        }
2396
    }
2397
}
2398

    
(36-36/64)