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.io.File;
28
import java.math.BigInteger;
29
import java.sql.PreparedStatement;
30
import java.sql.ResultSet;
31
import java.sql.SQLException;
32
import java.sql.Timestamp;
33
import java.util.ArrayList;
34
import java.util.Date;
35
import java.util.HashMap;
36
import java.util.Hashtable;
37
import java.util.List;
38
import java.util.Vector;
39

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

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

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

    
98
    /**
99
     * A private constructor that initializes the class when getInstance() is
100
     * called.
101
     */
102
    private IdentifierManager() {}
103

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

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

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

    
271
        try 
272
        {
273
            // Get a database connection from the pool
274
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getSystemMetadata");
275
            serialNumber = dbConn.getCheckOutSerialNumber();
276

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

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

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

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

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

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

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

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

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

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

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

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

    
1291
	            // Execute the insert statement
1292
	            stmt = dbConn.prepareStatement(query);
1293
	            stmt.setString(1, guid);
1294
	            ResultSet rs = stmt.executeQuery();
1295
	            if (rs.next()) {
1296
	                exists = true;
1297
	            }
1298
	            if(rs != null) {
1299
	                rs.close();
1300
	            }
1301

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

    
1388
            // Get a database connection from the pool
1389
            dbConn = 
1390
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1391
            serialNumber = dbConn.getCheckOutSerialNumber();
1392

    
1393
            // Execute the update statement
1394
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid = ?";
1395
            PreparedStatement stmt = dbConn.prepareStatement(query);
1396
            stmt.setString(1, docid);
1397
            stmt.setInt(2, rev);
1398
            stmt.setString(3, guid);
1399
            int rows = stmt.executeUpdate();
1400

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

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

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

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

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

    
1870
            boolean f1 = false;
1871
            boolean f2 = false;
1872
            boolean f3 = false;
1873
            boolean f4 = false;
1874
            boolean f5 = false;
1875

    
1876

    
1877
            if (startTime != null) {
1878
                whereClauseSql += " where systemmetadata.date_modified >= ?";
1879
                f1 = true;
1880
            }
1881

    
1882
            if (endTime != null) {
1883
                if (!f1) {
1884
                    whereClauseSql += " where systemmetadata.date_modified < ?";
1885
                } else {
1886
                    whereClauseSql += " and systemmetadata.date_modified < ?";
1887
                }
1888
                f2 = true;
1889
            }
1890

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

    
1918
            /*if (!replicaStatus) {
1919
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.nodeId");
1920
                if (!f1 && !f2 && !f3 && !f4) {
1921
                    whereClauseSql += " where authoritive_member_node = '" +
1922
                        currentNodeId.trim() + "'";
1923
                } else {
1924
                    whereClauseSql += " and authoritive_member_node = '" +
1925
                        currentNodeId.trim() + "'";
1926
                }
1927
            }*/
1928
            
1929
            if (nodeId != null && nodeId.getValue() != null && !nodeId.getValue().trim().equals("")) {
1930
                if (!f1 && !f2 && !f3 && !f4) {
1931
                    whereClauseSql += " where authoritive_member_node = '" +
1932
                        nodeId.getValue().trim() + "'";
1933
                } else {
1934
                    whereClauseSql += " and authoritive_member_node = '" +
1935
                        nodeId.getValue().trim() + "'";
1936
                }
1937
                f5 = true;
1938
            }
1939
            
1940
          //add a filter to remove pids whith white spaces
1941
            if(filterWhiteSpaces) {
1942
                logMetacat.debug("IdnetifierManager.querySystemMetadata - the default value of the property \"dataone.listingidentifier.filteringwhitespaces\" is true, so we will filter the white spaces in the query");
1943
                if(!f1 && !f2 && !f3 && !f4 && !f5) {
1944
                    whereClauseSql += " where guid not like '% %' ";
1945
                } else {
1946
                    whereClauseSql += " and guid not like '% %' ";
1947
                }
1948
            } else {
1949
                logMetacat.debug("IdnetifierManager.querySystemMetadata - the property \"dataone.listingidentifier.filteringwhitespaces\" is configured to be false, so we don't filter the white spaces in the query.");
1950
            }
1951
           
1952
            
1953
            // connection
1954
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1955
            serialNumber = dbConn.getCheckOutSerialNumber();
1956

    
1957
            // the field query
1958
            String orderBySql = " order by guid ";
1959
            String fieldQuery = fieldSql + whereClauseSql + orderBySql;
1960
            String finalQuery = DatabaseService.getInstance().getDBAdapter().getPagedQuery(fieldQuery, start, count);
1961
            fieldStmt = dbConn.prepareStatement(finalQuery);
1962
            
1963
            // construct the count query and statment
1964
            String countQuery = countSql + whereClauseSql;
1965
            countStmt = dbConn.prepareStatement(countQuery);
1966

    
1967
            if (f1 && f2 && f3 && f4) {
1968
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1969
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1970
                fieldStmt.setString(3, objectFormatId.getValue());
1971
                fieldStmt.setString(4, identifier.getValue());
1972
                // count
1973
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1974
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1975
                countStmt.setString(3, objectFormatId.getValue());
1976
                countStmt.setString(4, identifier.getValue());
1977
            } if (f1 && f2 && f3 && !f4) {
1978
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1979
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1980
                fieldStmt.setString(3, objectFormatId.getValue());
1981
                // count
1982
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1983
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1984
                countStmt.setString(3, objectFormatId.getValue());
1985
            } else if (f1 && f2 && !f3 && f4) {
1986
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1987
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1988
                fieldStmt.setString(3, identifier.getValue());
1989
                // count
1990
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1991
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1992
                countStmt.setString(3, identifier.getValue());
1993
            } else if (f1 && f2 && !f3 && !f4) {
1994
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1995
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1996
                // count
1997
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1998
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1999
            } else if (f1 && !f2 && f3 && f4) {
2000
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2001
                fieldStmt.setString(2, objectFormatId.getValue());
2002
                fieldStmt.setString(3, identifier.getValue());
2003
                // count
2004
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2005
                countStmt.setString(2, objectFormatId.getValue());
2006
                countStmt.setString(3, identifier.getValue());
2007
            } else if (f1 && !f2 && f3 && !f4) {
2008
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2009
                fieldStmt.setString(2, objectFormatId.getValue());
2010
                // count
2011
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2012
                countStmt.setString(2, objectFormatId.getValue());
2013
            } else if (f1 && !f2 && !f3 && f4) {
2014
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2015
                fieldStmt.setString(2, identifier.getValue());
2016
                // count
2017
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2018
                countStmt.setString(2, identifier.getValue());
2019
            } else if (f1 && !f2 && !f3 && !f4) {
2020
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2021
                // count
2022
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2023
            } else if (!f1 && f2 && f3 && f4) {
2024
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2025
                fieldStmt.setString(2, objectFormatId.getValue());
2026
                fieldStmt.setString(3, identifier.getValue());
2027
                // count
2028
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2029
                countStmt.setString(2, objectFormatId.getValue());
2030
                countStmt.setString(3, identifier.getValue());
2031
            } else if (!f1 && f2 && f3 && !f4) {
2032
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2033
                fieldStmt.setString(2, objectFormatId.getValue());
2034
                // count
2035
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2036
                countStmt.setString(2, objectFormatId.getValue());
2037
            } else if (!f1 && !f2 && f3 && f4) {
2038
                fieldStmt.setString(1, objectFormatId.getValue());
2039
                fieldStmt.setString(2, identifier.getValue());
2040
                // count
2041
                countStmt.setString(1, objectFormatId.getValue());
2042
                countStmt.setString(2, identifier.getValue());
2043
            } else if (!f1 && !f2 && f3 && !f4) {
2044
                fieldStmt.setString(1, objectFormatId.getValue());
2045
                // count
2046
                countStmt.setString(1, objectFormatId.getValue());
2047
            } else if (!f1 && f2 && !f3 && f4) {
2048
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2049
                fieldStmt.setString(2, identifier.getValue());
2050
                // count
2051
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2052
                countStmt.setString(2, identifier.getValue());
2053
            } else if (!f1 && f2 && !f3 && !f4) {
2054
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2055
                // count
2056
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2057
            } else if (!f1 && !f2 && !f3 && f4) {
2058
                fieldStmt.setString(1, identifier.getValue());
2059
                // count
2060
                countStmt.setString(1, identifier.getValue());
2061
            } else if (!f1 && !f2 && !f3 && !f4) {
2062
                //do nothing
2063
            }
2064

    
2065
            logMetacat.info("list objects fieldStmt: " + fieldStmt.toString());
2066
            
2067
            logMetacat.info("list objects countStmt: " + countStmt.toString());
2068
            
2069
            // get the total object count no matter what
2070
            int total = 0;
2071
            totalResult = countStmt.executeQuery();
2072
            if (totalResult.next()) {
2073
            	total = totalResult.getInt(1);
2074
            }
2075
            
2076
            logMetacat.debug("list objects total: " + total);
2077

    
2078
        	// set the totals
2079
        	ol.setStart(start);
2080
            ol.setCount(count);
2081
            
2082
            // retrieve the actual records if requested
2083
            if (count != 0) {
2084
            	
2085
                rs = fieldStmt.executeQuery();
2086
	            while (rs.next()) {                
2087
	                
2088
	                String guid = rs.getString(1);
2089
	                logMetacat.debug("query found object with guid " + guid);
2090
	                // Timestamp dateUploaded = rs.getTimestamp(2);
2091
	                // String rightsHolder = rs.getString(3);
2092
	                String checksum = rs.getString(4);
2093
	                String checksumAlgorithm = rs.getString(5);
2094
	                // String originMemberNode = rs.getString(6);
2095
	                // String authoritiveMemberNode = rs.getString(7);
2096
	                Timestamp dateModified = rs.getTimestamp(8);
2097
	                // String submitter = rs.getString(9);
2098
	                String fmtidStr = rs.getString(10);
2099
	                String sz = rs.getString(11);
2100
	                BigInteger size = new BigInteger("0");
2101
	
2102
	                if (sz != null && !sz.trim().equals("")) {
2103
	                    size = new BigInteger(rs.getString(11));
2104
	                }
2105
	
2106
	                ObjectInfo oi = new ObjectInfo();
2107
	
2108
	                Identifier id = new Identifier();
2109
	                id.setValue(guid);
2110
	                oi.setIdentifier(id);
2111
	
2112
	                if (dateModified != null) {
2113
	                    oi.setDateSysMetadataModified(dateModified);
2114
	                }
2115
	
2116
	                Checksum cs = new Checksum();
2117
	                cs.setValue(checksum);
2118
	                try {
2119
	                    // cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
2120
	                    cs.setAlgorithm(checksumAlgorithm);
2121
	                } catch (Exception e) {
2122
	                    logMetacat.error("could not parse checksum algorithm", e);
2123
	                    continue;
2124
	                }
2125
	                oi.setChecksum(cs);
2126
	
2127
	                // set the format type
2128
	                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
2129
	                fmtid.setValue(fmtidStr);
2130
	                oi.setFormatId(fmtid);
2131
	
2132
	                oi.setSize(size);
2133
	                
2134
	                ol.addObjectInfo(oi);                    
2135

    
2136
	            }
2137
	            
2138
	            logMetacat.debug("list objects count: " + ol.sizeObjectInfoList());
2139
	            // set the actual count retrieved
2140
	            ol.setCount(ol.sizeObjectInfoList());
2141
	            
2142
	
2143
	        }
2144
            ol.setTotal(total);
2145
        } finally {
2146
            // Return database connection to the pool
2147
            try {
2148
                if(totalResult !=null ){
2149
                    totalResult.close();
2150
                }
2151
                if(countStmt!=null ) {
2152
                    countStmt.close();
2153
                }
2154
                if(rs != null) {
2155
                    rs.close();
2156
                }
2157
                if(fieldStmt != null) {
2158
                    fieldStmt.close();
2159
                }
2160
                
2161
            } catch (SQLException sql) {
2162
                
2163
            }
2164
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2165
            
2166
        }
