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.convert(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
    
775
    /**
776
     * Determine if an identifier exists already, returning true if so.
777
     * 
778
     * @param guid the global identifier to look up
779
     * @return boolean true if the identifier exists
780
     */
781
    public boolean identifierExists(String guid)
782
    {
783
        boolean idExists = false;
784
        try {
785
            String id = getLocalId(guid);
786
            if (id != null) {
787
                idExists = true;
788
            }
789
        } catch (McdbDocNotFoundException e) {
790
        	// try system metadata only
791
        	try {
792
        		idExists = systemMetadataExists(guid);
793
            } catch (McdbDocNotFoundException e2) {
794
            	idExists = false;
795
            }
796
        }
797
        return idExists;
798
    }
799
    
800
    /**
801
     * 
802
     * @param guid
803
     * @param rev
804
     * @return
805
     */
806
    public String generateLocalId(String guid, int rev)
807
    {
808
        return generateLocalId(guid, rev, false);
809
    }
810

    
811
    /**
812
     * Given a global identifier (guid), create a suitable local identifier that
813
     * follows Metacat's docid semantics and format (scope.id.rev), and create
814
     * a mapping between these two identifiers.  This effectively reserves both
815
     * the global and the local identifier, as they will now be present in the
816
     * identifier mapping table.  If the incoming guid has the syntax of a
817
     * Metacat docid (scope.id.rev), then simply use it.
818
     * 
819
     * @param guid the global string identifier
820
     * @param rev the revision number to be used in the localId
821
     * @return String containing the localId to be used for Metacat operations
822
     */
823
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata) 
824
    {
825
        String localId = "";
826
        boolean conformsToDocidFormat = false;
827
        
828
        // Check if the guid passed in is already in docid (scope.id.rev) format
829
        try {
830
            AccessionNumber acc = new AccessionNumber(guid, "NONE");
831
            if (new Integer(acc.getRev()).intValue() > 0) {
832
                conformsToDocidFormat = true;
833
            }
834
        } catch (NumberFormatException e) {
835
            // No action needed, simply detecting invalid AccessionNumbers
836
        } catch (AccessionNumberException e) {
837
            // No action needed, simply detecting invalid AccessionNumbers
838
        } catch (SQLException e) {
839
            // No action needed, simply detecting invalid AccessionNumbers
840
        }
841
        
842
        if (conformsToDocidFormat) {
843
            // if it conforms, use it for both guid and localId
844
            localId = guid;
845
        } else {
846
            // if not, then generate a new unique localId
847
            localId = DocumentUtil.generateDocumentId(rev);
848
        }
849
        
850
        // Register this new pair in the identifier mapping table
851
        logMetacat.debug("creating mapping in generateLocalId");
852
        if(!isSystemMetadata)
853
        { //don't do this if we're generating for system metadata
854
            createMapping(guid, localId);
855
        }
856
        
857
        return localId;
858
    }
859
    
860
    /**
861
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
862
     * if the docid, rev is not found in the identifiers or systemmetadata tables
863
     *
864
     * @param docid the docid to look up
865
     * @param rev the revision of the docid to look up
866
     * @return String containing the mapped guid
867
     * @throws McdbDocNotFoundException if the docid, rev is not found
868
     */
869
    public String getGUID(String docid, int rev)
870
      throws McdbDocNotFoundException
871
    {
872
        logMetacat.debug("getting guid for " + docid);
873
        String query = "select guid from identifier where docid = ? and rev = ?";
874
        String guid = null;
875
        
876
        DBConnection dbConn = null;
877
        int serialNumber = -1;
878
        try {
879
            // Get a database connection from the pool
880
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
881
            serialNumber = dbConn.getCheckOutSerialNumber();
882
            
883
            // Execute the insert statement
884
            PreparedStatement stmt = dbConn.prepareStatement(query);
885
            stmt.setString(1, docid);
886
            stmt.setInt(2, rev);
887
            ResultSet rs = stmt.executeQuery();
888
            if (rs.next()) 
889
            {
890
                guid = rs.getString(1);
891
            } 
892
            else
893
            {
894
            	throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
895
            }
896
            
897
        } catch (SQLException e) {
898
            logMetacat.error("Error while looking up the guid: " 
899
                    + e.getMessage());
900
        } finally {
901
            // Return database connection to the pool
902
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
903
        }
904
        
905
        return guid;
906
    }
