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
          "obsoletes, obsoleted_by " +
248
          "from systemmetadata where guid = ?";
249
        DBConnection dbConn = null;
250
        int serialNumber = -1;
251
        try 
252
        {
253
            // Get a database connection from the pool
254
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getSystemMetadata");
255
            serialNumber = dbConn.getCheckOutSerialNumber();
256

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

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

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

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

    
571
            // Execute the insert statement
572
            PreparedStatement stmt = dbConn.prepareStatement(sql);
573
            ResultSet rs = stmt.executeQuery();
574
            if (rs.next()) 
575
            {
576
                rev = rs.getInt(1);
577
                stmt.close();
578
            } 
579
            else
580
            {
581
                stmt.close();
582
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
583
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
584
            }
585
        } 
586
        catch (SQLException e) 
587
        {
588
            logMetacat.error("Error while looking up the guid: " 
589
                    + e.getMessage());
590
        } 
591
        finally 
592
        {
593
            // Return database connection to the pool
594
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
595
        }
596
        return rev;
597
    }
598
    
599
    /**
600
     * return all local ids in the object store that do not have associated
601
     * system metadata
602
     */
603
    public List<String> getLocalIdsWithNoSystemMetadata()
604
    {
605
        Vector<String> ids = new Vector<String>();
606
        String sql = "select docid, rev from xml_documents " +
607
        		"where docid not in " +
608
        		"(select docid from identifier where guid in (select guid from systemmetadata)))";
609
        DBConnection dbConn = null;
610
        int serialNumber = -1;
611
        try 
612
        {
613
            // Get a database connection from the pool
614
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
615
            serialNumber = dbConn.getCheckOutSerialNumber();
616

    
617
            // Execute the insert statement
618
            PreparedStatement stmt = dbConn.prepareStatement(sql);
619
            ResultSet rs = stmt.executeQuery();
620
            while (rs.next()) 
621
            {
622
                String localid = rs.getString(1);
623
                String rev = rs.getString(2);
624
                localid += "." + rev;
625
                logMetacat.debug("id to add SM for: " + localid);
626
                ids.add(localid);
627
            } 
628
            stmt.close();
629
        } 
630
        catch (SQLException e) 
631
        {
632
            logMetacat.error("Error while looking up the guid: " 
633
                    + e.getMessage());
634
        } 
635
        finally 
636
        {
637
            // Return database connection to the pool
638
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
639
        }
640
        
641
        return ids;
642
    }
643
    
644
    /**
645
     * return a listing of all local ids in the object store
646
     * @return a list of all local ids in metacat
647
     */
648
    public List<String> getAllLocalIds()
649
    // seems to be an unnecessary and restrictive throw -rnahf 13-Sep-2011
650
    //    throws Exception