2167
        if(ol != null) {
2168
            logMetacat.debug("list objects start(before returning): " + ol.getStart());
2169
            logMetacat.debug("list objects count: " + ol.getCount());
2170
            logMetacat.debug("list objects total: " + ol.getTotal());
2171
        }
2172
        return ol;
2173
    }
2174
    
2175
    /**
2176
     * create a mapping in the identifier table
2177
     * @param guid
2178
     * @param localId
2179
     */
2180
    public void createMapping(String guid, String localId)
2181
    {        
2182
        
2183
        int serialNumber = -1;
2184
        DBConnection dbConn = null;
2185
        try {
2186

    
2187
            // Parse the localId into scope and rev parts
2188
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
2189
            String docid = acc.getDocid();
2190
            int rev = 1;
2191
            if (acc.getRev() != null) {
2192
              rev = (new Integer(acc.getRev()).intValue());
2193
            }
2194

    
2195
            // Get a database connection from the pool
2196
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
2197
            serialNumber = dbConn.getCheckOutSerialNumber();
2198

    
2199
            // Execute the insert statement
2200
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
2201
            PreparedStatement stmt = dbConn.prepareStatement(query);
2202
            stmt.setString(1, guid);
2203
            stmt.setString(2, docid);
2204
            stmt.setInt(3, rev);
2205
            logMetacat.debug("mapping query: " + stmt.toString());
2206
            int rows = stmt.executeUpdate();
2207

    
2208
            stmt.close();
2209
        } catch (SQLException e) {
2210
            e.printStackTrace();
2211
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
2212
                    + e.getMessage());
2213
        } catch (NumberFormatException e) {
2214
            e.printStackTrace();
2215
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
2216
                    + e.getMessage());
