Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2010 Regents of the University of California and the
4
 *             National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: jones $'
7
 *     '$Date: 2010-02-03 17:58:12 -0900 (Wed, 03 Feb 2010) $'
8
 * '$Revision: 5211 $'
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, write to the Free Software
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 */
24

    
25
package edu.ucsb.nceas.metacat;
26

    
27
import java.math.BigInteger;
28
import java.sql.PreparedStatement;
29
import java.sql.ResultSet;
30
import java.sql.SQLException;
31
import java.sql.Timestamp;
32
import java.util.ArrayList;
33
import java.util.Date;
34
import java.util.Hashtable;
35
import java.util.List;
36
import java.util.Vector;
37

    
38
import org.apache.log4j.Logger;
39
import org.dataone.client.ObjectFormatCache;
40
import org.dataone.service.exceptions.NotFound;
41
import org.dataone.service.types.v1.AccessPolicy;
42
import org.dataone.service.types.v1.AccessRule;
43
import org.dataone.service.types.v1.Checksum;
44
import org.dataone.service.types.v1.Identifier;
45
import org.dataone.service.types.v1.NodeReference;
46
import org.dataone.service.types.v1.ObjectFormat;
47
import org.dataone.service.types.v1.ObjectFormatIdentifier;
48
import org.dataone.service.types.v1.ObjectInfo;
49
import org.dataone.service.types.v1.ObjectList;
50
import org.dataone.service.types.v1.Permission;
51
import org.dataone.service.types.v1.Replica;
52
import org.dataone.service.types.v1.ReplicationPolicy;
53
import org.dataone.service.types.v1.ReplicationStatus;
54
import org.dataone.service.types.v1.Subject;
55
import org.dataone.service.types.v1.SystemMetadata;
56

    
57
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlInterface;
58
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
59
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
60
import edu.ucsb.nceas.metacat.database.DBConnection;
61
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
62
import edu.ucsb.nceas.metacat.properties.PropertyService;
63
import edu.ucsb.nceas.metacat.shared.AccessException;
64
import edu.ucsb.nceas.metacat.shared.ServiceException;
65
import edu.ucsb.nceas.metacat.util.DocumentUtil;
66
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
67

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

    
88
    /**
89
     * A private constructor that initializes the class when getInstance() is
90
     * called.
91
     */
92
    private IdentifierManager() {}
93

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

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

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

    
260
            // Execute the statement
261
            PreparedStatement stmt = dbConn.prepareStatement(sql);
262
            stmt.setString(1, guid);
263
            ResultSet rs = stmt.executeQuery();
264
            if (rs.next()) 
265
            {
266
                Timestamp dateUploaded = rs.getTimestamp(2);
267
                String rightsHolder = rs.getString(3);
268
                String checksum = rs.getString(4);
269
                String checksumAlgorithm = rs.getString(5);
270
                String originMemberNode = rs.getString(6);
271
                String authoritativeMemberNode = rs.getString(7);
272
                Timestamp dateModified = rs.getTimestamp(8);
273
                String submitter = rs.getString(9);
274
                String fmtidStr = rs.getString(10);
275
                BigInteger size = new BigInteger(rs.getString(11));
276
                replicationAllowed = new Boolean(rs.getBoolean(12));
277
                numberOfReplicas = new BigInteger(rs.getString(13));
278
                String obsoletes = rs.getString(14);
279
                String obsoletedBy = rs.getString(15);
280

    
281
                Identifier sysMetaId = new Identifier();
282
                sysMetaId.setValue(guid);
283
                sysMeta.setIdentifier(sysMetaId);
284
                sysMeta.setDateUploaded(dateUploaded);
285
                Subject rightsHolderSubject = new Subject();
286
                rightsHolderSubject.setValue(rightsHolder);
287
                sysMeta.setRightsHolder(rightsHolderSubject);
288
                Checksum checksumObject = new Checksum();
289
                checksumObject.setValue(checksum);
290
                checksumObject.setAlgorithm(checksumAlgorithm);
291
                sysMeta.setChecksum(checksumObject);
292
                if (originMemberNode != null) {
293
	                NodeReference omn = new NodeReference();
294
	                omn.setValue(originMemberNode);
295
	                sysMeta.setOriginMemberNode(omn);
296
                }
297
                if (authoritativeMemberNode != null) {
298
	                NodeReference amn = new NodeReference();
299
	                amn.setValue(authoritativeMemberNode);
300
	                sysMeta.setAuthoritativeMemberNode(amn);
301
                }
302
                sysMeta.setDateSysMetadataModified(dateModified);
303
                Subject submitterSubject = new Subject();
304
                submitterSubject.setValue(submitter);
305
                sysMeta.setSubmitter(submitterSubject);
306
                try {
307
                	ObjectFormatIdentifier fmtid = 
308
                		ObjectFormatCache.getInstance().getFormat(fmtidStr).getFmtid();
309
                	sysMeta.setFmtid(fmtid);
310
                } catch (NotFound nfe) {
311
                  logMetacat.error("The objectFormat " + fmtidStr +
312
                  	" is not registered. Setting the default format id.");
313
                  ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
314
                  fmtid.setValue("application/octet-stream");
315
                  sysMeta.setFmtid(fmtid);
316
                }
317
                sysMeta.setSize(size);
318
                if (obsoletes != null) {
319
	                Identifier obsoletesId = new Identifier();
320
	                obsoletesId.setValue(obsoletes);
321
	                sysMeta.setObsoletes(obsoletesId);
322
                }
323
                if (obsoletedBy != null) {
324
		            Identifier obsoletedById = new Identifier();
325
		            obsoletedById.setValue(obsoletedBy);
326
		            sysMeta.setObsoletedBy(obsoletedById);
327
                }
328
                stmt.close();
329
            } 