651
    {
652
        Vector<String> ids = new Vector<String>();
653
        String sql = "select docid from xml_documents";
654
        DBConnection dbConn = null;
655
        int serialNumber = -1;
656
        try 
657
        {
658
            // Get a database connection from the pool
659
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
660
            serialNumber = dbConn.getCheckOutSerialNumber();
661

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

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

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

    
781
        List<String> ids = new Vector<String>();
782
        String sql = 
783
        	"select max(date_modified) from " + TYPE_SYSTEM_METADATA;
784
        DBConnection dbConn = null;
785
        int serialNumber = -1;
786
        try 
787
        {
788
            // Get a database connection from the pool
789
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLastModifiedDate");
790
            serialNumber = dbConn.getCheckOutSerialNumber();
791

    
792
            // Execute the insert statement
793
            PreparedStatement stmt = dbConn.prepareStatement(sql);
794
            ResultSet rs = stmt.executeQuery();
795
            if (rs.next()) {
796
            	maxDate = rs.getDate(1);
797
            } 
798
            stmt.close();
799
        } 
800
        catch (SQLException e) 
801
        {
802
            logMetacat.error("Error while looking up the latest update date: " 
803
                    + e.getMessage());
804
        } 
805
        finally 
806
        {
807
            // Return database connection to the pool
808
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
809
        }
810
        return maxDate;
811
    }
812

    
813
    
814
    /**
815
     * Determine if an identifier exists already, returning true if so.
816
     * 
817
     * @param guid the global identifier to look up
818
     * @return boolean true if the identifier exists
819
     */
820
    public boolean identifierExists(String guid)
821
    {
822
        boolean idExists = false;
823
        try {
824
            String id = getLocalId(guid);
825
            if (id != null) {
826
                idExists = true;
827
            }
828
        } catch (McdbDocNotFoundException e) {
829
        	// try system metadata only
830
        	try {
831
        		idExists = systemMetadataExists(guid);
832
            } catch (Exception e2) {
833
            	idExists = false;
834
            }
835
        }
836
        return idExists;
837
    }
838
    
839
    /**
840
     * 
841
     * @param guid
842
     * @param rev
843
     * @return
844
     */
845
    public String generateLocalId(String guid, int rev)
846
    {
847
        return generateLocalId(guid, rev, false);
848
    }
849

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

    
952
		DBConnection dbConn = null;
953
		int serialNumber = -1;
954
		try {
955
			// Get a database connection from the pool
956
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
957
			serialNumber = dbConn.getCheckOutSerialNumber();
958

    
959
			// Execute the insert statement
960
			PreparedStatement stmt = dbConn.prepareStatement(query);
961
			stmt.setString(1, guid);
962
			ResultSet rs = stmt.executeQuery();
963
			if (rs.next()) {
964
				exists = true;
965
			}
966

    
967
		} catch (SQLException e) {
968
			logMetacat.error("Error while looking up the system metadata: "
969
					+ e.getMessage());
970
		} finally {
971
			// Return database connection to the pool
972
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
973
		}
974

    
975
		return exists;
976
	}
977
    
978
    /**
979
     * creates a system metadata mapping and adds additional fields from sysmeta
980
     * to the table for quick searching.
981
     * 
982
     * @param guid the id to insert
983
     * @param localId the systemMetadata object to get the local id for
984
     * @throws McdbDocNotFoundException 
985
     */
986
    public void createSystemMetadata(SystemMetadata sysmeta) throws McdbDocNotFoundException
987
    {
988
    	String guid = sysmeta.getIdentifier().getValue();
989
    	// insert the record
990
        insertSystemMetadata(guid);
991
        // update with the values
992
        updateSystemMetadata(sysmeta);
993
    }
994
        
995
    
996
    /**
997
     * update a mapping
998
     * @param guid
999
     * @param localId
1000
     */
1001
    public void updateMapping(String guid, String localId)
1002
    {
1003
    	
1004
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
1005
        int serialNumber = -1;
1006
        DBConnection dbConn = null;
1007
        try {
1008
            // Parse the localId into scope and rev parts
1009
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1010
            String docid = acc.getDocid();
1011
            int rev = 1;
1012
            if(acc.getRev() != null)
1013
            {
1014
              rev = (new Integer(acc.getRev()).intValue());
1015
            }
1016

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

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

    
1029
            stmt.close();
1030
        } catch (SQLException e) {
1031
            e.printStackTrace();
1032
            logMetacat.error("SQL error while updating a mapping identifier: " 
1033
                    + e.getMessage());
1034
        } catch (NumberFormatException e) {
1035
            e.printStackTrace();
1036
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
1037
                    + e.getMessage());
1038
        } catch (AccessionNumberException e) {
1039
            e.printStackTrace();
1040
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
1041
                    + e.getMessage());
1042
        } finally {
1043
            // Return database connection to the pool
1044
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1045
        }
1046
        logMetacat.debug("done updating mapping");
1047
    }
1048
        
1049
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1050
            String checksum, String checksumAlgorithm, String originMemberNode,
1051
            String authoritativeMemberNode, long modifiedDate, String submitter, 