907
    
908
    public boolean systemMetadataExists(String guid)
909
			throws McdbDocNotFoundException {
910
		logMetacat.debug("looking up system metadata for guid " + guid);
911
		boolean exists = false;
912
		String query = "select guid from systemmetadata where guid = ?";
913

    
914
		DBConnection dbConn = null;
915
		int serialNumber = -1;
916
		try {
917
			// Get a database connection from the pool
918
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
919
			serialNumber = dbConn.getCheckOutSerialNumber();
920

    
921
			// Execute the insert statement
922
			PreparedStatement stmt = dbConn.prepareStatement(query);
923
			stmt.setString(1, guid);
924
			ResultSet rs = stmt.executeQuery();
925
			if (rs.next()) {
926
				exists = true;
927
			} else {
928
				throw new McdbDocNotFoundException(
929
						"No system metadata registered for guid " + guid);
930
			}
931

    
932
		} catch (SQLException e) {
933
			logMetacat.error("Error while looking up the system metadata: "
934
					+ e.getMessage());
935
		} finally {
936
			// Return database connection to the pool
937
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
938
		}
939

    
940
		return exists;
941
	}
942
    
943
    /**
944
     * creates a system metadata mapping and adds additional fields from sysmeta
945
     * to the table for quick searching.
946
     * 
947
     * @param guid the id to insert
948
     * @param localId the systemMetadata object to get the local id for
949
     * @throws McdbDocNotFoundException 
950
     */
951
    public void createSystemMetadata(SystemMetadata sysmeta) throws McdbDocNotFoundException
952
    {
953
    	String guid = sysmeta.getIdentifier().getValue();
954
    	// insert the record
955
        insertSystemMetadata(guid);
956
        // update with the values
957
        updateSystemMetadata(sysmeta);
958
    }
959
        
960
    
961
    /**
962
     * update a mapping
963
     * @param guid
964
     * @param localId
965
     */
966
    public void updateMapping(String guid, String localId)
967
    {
968
    	
969
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
970
        int serialNumber = -1;
971
        DBConnection dbConn = null;
972
        try {
973
            // Parse the localId into scope and rev parts
974
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
975
            String docid = acc.getDocid();
976
            int rev = 1;
977
            if(acc.getRev() != null)
978
            {
979
              rev = (new Integer(acc.getRev()).intValue());
980
            }
981

    
982
            // Get a database connection from the pool
983
            dbConn = 
984
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
985
            serialNumber = dbConn.getCheckOutSerialNumber();
986

    
987
            // Execute the update statement
988
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid='" + guid + "'";
989
            PreparedStatement stmt = dbConn.prepareStatement(query);
990
            stmt.setString(1, docid);
991
            stmt.setInt(2, rev);
992
            int rows = stmt.executeUpdate();
993

    
994
            stmt.close();
995
        } catch (SQLException e) {
996
            e.printStackTrace();
997
            logMetacat.error("SQL error while updating a mapping identifier: " 
998
                    + e.getMessage());
999
        } catch (NumberFormatException e) {
1000
            e.printStackTrace();
1001
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
1002
                    + e.getMessage());
1003
        } catch (AccessionNumberException e) {
1004
            e.printStackTrace();
1005
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
1006
                    + e.getMessage());
1007
        } finally {
1008
            // Return database connection to the pool
1009
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1010
        }
1011
        logMetacat.debug("done updating mapping");
1012
    }
1013
        
1014
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1015
            String checksum, String checksumAlgorithm, String originMemberNode,
1016
            String authoritativeMemberNode, long modifiedDate, String submitter, 
1017
            String guid, String objectFormat, BigInteger size, boolean replicationAllowed,
1018
            int numberReplicas, String obsoletes, String obsoletedBy)