2217
        } catch (AccessionNumberException e) {
2218
            e.printStackTrace();
2219
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
2220
                    + e.getMessage());
2221
        } finally {
2222
            // Return database connection to the pool
2223
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2224
        }
2225
    }
2226
    
2227
    /**
2228
     * remove a mapping in the identifier table
2229
     * @param guid
2230
     * @param localId
2231
     */
2232
    public void removeMapping(String guid, String localId)
2233
    {        
2234
        
2235
        int serialNumber = -1;
2236
        DBConnection dbConn = null;
2237
        try {
2238

    
2239
            // Parse the localId into scope and rev parts
2240
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
2241
            String docid = acc.getDocid();
2242
            int rev = 1;
2243
            if (acc.getRev() != null) {
2244
              rev = (new Integer(acc.getRev()).intValue());
2245
            }
2246

    
2247
            // Get a database connection from the pool
2248
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.removeMapping");
2249
            serialNumber = dbConn.getCheckOutSerialNumber();
2250

    
2251
            // Execute the insert statement
2252
            String query = "DELETE FROM " + TYPE_IDENTIFIER + " WHERE guid = ? AND docid = ? AND rev = ?";
2253
            PreparedStatement stmt = dbConn.prepareStatement(query);
2254
            stmt.setString(1, guid);
2255
            stmt.setString(2, docid);
2256
            stmt.setInt(3, rev);
2257
            logMetacat.debug("remove mapping query: " + stmt.toString());
2258
            int rows = stmt.executeUpdate();
2259

    
2260
            stmt.close();
2261
        } catch (SQLException e) {
2262
            e.printStackTrace();
2263
            logMetacat.error("removeMapping: SQL error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
2264
                    + e.getMessage());
2265
        } catch (NumberFormatException e) {
2266
            e.printStackTrace();
2267
            logMetacat.error("removeMapping: NumberFormat error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
2268
                    + e.getMessage());
2269
        } catch (AccessionNumberException e) {
2270
            e.printStackTrace();
2271
            logMetacat.error("removeMapping: AccessionNumber error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
2272
                    + e.getMessage());
2273
        } finally {
2274
            // Return database connection to the pool
2275
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2276
        }
2277
    }