330
            else
331
            {
332
                stmt.close();
333
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
334
                throw new McdbDocNotFoundException("Could not find " + guid);
335
            }
336
            
337
        } 
338
        catch (SQLException e) 
339
        {
340
            e.printStackTrace();
341
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "  
342
                    + e.getMessage());
343
        } 
344
        finally 
345
        {
346
            // Return database connection to the pool
347
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
348
        }
349

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

    
493
            // Execute the insert statement
494
            PreparedStatement stmt = dbConn.prepareStatement(sql);
495
            ResultSet rs = stmt.executeQuery();
496
            if (rs.next()) 
497
            {
498
                String docname = rs.getString(1);
499
                String doctype = rs.getString(2);
500
                String user_owner = rs.getString(3);
501
                String user_updated = rs.getString(4);
502
                String server_location = rs.getString(5);
503
                int rev = rs.getInt(6);
504
                String date_created = rs.getString(7);
505
                String date_updated = rs.getString(8);
506
                h.put("docid", localId);
507
                h.put("docname", docname);
508
                h.put("doctype", doctype);
509
                h.put("user_owner", user_owner);
510
                h.put("user_updated", user_updated);
511
                h.put("server_location", server_location);
512
                h.put("rev", new Integer(rev).toString());
513
                h.put("date_created", date_created);
514
                h.put("date_updated", date_updated);
515
                
516
                stmt.close();
517
            } 
518
            else
519
            {
520
                stmt.close();
521
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
522
                throw new McdbDocNotFoundException("2Could not find document " + localId);
523
            }
524
            
525
            String sql2 = "select principal_name, permission, perm_type, perm_order from xml_access " +
526
            "where docid like '" + localId + "'";
527
            logMetacat.debug("executing sql: " + sql2);
528
            PreparedStatement stmt2 = dbConn.prepareStatement(sql2);
529
            rs = stmt2.executeQuery();
530
            Vector accessVector = new Vector();
531
            while(rs.next())
532
            {
533
                Hashtable accessHash = new Hashtable();
534
                String principal_name = rs.getString(1);
535
                String permission = rs.getString(2);
536
                String permissionType = rs.getString(3);
537
                String permissionOrder = rs.getString(4);
538
                accessHash.put("principal_name", principal_name);
539
                accessHash.put("permission", permission);
540
                accessHash.put("permission_type", permissionType);
541
                accessHash.put("permission_order", permissionOrder);
542
                logMetacat.debug("accessHash: " + accessHash.toString());
543
                accessVector.add(accessHash);
544
            }
545
            h.put("access", accessVector);
546
        } 
547
        catch (SQLException e) 
548
        {
549
            e.printStackTrace();
550
            logMetacat.error("Error while getting document info for localid " + localId + " : "  
551
                    + e.getMessage());
552
        } 
553
        finally 
554
        {
555
            // Return database connection to the pool
556
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
557
        }
558
        return h;
559
    }
560
    
561
    /**
562
     * return the newest rev for a given localId
563
     * @param localId
564
     * @return
565
     */
566
    public int getLatestRevForLocalId(String localId)
567
        throws McdbDocNotFoundException
568
    {
569
        try
570
        {
571
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
572
            localId = acc.getDocid();
573
        }
574
        catch(Exception e)
575
        {
576
            //do nothing. just try the localId as it is
577
        }
578
        int rev = 0;
579
        String sql = "select rev from xml_documents where docid like '" + localId + "'";
580
        DBConnection dbConn = null;
581
        int serialNumber = -1;
582
        try 
583
        {
584
            // Get a database connection from the pool
585
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLatestRevForLocalId");
586
            serialNumber = dbConn.getCheckOutSerialNumber();
587

    
588
            // Execute the insert statement
589
            PreparedStatement stmt = dbConn.prepareStatement(sql);
590
            ResultSet rs = stmt.executeQuery();
591
            if (rs.next()) 
592
            {
593
                rev = rs.getInt(1);
594
                stmt.close();
595
            } 
596
            else
597
            {
598
                stmt.close();
599
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
600
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
601
            }
602
        } 
603
        catch (SQLException e) 
604
        {
605
            logMetacat.error("Error while looking up the guid: " 
606
                    + e.getMessage());
607
        } 
608
        finally 
609
        {
610
            // Return database connection to the pool
611
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
612
        }
613
        return rev;
614
    }
615
    
616
    /**
617
     * return all local ids in the object store that do not have associated
618
     * system metadata
619
     */
620
    public List<String> getLocalIdsWithNoSystemMetadata()
621
    {
622
        Vector<String> ids = new Vector<String>();
623
        String sql = "select docid, rev from xml_documents " +
624
        		"where docid not in " +
625
        		"(select docid from identifier where guid in (select guid from systemmetadata)))";
626
        DBConnection dbConn = null;
627
        int serialNumber = -1;
628
        try 
629
        {
630
            // Get a database connection from the pool
631
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
632
            serialNumber = dbConn.getCheckOutSerialNumber();
633

    
634
            // Execute the insert statement
635
            PreparedStatement stmt = dbConn.prepareStatement(sql);
636
            ResultSet rs = stmt.executeQuery();
637
            while (rs.next()) 
638
            {
639
                String localid = rs.getString(1);
640
                String rev = rs.getString(2);
641
                localid += "." + rev;
642
                logMetacat.debug("id to add SM for: " + localid);
643
                ids.add(localid);
644
            } 
645
            stmt.close();
646
        } 
647
        catch (SQLException e) 
648
        {
649
            logMetacat.error("Error while looking up the guid: " 
650
                    + e.getMessage());
651
        } 
652
        finally 
653
        {
654
            // Return database connection to the pool
655
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
656
        }
657
        
658
        return ids;
659
    }