1019
    {
1020
        DBConnection dbConn = null;
1021
        int serialNumber = -1;
1022
        
1023
        try {
1024
            // Get a database connection from the pool
1025
            dbConn = 
1026
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1027
            serialNumber = dbConn.getCheckOutSerialNumber();
1028

    
1029
            // Execute the insert statement
1030
            String query = "update " + TYPE_SYSTEM_METADATA + 
1031
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1032
                "origin_member_node, authoritive_member_node, date_modified, " +
1033
                "submitter, object_format, size, replication_allowed, number_replicas, obsoletes, obsoleted_by) " +
1034
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1035
            PreparedStatement stmt = dbConn.prepareStatement(query);
1036
            
1037
            //data values
1038
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1039
            stmt.setString(2, rightsHolder);
1040
            stmt.setString(3, checksum);
1041
            stmt.setString(4, checksumAlgorithm);
1042
            stmt.setString(5, originMemberNode);
1043
            stmt.setString(6, authoritativeMemberNode);
1044
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1045
            stmt.setString(8, submitter);
1046
            stmt.setString(9, objectFormat);
1047
            stmt.setString(10, size.toString());
1048
            stmt.setBoolean(11, replicationAllowed);
1049
            stmt.setInt(12, numberReplicas);
1050
            stmt.setString(13, obsoletes);
1051
            stmt.setString(14, obsoletedBy);
1052

    
1053
            //where clause
1054
            stmt.setString(15, guid);
1055
            logMetacat.debug("stmt: " + stmt.toString());
1056
            //execute
1057
            int rows = stmt.executeUpdate();
1058

    
1059
            stmt.close();
1060
        } catch (SQLException e) {
1061
            e.printStackTrace();
1062
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: " 
1063
                    + e.getMessage());
1064
        } catch (NumberFormatException e) {
1065
            e.printStackTrace();
1066
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: " 
1067
                    + e.getMessage());
1068
        } finally {
1069
            // Return database connection to the pool
1070
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1071
        }
1072
    }
1073
    
1074
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes)
1075
    {
1076
        DBConnection dbConn = null;
1077
        int serialNumber = -1;
1078
        
1079
        try {
1080
            // Get a database connection from the pool
1081
            dbConn = 
1082
                DBConnectionPool.getDBConnection("IdentifierManager.insertReplicationPolicy");
1083
            serialNumber = dbConn.getCheckOutSerialNumber();
1084

    
1085
            // remove existing values first
1086
            String delete = "delete from systemMetadataReplicationPolicy " + 
1087
            "where guid = ? and policy = ?";
1088
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1089
	        //data values
1090
	        stmt.setString(1, guid);
1091
	        stmt.setString(2, policy);
1092
	        //execute
1093
	        int deletedCount = stmt.executeUpdate();
1094
	        stmt.close();
1095
            
1096
            for (String memberNode: memberNodes) {
1097
	            // Execute the insert statement
1098
	            String insert = "insert into systemMetadataReplicationPolicy " + 
1099
	                "(guid, policy, member_node) " +
1100
	                "values (?, ?, ?)";
1101
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1102
	            
1103
	            //data values
1104
	            insertStatement.setString(1, guid);
1105
	            insertStatement.setString(2, policy);
1106
	            insertStatement.setString(3, memberNode);
1107
	            //execute
1108
	            int rows = insertStatement.executeUpdate();
1109
	            insertStatement.close();
1110
            }
1111
        } catch (SQLException e) {
1112
            logMetacat.error("SQL error while adding systemMetadataReplicationPolicy for: " + guid, e); 
1113
        } finally {
1114
            // Return database connection to the pool
1115
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1116
        }
1117
    }
1118
    
1119
    private void insertReplicationStatus(String guid, List<Replica> replicas) {
1120
        DBConnection dbConn = null;
1121
        int serialNumber = -1;
1122
        
1123
        try {
1124
            // Get a database connection from the pool
1125
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertReplicas");
1126
            serialNumber = dbConn.getCheckOutSerialNumber();
1127

    
1128
            // remove existing values first
1129
            String delete = "delete from systemMetadataReplicationStatus " + 
1130
            "where guid = ?";
1131
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1132
	        //data values
1133
	        stmt.setString(1, guid);
1134
	        //execute
1135
	        int deletedCount = stmt.executeUpdate();
1136
	        stmt.close();
1137
            
1138
	        if (replicas != null) {
1139
	            for (Replica replica: replicas) {
1140
		            // Execute the insert statement
1141
		            String insert = "insert into systemMetadataReplicationStatus " + 
1142
		                "(guid, member_node, status, date_verified) " +
1143
		                "values (?, ?, ?, ?)";
1144
		            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1145
		            
1146
		            //data values
1147
		            String memberNode = replica.getReplicaMemberNode().getValue();
1148
		            String status = replica.getReplicationStatus().toString();
1149
		            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1150
		            insertStatement.setString(1, guid);
1151
		            insertStatement.setString(2, memberNode);
1152
		            insertStatement.setString(3, status);
1153
		            insertStatement.setDate(4, sqlDate);
1154
	
1155
		            //execute
1156
		            int rows = insertStatement.executeUpdate();
1157
		            insertStatement.close();
1158
	            }
1159
	        }
1160
        } catch (SQLException e) {
1161
            logMetacat.error("SQL error while adding systemMetadataReplicationStatus for: " + guid, e); 
1162
        } finally {
1163
            // Return database connection to the pool
1164
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1165
        }
1166
    }