1052
            String guid, String objectFormat, BigInteger size, boolean replicationAllowed,
1053
            int numberReplicas, String obsoletes, String obsoletedBy)
1054
    {
1055
        DBConnection dbConn = null;
1056
        int serialNumber = -1;
1057
        
1058
        try {
1059
            // Get a database connection from the pool
1060
            dbConn = 
1061
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1062
            serialNumber = dbConn.getCheckOutSerialNumber();
1063

    
1064
            // Execute the insert statement
1065
            String query = "update " + TYPE_SYSTEM_METADATA + 
1066
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1067
                "origin_member_node, authoritive_member_node, date_modified, " +
1068
                "submitter, object_format, size, replication_allowed, number_replicas, obsoletes, obsoleted_by) " +
1069
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1070
            PreparedStatement stmt = dbConn.prepareStatement(query);
1071
            
1072
            //data values
1073
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1074
            stmt.setString(2, rightsHolder);
1075
            stmt.setString(3, checksum);
1076
            stmt.setString(4, checksumAlgorithm);
1077
            stmt.setString(5, originMemberNode);
1078
            stmt.setString(6, authoritativeMemberNode);
1079
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1080
            stmt.setString(8, submitter);
1081
            stmt.setString(9, objectFormat);
1082
            stmt.setString(10, size.toString());
1083
            stmt.setBoolean(11, replicationAllowed);
1084
            stmt.setInt(12, numberReplicas);
1085
            stmt.setString(13, obsoletes);
1086
            stmt.setString(14, obsoletedBy);
1087

    
1088
            //where clause
1089
            stmt.setString(15, guid);
1090
            logMetacat.debug("stmt: " + stmt.toString());
1091
            //execute
1092
            int rows = stmt.executeUpdate();
1093

    
1094
            stmt.close();
1095
        } catch (SQLException e) {
1096
            e.printStackTrace();
1097
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: " 
1098
                    + e.getMessage());
1099
        } catch (NumberFormatException e) {
1100
            e.printStackTrace();
1101
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: " 
1102
                    + e.getMessage());
1103
        } finally {
1104
            // Return database connection to the pool
1105
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1106
        }
1107
    }
1108
    
1109
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes)
1110
    {
1111
        DBConnection dbConn = null;
1112
        int serialNumber = -1;
1113
        
1114
        try {
1115
            // Get a database connection from the pool
1116
            dbConn = 
1117
                DBConnectionPool.getDBConnection("IdentifierManager.insertReplicationPolicy");
1118
            serialNumber = dbConn.getCheckOutSerialNumber();
1119

    
1120
            // remove existing values first
1121
            String delete = "delete from systemMetadataReplicationPolicy " + 
1122
            "where guid = ? and policy = ?";
1123
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1124
	        //data values
1125
	        stmt.setString(1, guid);
1126
	        stmt.setString(2, policy);
1127
	        //execute
1128
	        int deletedCount = stmt.executeUpdate();
1129
	        stmt.close();
1130
            
1131
            for (String memberNode: memberNodes) {
1132
	            // Execute the insert statement
1133
	            String insert = "insert into systemMetadataReplicationPolicy " + 
1134
	                "(guid, policy, member_node) " +
1135
	                "values (?, ?, ?)";
1136
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1137
	            
1138
	            //data values
1139
	            insertStatement.setString(1, guid);
1140
	            insertStatement.setString(2, policy);
1141
	            insertStatement.setString(3, memberNode);
1142
	            //execute
1143
	            int rows = insertStatement.executeUpdate();
1144
	            insertStatement.close();
1145
            }
1146
        } catch (SQLException e) {
1147
            logMetacat.error("SQL error while adding systemMetadataReplicationPolicy for: " + guid, e); 
1148
        } finally {
1149
            // Return database connection to the pool
1150
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1151
        }
1152
    }
1153
    