660
    
661
    /**
662
     * return a listing of all local ids in the object store
663
     * @return a list of all local ids in metacat
664
     */
665
    public List<String> getAllLocalIds()
666
    // seems to be an unnecessary and restrictive throw -rnahf 13-Sep-2011
667
    //    throws Exception
668
    {
669
        Vector<String> ids = new Vector<String>();
670
        String sql = "select docid from xml_documents";
671
        DBConnection dbConn = null;
672
        int serialNumber = -1;
673
        try 
674
        {
675
            // Get a database connection from the pool
676
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
677
            serialNumber = dbConn.getCheckOutSerialNumber();
678

    
679
            // Execute the insert statement
680
            PreparedStatement stmt = dbConn.prepareStatement(sql);
681
            ResultSet rs = stmt.executeQuery();
682
            while (rs.next()) 
683
            {
684
                String localid = rs.getString(1);
685
                ids.add(localid);
686
            } 
687
            stmt.close();
688
        } 
689
        catch (SQLException e) 
690
        {
691
            logMetacat.error("Error while looking up the guid: " 
692
                    + e.getMessage());
693
        } 
694
        finally 
695
        {
696
            // Return database connection to the pool
697
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
698
        }
699
        return ids;
700
    }
701
    
702
    
703
    /**
704
     * return a listing of all guids in the object store
705
     * @return a list of all GUIDs in metacat
706
     */
707
    public List<String> getAllGUIDs()
708
    {
709
        Vector<String> guids = new Vector<String>();
710
        String sql = "select guid from identifier";
711
        DBConnection dbConn = null;
712
        int serialNumber = -1;
713
        try 
714
        {
715
            // Get a database connection from the pool
716
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllGUIDs");
717
            serialNumber = dbConn.getCheckOutSerialNumber();
718

    
719
            // Execute the insert statement
720
            PreparedStatement stmt = dbConn.prepareStatement(sql);
721
            ResultSet rs = stmt.executeQuery();
722
            while (rs.next()) 
723
            {
724
                String guid = rs.getString(1);
725
                guids.add(guid);
726
            } 
727
            stmt.close();
728
        } 
729
        catch (SQLException e) 
730
        {
731
            logMetacat.error("Error while retrieving the guid: " 
732
                    + e.getMessage());
733
        } 
734
        finally 
735
        {
736
            // Return database connection to the pool
737
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
738
        }
739
        return guids;
740
    }
741
    
742
    
743
    
744
    /**
745
     * returns a list of system metadata-only guids since the given date
746
     * @return a list of system ids in metacat that do not correspond to objects
747
     * TODO: need to check which server they are on
748
     */
749
    public List<String> getUpdatedSystemMetadataIds(Date since)
750
       throws Exception
751
    {
752
        List<String> ids = new Vector<String>();
753
        String sql = 
754
        	"select guid from " + TYPE_SYSTEM_METADATA +
755
        	" where guid not in " +
756
        	" (select guid from " + TYPE_IDENTIFIER + ") " +
757
        	" and date_modified > ?";
758
        DBConnection dbConn = null;
759
        int serialNumber = -1;
760
        try 
761
        {
762
            // Get a database connection from the pool
763
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getUpdatedSystemMetadataIds");
764
            serialNumber = dbConn.getCheckOutSerialNumber();
765

    
766
            // Execute the insert statement
767
            PreparedStatement stmt = dbConn.prepareStatement(sql);
768
            stmt.setDate(1, new java.sql.Date(since.getTime()));
769
            ResultSet rs = stmt.executeQuery();
770
            while (rs.next()) 
771
            {
772
                String guid = rs.getString(1);
773
                ids.add(guid);
774
            } 
775
            stmt.close();
776
        } 
777
        catch (SQLException e) 
778
        {
779
            logMetacat.error("Error while looking up the updated guids: " 
780
                    + e.getMessage());
781
        } 
782
        finally 
783
        {
784
            // Return database connection to the pool
785
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
786
        }
787
        return ids;
788
    }
789
    
790
    /**
791
     * returns a list of system metadata-only guids since the given date
792
     * @return a list of system ids in metacat that do not correspond to objects
793
     * TODO: need to check which server they are on
794
     */
795
    public Date getLastModifiedDate() throws Exception {
796
        Date maxDate = null;
797

    
798
        List<String> ids = new Vector<String>();
799
        String sql = 
800
        	"select max(date_modified) from " + TYPE_SYSTEM_METADATA;
801
        DBConnection dbConn = null;
802
        int serialNumber = -1;
803
        try 
804
        {
805
            // Get a database connection from the pool
806
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLastModifiedDate");
807
            serialNumber = dbConn.getCheckOutSerialNumber();
808

    
809
            // Execute the insert statement
810
            PreparedStatement stmt = dbConn.prepareStatement(sql);
811
            ResultSet rs = stmt.executeQuery();
812
            if (rs.next()) {
813
            	maxDate = rs.getDate(1);
814
            } 
815
            stmt.close();
816
        } 
817
        catch (SQLException e) 
818
        {
819
            logMetacat.error("Error while looking up the latest update date: " 
820
                    + e.getMessage());
821
        } 
822
        finally 
823
        {
824
            // Return database connection to the pool
825
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
826
        }
827
        return maxDate;
828
    }
829

    
830
    
831
    /**
832
     * Determine if an identifier exists already, returning true if so.
833
     * 
834
     * @param guid the global identifier to look up
835
     * @return boolean true if the identifier exists
836
     */
837
    public boolean identifierExists(String guid)