1167
    
1168
    /**
1169
     * Insert the system metadata fields into the db
1170
     * @param sm
1171
     * @throws McdbDocNotFoundException 
1172
     */
1173
    public void updateSystemMetadata(SystemMetadata sm) throws McdbDocNotFoundException {
1174
    	
1175
        Boolean replicationAllowed = false;
1176
		Integer numberReplicas = -1;
1177
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1178
    	if (replicationPolicy != null) {
1179
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1180
    		numberReplicas = replicationPolicy.getNumberReplicas();
1181
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1182
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1183
    	}
1184

    
1185
    	// the main systemMetadata fields
1186
		updateSystemMetadataFields(
1187
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1188
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(), 
1189
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(), 
1190
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm(), 
1191
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1192
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(), 
1193
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1194
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(), 
1195
        sm.getIdentifier().getValue(),
1196
        sm.getFmtid() == null ? null: sm.getFmtid().getValue(),
1197
        sm.getSize(),
1198
        replicationAllowed, 
1199
        numberReplicas,
1200
        sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
1201
        sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue());
1202
        
1203
        String guid = sm.getIdentifier().getValue();
1204
        
1205
        // save replication policies
1206
        if (replicationPolicy != null) {
1207
		    List<String> nodes = null;
1208
		    String policy = null;
1209
		    
1210
		    nodes = new ArrayList<String>();
1211
		    policy = "blocked";
1212
		    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1213
		    	nodes.add(node.getValue());
1214
		    }
1215
		    this.insertReplicationPolicy(guid, policy, nodes);
1216
		    
1217
		    nodes = new ArrayList<String>();
1218
		    policy = "preferred";
1219
		    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1220
		    	nodes.add(node.getValue());
1221
		    }
1222
	        this.insertReplicationPolicy(guid, policy, nodes);
1223
        }
1224
        
1225
        // save replica information
1226
        this.insertReplicationStatus(guid, sm.getReplicaList());
1227
        
1228
        // save access policy
1229
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1230
        if (accessPolicy != null) {
1231
        	try {
1232
				this.insertAccessPolicy(guid, accessPolicy);
1233
			} catch (AccessException e) {
1234
				throw new McdbDocNotFoundException(e);
1235
			}
1236
        }
1237
    }
1238
    
1239
    /**
1240
     * Creates Metacat access rules and inserts them
1241
     * @param accessPolicy
1242
     * @throws McdbDocNotFoundException
1243
     * @throws AccessException
1244
     */
1245
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1246
    	
1247
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1248
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1249
        	List<Subject> subjects = accessRule.getSubjectList();
1250
        	List<Permission> permissions = accessRule.getPermissionList();
1251
        	for (Subject subject: subjects) {
1252
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1253
        		accessDAO.setPrincipalName(subject.getValue());
1254
    			accessDAO.setGuid(guid);
1255
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1256
    			accessDAO.setPermOrder(AccessControlInterface.DENYFIRST);
1257
    			for (Permission permission: permissions) {
1258
    				Long metacatPermission = new Long(convertPermission(permission));
1259
        			accessDAO.addPermission(metacatPermission);
1260
    			}
1261
    			accessDAOs.add(accessDAO);
1262
        	}
1263
        }
1264
        
1265
        // use GUID to update
1266
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1267
        accessController.replaceAccess(guid, accessDAOs);
1268
        
1269
        
1270
    }
1271
    
1272
    /**
1273
     * Lookup access policy from Metacat
1274
     * @param guid
1275
     * @return
1276
     * @throws McdbDocNotFoundException
1277
     * @throws AccessException
1278
     */