1154
    private void insertReplicationStatus(String guid, List<Replica> replicas) {
1155
        DBConnection dbConn = null;
1156
        int serialNumber = -1;
1157
        
1158
        try {
1159
            // Get a database connection from the pool
1160
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertReplicas");
1161
            serialNumber = dbConn.getCheckOutSerialNumber();
1162

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

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

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

    
1565
				}
1566
                                
1567
                oi.setSize(size);
1568
                
1569
                ol.addObjectInfo(oi);
1570
                countIndex++;
1571
            }
1572
            
1573
            // expend the resultset to get the total count of possible rows
1574
            while (rs.next()) { 
1575
                total++;
1576
            }
1577
        }
1578
        
1579
        finally {
1580
            // Return database connection to the pool
1581
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1582
        }
1583
        
1584
        ol.setStart(start);
1585
        ol.setCount(ol.sizeObjectInfoList());
1586
        ol.setTotal(total);
1587
        
1588
        return ol;
1589
    }
1590
    
1591
    /**
1592
     * create a mapping in the identifier table
1593
     * @param guid
1594
     * @param localId
1595
     */
1596
    public void createMapping(String guid, String localId)
1597
    {        
1598
        
1599
        int serialNumber = -1;
1600
        DBConnection dbConn = null;
1601
        try {
1602

    
1603
            // Parse the localId into scope and rev parts
1604
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1605
            String docid = acc.getDocid();
1606
            int rev = 1;
1607
            if (acc.getRev() != null) {
1608
              rev = (new Integer(acc.getRev()).intValue());
1609
            }
1610

    
1611
            // Get a database connection from the pool
1612
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1613
            serialNumber = dbConn.getCheckOutSerialNumber();
1614

    
1615
            // Execute the insert statement
1616
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1617
            PreparedStatement stmt = dbConn.prepareStatement(query);
1618
            stmt.setString(1, guid);
1619
            stmt.setString(2, docid);
1620
            stmt.setInt(3, rev);
1621
            logMetacat.debug("mapping query: " + stmt.toString());
1622
            int rows = stmt.executeUpdate();
1623

    
1624
            stmt.close();
1625
        } catch (SQLException e) {
1626
            e.printStackTrace();
1627
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1628
                    + e.getMessage());
1629
        } catch (NumberFormatException e) {
1630
            e.printStackTrace();
1631
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1632
                    + e.getMessage());
1633
        } catch (AccessionNumberException e) {
1634
            e.printStackTrace();
1635
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1636
                    + e.getMessage());
1637
        } finally {
1638
            // Return database connection to the pool
1639
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1640
        }
1641
    }
1642
    
1643
    /**
1644
     * create the systemmetadata record
1645
     * @param guid
1646
     */
1647
    private void insertSystemMetadata(String guid)
1648
    {        
1649
        
1650
        int serialNumber = -1;
1651
        DBConnection dbConn = null;
1652
        try {
1653

    
1654
            // Get a database connection from the pool
1655
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1656
            serialNumber = dbConn.getCheckOutSerialNumber();
1657

    
1658
            // Execute the insert statement
1659
            String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1660
            PreparedStatement stmt = dbConn.prepareStatement(query);
1661
            stmt.setString(1, guid);
1662
            logMetacat.debug("system metadata query: " + stmt.toString());
1663
            int rows = stmt.executeUpdate();
1664

    
1665
            stmt.close();
1666
        } catch (Exception e) {
1667
            e.printStackTrace();
1668
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1669
        } finally {
1670
            // Return database connection to the pool
1671
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1672
        }
1673
    }
1674
    
1675
    private void deleteSystemMetadata(String guid)
1676
    {        
1677
        
1678
        int serialNumber = -1;
1679
        DBConnection dbConn = null;
1680
        try {
1681

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

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

    
1693
            stmt.close();
1694
        } catch (Exception e) {
1695
            e.printStackTrace();
1696
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1697
        } finally {
1698
            // Return database connection to the pool
1699
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1700
        }
1701
    }
1702
}
1703

    
(37-37/65)