838
    {
839
        boolean idExists = false;
840
        try {
841
            String id = getLocalId(guid);
842
            if (id != null) {
843
                idExists = true;
844
            }
845
        } catch (McdbDocNotFoundException e) {
846
        	// try system metadata only
847
        	try {
848
        		idExists = systemMetadataExists(guid);
849
            } catch (Exception e2) {
850
            	idExists = false;
851
            }
852
        }
853
        return idExists;
854
    }
855
    
856
    /**
857
     * 
858
     * @param guid
859
     * @param rev
860
     * @return
861
     */
862
    public String generateLocalId(String guid, int rev)
863
    {
864
        return generateLocalId(guid, rev, false);
865
    }
866

    
867
    /**
868
     * Given a global identifier (guid), create a suitable local identifier that
869
     * follows Metacat's docid semantics and format (scope.id.rev), and create
870
     * a mapping between these two identifiers.  This effectively reserves both
871
     * the global and the local identifier, as they will now be present in the
872
     * identifier mapping table.  If the incoming guid has the syntax of a
873
     * Metacat docid (scope.id.rev), then simply use it.
874
     * 
875
     * @param guid the global string identifier
876
     * @param rev the revision number to be used in the localId
877
     * @return String containing the localId to be used for Metacat operations
878
     */
879
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata) 
880
    {
881
        String localId = "";
882
        boolean conformsToDocidFormat = false;
883
        
884
        // Check if the guid passed in is already in docid (scope.id.rev) format
885
        try {
886
            AccessionNumber acc = new AccessionNumber(guid, "NONE");
887
            if (new Integer(acc.getRev()).intValue() > 0) {
888
                conformsToDocidFormat = true;
889
            }
890
        } catch (NumberFormatException e) {
891
            // No action needed, simply detecting invalid AccessionNumbers
892
        } catch (AccessionNumberException e) {
893
            // No action needed, simply detecting invalid AccessionNumbers
894
        } catch (SQLException e) {
895
            // No action needed, simply detecting invalid AccessionNumbers
896
        }
897
        
898
        if (conformsToDocidFormat) {
899
            // if it conforms, use it for both guid and localId
900
            localId = guid;
901
        } else {
902
            // if not, then generate a new unique localId
903
            localId = DocumentUtil.generateDocumentId(rev);
904
        }
905
        
906
        // Register this new pair in the identifier mapping table
907
        logMetacat.debug("creating mapping in generateLocalId");
908
        if(!isSystemMetadata)
909
        { //don't do this if we're generating for system metadata
910
            createMapping(guid, localId);
911
        }
912
        
913
        return localId;
914
    }
915
    
916
    /**
917
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
918
     * if the docid, rev is not found in the identifiers or systemmetadata tables
919
     *
920
     * @param docid the docid to look up
921
     * @param rev the revision of the docid to look up
922
     * @return String containing the mapped guid
923
     * @throws McdbDocNotFoundException if the docid, rev is not found
924
     */
925
    public String getGUID(String docid, int rev)
926
      throws McdbDocNotFoundException
927
    {
928
        logMetacat.debug("getting guid for " + docid);
929
        String query = "select guid from identifier where docid = ? and rev = ?";
930
        String guid = null;
931
        
932
        DBConnection dbConn = null;
933
        int serialNumber = -1;
934
        try {
935
            // Get a database connection from the pool
936
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
937
            serialNumber = dbConn.getCheckOutSerialNumber();
938
            
939
            // Execute the insert statement
940
            PreparedStatement stmt = dbConn.prepareStatement(query);
941
            stmt.setString(1, docid);
942
            stmt.setInt(2, rev);
943
            ResultSet rs = stmt.executeQuery();
944
            if (rs.next()) 
945
            {
946
                guid = rs.getString(1);
947
            } 
948
            else
949
            {
950
            	throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
951
            }
952
            
953
        } catch (SQLException e) {
954
            logMetacat.error("Error while looking up the guid: " 
955
                    + e.getMessage());
956
        } finally {
957
            // Return database connection to the pool
958
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
959
        }
960
        
961
        return guid;
962
    }
963
    
964
    public boolean systemMetadataExists(String guid) {
965
		logMetacat.debug("looking up system metadata for guid " + guid);
966
		boolean exists = false;
967
		String query = "select guid from systemmetadata where guid = ?";
968

    
969
		DBConnection dbConn = null;
970
		int serialNumber = -1;
971
		try {
972
			// Get a database connection from the pool
973
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
974
			serialNumber = dbConn.getCheckOutSerialNumber();
975

    
976
			// Execute the insert statement
977
			PreparedStatement stmt = dbConn.prepareStatement(query);
978
			stmt.setString(1, guid);
979
			ResultSet rs = stmt.executeQuery();
980
			if (rs.next()) {
981
				exists = true;
982
			}
983

    
984
		} catch (SQLException e) {
985
			logMetacat.error("Error while looking up the system metadata: "
986
					+ e.getMessage());
987
		} finally {
988
			// Return database connection to the pool
989
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
990
		}
991

    
992
		return exists;
993
	}
994
    
995
    /**
996
     * creates a system metadata mapping and adds additional fields from sysmeta
997
     * to the table for quick searching.
998
     * 
999
     * @param guid the id to insert
1000
     * @param localId the systemMetadata object to get the local id for
1001
     * @throws McdbDocNotFoundException 
1002
     */
1003
    public void createSystemMetadata(SystemMetadata sysmeta) throws McdbDocNotFoundException
1004
    {
1005
    	String guid = sysmeta.getIdentifier().getValue();
1006
    	// insert the record
1007
        insertSystemMetadata(guid);
1008
        // update with the values
1009
        updateSystemMetadata(sysmeta);
1010
    }
1011
        
1012
    
1013
    /**
1014
     * update a mapping
1015
     * @param guid
1016
     * @param localId
1017
     */