2278
    
2279
    /**
2280
     * create the systemmetadata record
2281
     * @param guid
2282
     * @param dbConn 
2283
     * @throws SQLException 
2284
     */
2285
    private void insertSystemMetadata(String guid, DBConnection dbConn) throws SQLException
2286
    {        
2287

    
2288
        // Execute the insert statement
2289
        String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
2290
        PreparedStatement stmt = dbConn.prepareStatement(query);
2291
        stmt.setString(1, guid);
2292
        logMetacat.debug("system metadata query: " + stmt.toString());
2293
        int rows = stmt.executeUpdate();
2294

    
2295
        stmt.close();
2296
        
2297
    }
2298
    
2299
    public boolean deleteSystemMetadata(String guid)
2300
    {        
2301
        boolean success = false;
2302
        int serialNumber = -1;
2303
        DBConnection dbConn = null;
2304
        String query = null;
2305
        PreparedStatement stmt = null;
2306
        int rows = 0;
2307
        try {
2308

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

    
2388
            // Execute the insert statement
2389
            String query = "update " + TYPE_SYSTEM_METADATA + 
2390
                " set authoritive_member_node = ? " +
2391
                " where authoritive_member_node = ?";
2392
            PreparedStatement stmt = dbConn.prepareStatement(query);
2393
            
2394
            //data values
2395
            stmt.setString(1, newMemberNodeId);
2396
            stmt.setString(2, existingMemberNodeId);
2397

    
2398
            logMetacat.debug("stmt: " + stmt.toString());
2399
            //execute
2400
            int rows = stmt.executeUpdate();
2401

    
2402
            stmt.close();
2403
        } catch (SQLException e) {
2404
            e.printStackTrace();
2405
            logMetacat.error("updateSystemMetadataFields: SQL error while updating system metadata: " 
2406
                    + e.getMessage());
2407
        } catch (NumberFormatException e) {
2408
            e.printStackTrace();
2409
            logMetacat.error("updateSystemMetadataFields: NumberFormat error while updating system metadata: " 
2410
                    + e.getMessage());
2411
        } finally {
2412
            // Return database connection to the pool
2413
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2414
        }
2415
    }