1279
    private AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1280
        AccessPolicy accessPolicy = new AccessPolicy();
1281

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

    
1530
				}
1531
                                
1532
                oi.setSize(size);
1533
                
1534
                ol.addObjectInfo(oi);
1535
                countIndex++;
1536
            }
1537
            
1538
            // expend the resultset to get the total count of possible rows
1539
            while (rs.next()) { 
1540
                total++;
1541
            }
1542
        }
1543
        
1544
        finally {
1545
            // Return database connection to the pool
1546
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1547
        }
1548
        
1549
        ol.setStart(start);
1550
        ol.setCount(ol.sizeObjectInfoList());
1551
        ol.setTotal(total);
1552
        
1553
        return ol;
1554
    }
1555
    
1556
    /**
1557
     * create a mapping in the identifier table
1558
     * @param guid
1559
     * @param localId
1560
     */
1561
    public void createMapping(String guid, String localId)
1562
    {        
1563
        
1564
        int serialNumber = -1;
1565
        DBConnection dbConn = null;
1566
        try {
1567

    
1568
            // Parse the localId into scope and rev parts
1569
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1570
            String docid = acc.getDocid();
1571
            int rev = 1;
1572
            if (acc.getRev() != null) {
1573
              rev = (new Integer(acc.getRev()).intValue());
1574
            }
1575

    
1576
            // Get a database connection from the pool
1577
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1578
            serialNumber = dbConn.getCheckOutSerialNumber();
1579

    
1580
            // Execute the insert statement
1581
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1582
            PreparedStatement stmt = dbConn.prepareStatement(query);
1583
            stmt.setString(1, guid);
1584
            stmt.setString(2, docid);
1585
            stmt.setInt(3, rev);
1586
            logMetacat.debug("mapping query: " + stmt.toString());
1587
            int rows = stmt.executeUpdate();
1588

    
1589
            stmt.close();
1590
        } catch (SQLException e) {
1591
            e.printStackTrace();
1592
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1593
                    + e.getMessage());
1594
        } catch (NumberFormatException e) {
1595
            e.printStackTrace();
1596
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1597
                    + e.getMessage());
1598
        } catch (AccessionNumberException e) {
1599
            e.printStackTrace();
1600
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1601
                    + e.getMessage());
1602
        } finally {
1603
            // Return database connection to the pool
1604
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1605
        }
1606
    }
1607
    
1608
    /**
1609
     * create the systemmetadata record
1610
     * @param guid
1611
     */
1612
    private void insertSystemMetadata(String guid)
1613
    {        
1614
        
1615
        int serialNumber = -1;
1616
        DBConnection dbConn = null;
1617
        try {
1618

    
1619
            // Get a database connection from the pool
1620
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1621
            serialNumber = dbConn.getCheckOutSerialNumber();
1622

    
1623
            // Execute the insert statement
1624
            String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1625
            PreparedStatement stmt = dbConn.prepareStatement(query);
1626
            stmt.setString(1, guid);
1627
            logMetacat.debug("system metadata query: " + stmt.toString());
1628
            int rows = stmt.executeUpdate();
1629

    
1630
            stmt.close();
1631
        } catch (Exception e) {
1632
            e.printStackTrace();
1633
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1634
        } finally {
1635
            // Return database connection to the pool
1636
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1637
        }
1638
    }
1639
    
1640
    private void deleteSystemMetadata(String guid)
1641
    {        
1642
        
1643
        int serialNumber = -1;
1644
        DBConnection dbConn = null;
1645
        try {
1646

    
1647
            // Get a database connection from the pool
1648
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1649
            serialNumber = dbConn.getCheckOutSerialNumber();
1650

    
1651
            // Execute the statement
1652
            String query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
1653
            PreparedStatement stmt = dbConn.prepareStatement(query);
1654
            stmt.setString(1, guid);
1655
            logMetacat.debug("delete system metadata: " + stmt.toString());
1656
            int rows = stmt.executeUpdate();
1657

    
1658
            stmt.close();
1659
        } catch (Exception e) {
1660
            e.printStackTrace();
1661
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1662
        } finally {
1663
            // Return database connection to the pool
1664
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1665
        }
1666
    }
1667
}
1668

    
(37-37/65)