1018
    public void updateMapping(String guid, String localId)
1019
    {
1020
    	
1021
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
1022
        int serialNumber = -1;
1023
        DBConnection dbConn = null;
1024
        try {
1025
            // Parse the localId into scope and rev parts
1026
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1027
            String docid = acc.getDocid();
1028
            int rev = 1;
1029
            if(acc.getRev() != null)
1030
            {
1031
              rev = (new Integer(acc.getRev()).intValue());
1032
            }
1033

    
1034
            // Get a database connection from the pool
1035
            dbConn = 
1036
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1037
            serialNumber = dbConn.getCheckOutSerialNumber();
1038

    
1039
            // Execute the update statement
1040
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid='" + guid + "'";
1041
            PreparedStatement stmt = dbConn.prepareStatement(query);
1042
            stmt.setString(1, docid);
1043
            stmt.setInt(2, rev);
1044
            int rows = stmt.executeUpdate();
1045

    
1046
            stmt.close();
1047
        } catch (SQLException e) {
1048
            e.printStackTrace();
1049
            logMetacat.error("SQL error while updating a mapping identifier: " 
1050
                    + e.getMessage());
1051
        } catch (NumberFormatException e) {
1052
            e.printStackTrace();
1053
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
1054
                    + e.getMessage());
1055
        } catch (AccessionNumberException e) {
1056
            e.printStackTrace();
1057
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
1058
                    + e.getMessage());
1059
        } finally {
1060
            // Return database connection to the pool
1061
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1062
        }
1063
        logMetacat.debug("done updating mapping");
1064
    }
1065
        
1066
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1067
            String checksum, String checksumAlgorithm, String originMemberNode,
1068
            String authoritativeMemberNode, long modifiedDate, String submitter, 
1069
            String guid, String objectFormat, BigInteger size, boolean replicationAllowed,
1070
            int numberReplicas, String obsoletes, String obsoletedBy)
1071
    {
1072
        DBConnection dbConn = null;
1073
        int serialNumber = -1;
1074
        
1075
        try {
1076
            // Get a database connection from the pool
1077
            dbConn = 
1078
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1079
            serialNumber = dbConn.getCheckOutSerialNumber();
1080

    
1081
            // Execute the insert statement
1082
            String query = "update " + TYPE_SYSTEM_METADATA + 
1083
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1084
                "origin_member_node, authoritive_member_node, date_modified, " +
1085
                "submitter, object_format, size, replication_allowed, number_replicas, obsoletes, obsoleted_by) " +
1086
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1087
            PreparedStatement stmt = dbConn.prepareStatement(query);
1088
            
1089
            //data values
1090
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1091
            stmt.setString(2, rightsHolder);
1092
            stmt.setString(3, checksum);
1093
            stmt.setString(4, checksumAlgorithm);
1094
            stmt.setString(5, originMemberNode);
1095
            stmt.setString(6, authoritativeMemberNode);
1096
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1097
            stmt.setString(8, submitter);
1098
            stmt.setString(9, objectFormat);
1099
            stmt.setString(10, size.toString());
1100
            stmt.setBoolean(11, replicationAllowed);
1101
            stmt.setInt(12, numberReplicas);
1102
            stmt.setString(13, obsoletes);
1103
            stmt.setString(14, obsoletedBy);
1104

    
1105
            //where clause
1106
            stmt.setString(15, guid);
1107
            logMetacat.debug("stmt: " + stmt.toString());
1108
            //execute
1109
            int rows = stmt.executeUpdate();
1110

    
1111
            stmt.close();
1112
        } catch (SQLException e) {
1113
            e.printStackTrace();
1114
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: " 
1115
                    + e.getMessage());
1116
        } catch (NumberFormatException e) {
1117
            e.printStackTrace();
1118
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: " 
1119
                    + e.getMessage());
1120
        } finally {
1121
            // Return database connection to the pool
1122
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1123
        }
1124
    }
1125
    
1126
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes)
1127
    {
1128
        DBConnection dbConn = null;
1129
        int serialNumber = -1;
1130
        
1131
        try {
1132
            // Get a database connection from the pool
1133
            dbConn = 
1134
                DBConnectionPool.getDBConnection("IdentifierManager.insertReplicationPolicy");
1135
            serialNumber = dbConn.getCheckOutSerialNumber();
1136

    
1137
            // remove existing values first
1138
            String delete = "delete from systemMetadataReplicationPolicy " + 
1139
            "where guid = ? and policy = ?";
1140
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1141
	        //data values
1142
	        stmt.setString(1, guid);
1143
	        stmt.setString(2, policy);
1144
	        //execute
1145
	        int deletedCount = stmt.executeUpdate();
1146
	        stmt.close();
1147
            
1148
            for (String memberNode: memberNodes) {
1149
	            // Execute the insert statement
1150
	            String insert = "insert into systemMetadataReplicationPolicy " + 
1151
	                "(guid, policy, member_node) " +
1152
	                "values (?, ?, ?)";
1153
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1154
	            
1155
	            //data values
1156
	            insertStatement.setString(1, guid);
1157
	            insertStatement.setString(2, policy);
1158
	            insertStatement.setString(3, memberNode);
1159
	            //execute
1160
	            int rows = insertStatement.executeUpdate();
1161
	            insertStatement.close();
1162
            }
1163
        } catch (SQLException e) {
1164
            logMetacat.error("SQL error while adding systemMetadataReplicationPolicy for: " + guid, e); 
1165
        } finally {
1166
            // Return database connection to the pool
1167
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1168
        }
1169
    }
1170
    