2416
    
2417
    /**
2418
     * Determine if the object file exist for the given localId.
2419
     * @param localId
2420
     * @param isScienceMetadata
2421
     * @return
2422
     * @throws PropertyNotFoundException
2423
     */
2424
    public boolean objectFileExists(String localId, boolean isScienceMetadata) throws PropertyNotFoundException {
2425
        boolean exist =false;
2426
        if (localId != null) {
2427
            String documentPath = getObjectFilePath(localId, isScienceMetadata);
2428
            if(documentPath != null) {
2429
                File file = new File(documentPath);
2430
                exist = file.exists();
2431
            }
2432
        } 
2433
        logMetacat.debug("IdentifierManager.ObjectFileExist - Does the object file for the local id "+localId+" which is science metadata "+isScienceMetadata+" exist in the Metacast file system? The answer is "+exist);
2434
        return exist;   
2435
    }
2436
    
2437
    /**
2438
     *Get the the file path for the given object local id
2439
     * @param localId
2440
     * @param isScienceMetadata
2441
     * @return
2442
     * @throws PropertyNotFoundException
2443
     */
2444
    public String getObjectFilePath(String localId, boolean isScienceMetadata) throws PropertyNotFoundException {
2445
        String documentPath = null;
2446
        if (localId != null) {      
2447
            String documentDir = null;
2448
            // get the correct location on disk
2449
            if (isScienceMetadata) {
2450
                documentDir = PropertyService.getProperty("application.documentfilepath");
2451
            } else {
2452
                documentDir = PropertyService.getProperty("application.datafilepath");
2453
            }
2454
            documentPath = documentDir + FileUtil.getFS() + localId;
2455
        } 
2456
        logMetacat.debug("IdentifierManager.getObjectFilePath - the file path for the object with localId "+localId+" which is scienceMetacat "+isScienceMetadata+", is "+documentPath+". If the value is null, this means we can't find it.");
2457
        return documentPath;   
2458
    }
2459
    
2460
    /**
2461
     * IF the given localId exists on the xml_revisions table
2462
     * @param localId
2463
     * @return
2464
     * @throws SQLException
2465
     */
2466
    public boolean existsInXmlLRevisionTable(String docid, int rev) throws SQLException{
2467
        boolean exist =false;
2468
        DBConnection conn = null;
2469
        int serialNumber = -1;
2470
        PreparedStatement pstmt = null;
2471
        ResultSet rs = null;
2472
        logMetacat.info("IdentifierManager.existsInXmlLRevisionTable - the docid is "+docid +" and rev is "+rev);
2473
        try {
2474
            //check out DBConnection
2475
            conn = DBConnectionPool.getDBConnection("IdentifierManager.existsInXmlLRevisionTable");
2476
            serialNumber = conn.getCheckOutSerialNumber();
2477
            // Check if the document exists in xml_revisions table.
2478
            //this only archives a document from xml_documents to xml_revisions (also archive the xml_nodes table as well)
2479
            logMetacat.debug("IdentifierManager.existsInXmlLRevisionTable - check if the document "+docid+"."+rev+ " exists in the xml_revision table");
2480
            pstmt = conn.prepareStatement("SELECT rev, docid FROM xml_revisions WHERE docid = ? AND rev = ?");
2481
            pstmt.setString(1, docid);
2482
            pstmt.setInt(2, rev);
2483
            logMetacat.debug("IdentifierManager.existsInXmlLRevisionTable - executing SQL: " + pstmt.toString());
2484
            pstmt.execute();
2485
            rs = pstmt.getResultSet();
2486
            if(rs.next()){
2487
                exist = true;
2488
            }
2489
            conn.increaseUsageCount(1);
2490
        } catch (Exception e) {
2491
            throw new SQLException(e.getMessage());
2492
        } finally {
2493
            // Return database connection to the pool
2494
            DBConnectionPool.returnDBConnection(conn, serialNumber);
2495
            if(rs != null) {
2496
                rs.close();
2497
            }
2498
            if(pstmt != null) {
2499
                pstmt.close();
2500
            }
2501
        }
2502
        logMetacat.info("IdentifierManager.existsInXmlLRevisionTable - Does the docid "+docid+"."+rev+ " exist in the xml_revision table? - "+exist);
2503
        return exist;
2504
    }
2505
}
2506

    
(36-36/64)