1171
    private void insertReplicationStatus(String guid, List<Replica> replicas) {
1172
        DBConnection dbConn = null;
1173
        int serialNumber = -1;
1174
        
1175
        try {
1176
            // Get a database connection from the pool
1177
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertReplicas");
1178
            serialNumber = dbConn.getCheckOutSerialNumber();
1179

    
1180
            // remove existing values first
1181
            String delete = "delete from systemMetadataReplicationStatus " + 
1182
            "where guid = ?";
1183
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1184
	        //data values
1185
	        stmt.setString(1, guid);
1186
	        //execute
1187
	        int deletedCount = stmt.executeUpdate();
1188
	        stmt.close();
1189
            
1190
	        if (replicas != null) {
1191
	            for (Replica replica: replicas) {
1192
		            // Execute the insert statement
1193
		            String insert = "insert into systemMetadataReplicationStatus " + 
1194
		                "(guid, member_node, status, date_verified) " +
1195
		                "values (?, ?, ?, ?)";
1196
		            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1197
		            
1198
		            //data values
1199
		            String memberNode = replica.getReplicaMemberNode().getValue();
1200
		            String status = replica.getReplicationStatus().toString();
1201
		            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1202
		            insertStatement.setString(1, guid);
1203
		            insertStatement.setString(2, memberNode);
1204
		            insertStatement.setString(3, status);
1205
		            insertStatement.setDate(4, sqlDate);
1206
	
1207
		            //execute
1208
		            int rows = insertStatement.executeUpdate();
1209
		            insertStatement.close();
1210
	            }
1211
	        }
1212
        } catch (SQLException e) {
1213
            logMetacat.error("SQL error while adding systemMetadataReplicationStatus for: " + guid, e); 
1214
        } finally {
1215
            // Return database connection to the pool
1216
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1217
        }
1218
    }
1219
    
1220
    /**
1221
     * Insert the system metadata fields into the db
1222
     * @param sm
1223
     * @throws McdbDocNotFoundException 
1224
     */
1225
    public void updateSystemMetadata(SystemMetadata sm) throws McdbDocNotFoundException {
1226
    	
1227
        Boolean replicationAllowed = false;
1228
		Integer numberReplicas = -1;
1229
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1230
    	if (replicationPolicy != null) {
1231
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1232
    		numberReplicas = replicationPolicy.getNumberReplicas();
1233
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1234
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1235
    	}
1236

    
1237
    	// the main systemMetadata fields
1238
		updateSystemMetadataFields(
1239
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1240
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(), 
1241
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(), 
1242
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm(), 
1243
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1244
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(), 
1245
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1246
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(), 
1247
        sm.getIdentifier().getValue(),
1248
        sm.getFmtid() == null ? null: sm.getFmtid().getValue(),
1249
        sm.getSize(),
1250
        replicationAllowed, 
1251
        numberReplicas,
1252
        sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
1253
        sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue());
1254
        
1255
        String guid = sm.getIdentifier().getValue();
1256
        
1257
        // save replication policies
1258
        if (replicationPolicy != null) {
1259
		    List<String> nodes = null;
1260
		    String policy = null;
1261
		    
1262
		    // check for null 
1263
		    if (replicationPolicy.getBlockedMemberNodeList() != null) {
1264
			    nodes = new ArrayList<String>();
1265
			    policy = "blocked";
1266
			    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1267
			    	nodes.add(node.getValue());
1268
			    }
1269
			    this.insertReplicationPolicy(guid, policy, nodes);
1270
		    }
1271
		    
1272
		    if (replicationPolicy.getPreferredMemberNodeList() != null) {
1273
			    nodes = new ArrayList<String>();
1274
			    policy = "preferred";
1275
			    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1276
			    	nodes.add(node.getValue());
1277
			    }
1278
		        this.insertReplicationPolicy(guid, policy, nodes);
1279
		    }
1280
        }
1281
        
1282
        // save replica information
1283
        this.insertReplicationStatus(guid, sm.getReplicaList());
1284
        
1285
        // save access policy
1286
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1287
        if (accessPolicy != null) {
1288
        	try {
1289
				this.insertAccessPolicy(guid, accessPolicy);
1290
			} catch (AccessException e) {
1291
				throw new McdbDocNotFoundException(e);
1292
			}
1293
        }
1294
    }
1295
    
1296
    /**
1297
     * Creates Metacat access rules and inserts them
1298
     * @param accessPolicy
1299
     * @throws McdbDocNotFoundException
1300
     * @throws AccessException
1301
     */
1302
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1303
    	
1304
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1305
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1306
        	List<Subject> subjects = accessRule.getSubjectList();
1307
        	List<Permission> permissions = accessRule.getPermissionList();
1308
        	for (Subject subject: subjects) {
1309
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1310
        		accessDAO.setPrincipalName(subject.getValue());
1311
    			accessDAO.setGuid(guid);
1312
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1313
    			accessDAO.setPermOrder(AccessControlInterface.DENYFIRST);
1314
    			for (Permission permission: permissions) {
1315
    				Long metacatPermission = new Long(convertPermission(permission));
1316
        			accessDAO.addPermission(metacatPermission);
1317
    			}
1318
    			accessDAOs.add(accessDAO);
1319
        	}
1320
        }
1321
        
1322
        // use GUID to update
1323
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1324
        accessController.replaceAccess(guid, accessDAOs);
1325
        
1326
        
1327
    }
1328
    
1329
    /**
1330
     * Lookup access policy from Metacat
1331
     * @param guid
1332
     * @return
1333
     * @throws McdbDocNotFoundException
1334
     * @throws AccessException
1335
     */
1336
    private AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1337
        AccessPolicy accessPolicy = new AccessPolicy();
1338

    
1339
    	// use GUID to look up the access
1340
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1341
    	List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1342
        for (XMLAccessDAO accessDAO: accessDAOs) {
1343
        	AccessRule accessRule = new AccessRule();    	
1344
        	Permission permission = convertPermission(accessDAO.getPermission().intValue());
1345
        	accessRule.addPermission(permission);
1346
        	Subject subject = new Subject();
1347
        	subject.setValue(accessDAO.getPrincipalName());
1348
        	accessRule.addSubject(subject);
1349
            accessPolicy.addAllow(accessRule);
1350
        }
1351
        return accessPolicy;
1352
    }
1353
    
1354
    public int convertPermission(Permission permission) {
1355
    	if (permission.equals(Permission.READ)) {
1356
    		return AccessControlInterface.READ;
1357
    	}
1358
    	if (permission.equals(Permission.WRITE)) {
1359
    		return AccessControlInterface.WRITE;
1360
    	}
1361
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1362
    		return AccessControlInterface.CHMOD;
1363
    	}
1364
		return -1;
1365
    }
1366
    
1367
    public Permission convertPermission(int permission) {
1368
    	if (permission == AccessControlInterface.READ) {
1369
    		return Permission.READ;
1370
    	}
1371
    	if (permission == AccessControlInterface.WRITE) {
1372
    		return Permission.WRITE;
1373
    	}
1374
    	if (permission == AccessControlInterface.CHMOD) {
1375
    		return Permission.CHANGE_PERMISSION;
1376
    	}
1377
		return null;
1378
    }
1379
    
1380
    /**
1381
     * Lookup a localId given the GUID. If
1382
     * the identifier is not found, throw an exception.
1383
     * 
1384
     * @param guid the global identifier to look up
1385
     * @return String containing the corresponding LocalId
1386
     * @throws McdbDocNotFoundException if the identifier is not found
1387
     */
1388
    public String getLocalId(String guid) throws McdbDocNotFoundException {
1389
      
1390
      String db_guid = "";
1391
      String docid = "";
1392
      int rev = 0;
1393
      
1394
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1395
      
1396
      DBConnection dbConn = null;
1397
      int serialNumber = -1;
1398
      try {
1399
          // Get a database connection from the pool
1400
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1401
          serialNumber = dbConn.getCheckOutSerialNumber();
1402
          
1403
          // Execute the insert statement
1404
          PreparedStatement stmt = dbConn.prepareStatement(query);
1405
          stmt.setString(1, guid);
1406
          ResultSet rs = stmt.executeQuery();
1407
          if (rs.next()) {
1408
              db_guid = rs.getString(1);
1409
              docid = rs.getString(2);
1410
              rev = rs.getInt(3);
1411
              assert(db_guid.equals(guid));
1412
          } else {
1413
              throw new McdbDocNotFoundException("Document not found:" + guid);
1414
          }
1415
          stmt.close();
1416
      } catch (SQLException e) {
1417
          logMetacat.error("Error while looking up the local identifier: " 
1418
                  + e.getMessage());
1419
      } finally {
1420
          // Return database connection to the pool
1421
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1422
      }
1423
      return docid + "." + rev;
1424
    }
1425
    
1426
    /**
1427
     * query the systemmetadata table based on the given parameters
1428
     * @param startTime
1429
     * @param endTime
1430
     * @param objectFormat
1431
     * @param replicaStatus
1432
     * @param start
1433
     * @param count
1434
     * @return ObjectList
1435
     * @throws SQLException 
1436
     * @throws ServiceException 
1437
     * @throws PropertyNotFoundException 
1438
     */
1439
    public ObjectList querySystemMetadata(Date startTime, Date endTime, 
1440
            ObjectFormatIdentifier objectFormatId, boolean replicaStatus, int start, int count) throws SQLException, PropertyNotFoundException, ServiceException
1441
    {
1442
        ObjectList ol = new ObjectList();
1443
        int total = 0;
1444
        DBConnection dbConn = null;
1445
        int serialNumber = -1;
1446
        
1447
        try {
1448
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
1449
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
1450
                "date_modified, submitter, object_format, size from systemmetadata";
1451
            
1452
            boolean f1 = false;
1453
            boolean f2 = false;
1454
            boolean f3 = false;
1455
            
1456
            if (startTime != null) {
1457
                sql += " where systemmetadata.date_modified > ?";
1458
                f1 = true;
1459
            }
1460
            
1461
            if (endTime != null) {
1462
                if (!f1) {
1463
                    sql += " where systemmetadata.date_modified < ?";
1464
                }
1465
                else {
1466
                    sql += " and systemmetadata.date_modified < ?";
1467
                }
1468
                f2 = true;
1469
            }
1470
            
1471
            if (objectFormatId != null) {
1472
                if (!f1 && !f2) {
1473
                    sql += " where object_format = ?";
1474
                }
1475
                else {
1476
                    sql += " and object_format = ?";
1477
                }
1478
                f3 = true;
1479
            }
1480
            
1481
            if (replicaStatus) {
1482
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
1483
                if (!f1 && !f2 && !f3) {
1484
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
1485
                }
1486
                else {
1487
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
1488
                }
1489
            }
1490
            
1491
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1492
            serialNumber = dbConn.getCheckOutSerialNumber();
1493
            PreparedStatement stmt = dbConn.prepareStatement(sql);
1494
            
1495
            if (f1 && f2 && f3) {
1496
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1497
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1498
                stmt.setString(3, objectFormatId.getValue());
1499
            }
1500
            else if (f1 && f2 && !f3) {
1501
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1502
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1503
            }
1504
            else if (f1 && !f2 && f3) {
1505
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1506
                stmt.setString(2, objectFormatId.getValue());
1507
            }
1508
            else if (f1 && !f2 && !f3) {
1509
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1510
            }
1511
            else if (!f1 && f2 && f3) {
1512
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1513
                stmt.setString(2, objectFormatId.getValue());
1514
            }
1515
            else if (!f1 && !f2 && f3) {
1516
                stmt.setString(1, objectFormatId.getValue());
1517
            }
1518
            else if (!f1 && f2 && !f3) {
1519
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1520
            }
1521
            
1522
            //logMetacat.debug("LISTOBJECTS QUERY: " + stmt.toString());
1523
            
1524
            ResultSet rs = stmt.executeQuery();
1525
            for (int i=0; i<start; i++) {
1526
                if (rs.next()) {
1527
                    total++;
1528
                } else {
1529
                    break;
1530
                }
1531
            }
1532
            
1533
            int countIndex = 0;
1534
                        
1535
            while (rs.next()) {
1536
                total++;
1537
                if (countIndex >= count) {
1538
                	// allow unlimited (negative number for count)
1539
                	if (count > 0) {
1540
                		break;
1541
                	}
1542
                }
1543
                                
1544
                String guid = rs.getString(1);
1545
                //logMetacat.debug("query found doc with guid " + guid);
1546
                //Timestamp dateUploaded = rs.getTimestamp(2);
1547
                //String rightsHolder = rs.getString(3);
1548
                String checksum = rs.getString(4);
1549
                String checksumAlgorithm = rs.getString(5);
1550
                //String originMemberNode = rs.getString(6);
1551
                //String authoritiveMemberNode = rs.getString(7);
1552
                Timestamp dateModified = rs.getTimestamp(8);
1553
                //String submitter = rs.getString(9);
1554
                String fmtidStr = rs.getString(10);
1555
                String sz = rs.getString(11);
1556
                BigInteger size = new BigInteger("0");
1557
                
1558
                if (sz != null && !sz.trim().equals("")) {
1559
                    size = new BigInteger(rs.getString(11));
1560
                }
1561
                
1562
                ObjectInfo oi = new ObjectInfo();
1563
                
1564
                Identifier id = new Identifier();
1565
                id.setValue(guid);
1566
                oi.setIdentifier(id);
1567
                
1568
                if (dateModified != null) {
1569
                	oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
1570
                }
1571
                
1572
                Checksum cs = new Checksum();
1573
                cs.setValue(checksum);
1574
                try {
1575
                	//cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1576
                    cs.setAlgorithm(checksumAlgorithm);
1577
                } catch (Exception e) {
1578
					logMetacat.error("could not parse checksum algorithm", e);
1579
					continue;
1580
				}
1581
                oi.setChecksum(cs);
1582
                
1583
                // set the format type
1584
                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
1585
            	fmtid.setValue(fmtidStr);
1586
                oi.setFmtid(fmtid);
1587
                
1588
//                try {
1589
//	                oi.setFmtid(ObjectFormatCache.getInstance().getFormat(fmtidStr).getFmtid());
1590
//                } catch (NotFound e) {
1591
//                	logMetacat.error("could not find object format: " + fmtidStr, e);
1592
//                	// skip this one
1593
//                	continue;
1594
//				}
1595
                                
1596
                oi.setSize(size);
1597
                
1598
                ol.addObjectInfo(oi);
1599
                countIndex++;
1600
            }
1601
            
1602
            // expend the resultset to get the total count of possible rows
1603
            while (rs.next()) { 
1604
                total++;
1605
            }
1606
        }
1607
        
1608
        finally {
1609
            // Return database connection to the pool
1610
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1611
        }
1612
        
1613
        ol.setStart(start);
1614
        ol.setCount(ol.sizeObjectInfoList());
1615
        ol.setTotal(total);
1616
        
1617
        return ol;
1618
    }
1619
    
1620
    /**
1621
     * create a mapping in the identifier table
1622
     * @param guid
1623
     * @param localId
1624
     */
1625
    public void createMapping(String guid, String localId)
1626
    {        
1627
        
1628
        int serialNumber = -1;
1629
        DBConnection dbConn = null;
1630
        try {
1631

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

    
1640
            // Get a database connection from the pool
1641
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1642
            serialNumber = dbConn.getCheckOutSerialNumber();
1643

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

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

    
1683
            // Get a database connection from the pool
1684
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1685
            serialNumber = dbConn.getCheckOutSerialNumber();
1686

    
1687
            // Execute the insert statement
1688
            String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1689
            PreparedStatement stmt = dbConn.prepareStatement(query);
1690
            stmt.setString(1, guid);
1691
            logMetacat.debug("system metadata query: " + stmt.toString());
1692
            int rows = stmt.executeUpdate();
1693

    
1694
            stmt.close();
1695
        } catch (Exception e) {
1696
            e.printStackTrace();
1697
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1698
        } finally {
1699
            // Return database connection to the pool
1700
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1701
        }
1702
    }
1703
    
1704
    private void deleteSystemMetadata(String guid)
1705
    {        
1706
        
1707
        int serialNumber = -1;
1708
        DBConnection dbConn = null;
1709
        try {
1710

    
1711
            // Get a database connection from the pool
1712
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1713
            serialNumber = dbConn.getCheckOutSerialNumber();
1714

    
1715
            // Execute the statement
1716
            String query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
1717
            PreparedStatement stmt = dbConn.prepareStatement(query);
1718
            stmt.setString(1, guid);
1719
            logMetacat.debug("delete system metadata: " + stmt.toString());
1720
            int rows = stmt.executeUpdate();
1721

    
1722
            stmt.close();
1723
        } catch (Exception e) {
1724
            e.printStackTrace();
1725
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1726
        } finally {
1727
            // Return database connection to the pool
1728
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1729
        }
1730
    }
1731
}
1732

    
(37-37/65)