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
            for (Replica replica: replicas) {
1139
	            // Execute the insert statement
1140
	            String insert = "insert into systemMetadataReplicationStatus " + 
1141
	                "(guid, member_node, status, date_verified) " +
1142
	                "values (?, ?, ?, ?)";
1143
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1144
	            
1145
	            //data values
1146
	            String memberNode = replica.getReplicaMemberNode().getValue();
1147
	            String status = replica.getReplicationStatus().toString();
1148
	            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1149
	            insertStatement.setString(1, guid);
1150
	            insertStatement.setString(2, memberNode);
1151
	            insertStatement.setString(3, status);
1152
	            insertStatement.setDate(4, sqlDate);
1153

    
1154
	            //execute
1155
	            int rows = insertStatement.executeUpdate();
1156
	            insertStatement.close();
1157
            }
1158
        } catch (SQLException e) {
1159
            logMetacat.error("SQL error while adding systemMetadataReplicationStatus for: " + guid, e); 
1160
        } finally {
1161
            // Return database connection to the pool
1162
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1163
        }
1164
    }
1165
    
1166
    /**
1167
     * Insert the system metadata fields into the db
1168
     * @param sm
1169
     * @throws McdbDocNotFoundException 
1170
     */
1171
    public void updateSystemMetadata(SystemMetadata sm) throws McdbDocNotFoundException {
1172
    	
1173
        Boolean replicationAllowed = false;
1174
		Integer numberReplicas = -1;
1175
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1176
    	if (replicationPolicy != null) {
1177
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1178
    		numberReplicas = replicationPolicy.getNumberReplicas();
1179
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1180
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1181
    	}
1182

    
1183
    	// the main systemMetadata fields
1184
		updateSystemMetadataFields(
1185
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1186
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(), 
1187
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(), 
1188
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm(), 
1189
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1190
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(), 
1191
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1192
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(), 
1193
        sm.getIdentifier().getValue(),
1194
        sm.getFmtid() == null ? null: sm.getFmtid().getValue(),
1195
        sm.getSize(),
1196
        replicationAllowed, 
1197
        numberReplicas,
1198
        sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
1199
        sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue());
1200
        
1201
        String guid = sm.getIdentifier().getValue();
1202
        
1203
        // save replication policies
1204
        if (replicationPolicy != null) {
1205
		    List<String> nodes = null;
1206
		    String policy = null;
1207
		    
1208
		    nodes = new ArrayList<String>();
1209
		    policy = "blocked";
1210
		    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1211
		    	nodes.add(node.getValue());
1212
		    }
1213
		    this.insertReplicationPolicy(guid, policy, nodes);
1214
		    
1215
		    nodes = new ArrayList<String>();
1216
		    policy = "preferred";
1217
		    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1218
		    	nodes.add(node.getValue());
1219
		    }
1220
	        this.insertReplicationPolicy(guid, policy, nodes);
1221
        }
1222
        
1223
        // save replica information
1224
        this.insertReplicationStatus(guid, sm.getReplicaList());
1225
        
1226
        // save access policy
1227
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1228
        if (accessPolicy != null) {
1229
        	try {
1230
				this.insertAccessPolicy(guid, accessPolicy);
1231
			} catch (AccessException e) {
1232
				throw new McdbDocNotFoundException(e);
1233
			}
1234
        }
1235
    }
1236
    
1237
    /**
1238
     * Creates Metacat access rules and inserts them
1239
     * @param accessPolicy
1240
     * @throws McdbDocNotFoundException
1241
     * @throws AccessException
1242
     */
1243
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1244
    	
1245
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1246
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1247
        	List<Subject> subjects = accessRule.getSubjectList();
1248
        	List<Permission> permissions = accessRule.getPermissionList();
1249
        	for (Subject subject: subjects) {
1250
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1251
        		accessDAO.setPrincipalName(subject.getValue());
1252
    			accessDAO.setGuid(guid);
1253
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1254
    			accessDAO.setPermOrder(AccessControlInterface.DENYFIRST);
1255
    			for (Permission permission: permissions) {
1256
    				Long metacatPermission = new Long(convertPermission(permission));
1257
        			accessDAO.addPermission(metacatPermission);
1258
    			}
1259
    			accessDAOs.add(accessDAO);
1260
        	}
1261
        }
1262
        
1263
        // use GUID to update
1264
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1265
        accessController.replaceAccess(guid, accessDAOs);
1266
        
1267
        
1268
    }
1269
    
1270
    /**
1271
     * Lookup access policy from Metacat
1272
     * @param guid
1273
     * @return
1274
     * @throws McdbDocNotFoundException
1275
     * @throws AccessException
1276
     */
1277
    private AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1278
    	// use GUID to look up the access
1279
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1280
    	List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1281
    	AccessRule accessRule = new AccessRule();    	
1282
        for (XMLAccessDAO accessDAO: accessDAOs) {
1283
        	Permission permission = convertPermission(accessDAO.getPermission().intValue());
1284
        	accessRule.addPermission(permission);
1285
        	Subject subject = new Subject();
1286
        	subject.setValue(accessDAO.getPrincipalName());
1287
        	accessRule.addSubject(subject);
1288
        }
1289
        AccessPolicy accessPolicy = new AccessPolicy();
1290
        accessPolicy.addAllow(accessRule);
1291
        return accessPolicy;
1292
    }
1293
    
1294
    public int convertPermission(Permission permission) {
1295
    	if (permission.equals(Permission.READ)) {
1296
    		return AccessControlInterface.READ;
1297
    	}
1298
    	if (permission.equals(Permission.WRITE)) {
1299
    		return AccessControlInterface.WRITE;
1300
    	}
1301
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1302
    		return AccessControlInterface.CHMOD;
1303
    	}
1304
		return -1;
1305
    }
1306
    
1307
    public Permission convertPermission(int permission) {
1308
    	if (permission == AccessControlInterface.READ) {
1309
    		return Permission.READ;
1310
    	}
1311
    	if (permission == AccessControlInterface.WRITE) {
1312
    		return Permission.WRITE;
1313
    	}
1314
    	if (permission == AccessControlInterface.CHMOD) {
1315
    		return Permission.CHANGE_PERMISSION;
1316
    	}
1317
		return null;
1318
    }
1319
    
1320
    /**
1321
     * Lookup a localId given the GUID. If
1322
     * the identifier is not found, throw an exception.
1323
     * 
1324
     * @param guid the global identifier to look up
1325
     * @return String containing the corresponding LocalId
1326
     * @throws McdbDocNotFoundException if the identifier is not found
1327
     */
1328
    public String getLocalId(String guid) throws McdbDocNotFoundException {
1329
      
1330
      String db_guid = "";
1331
      String docid = "";
1332
      int rev = 0;
1333
      
1334
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1335
      
1336
      DBConnection dbConn = null;
1337
      int serialNumber = -1;
1338
      try {
1339
          // Get a database connection from the pool
1340
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1341
          serialNumber = dbConn.getCheckOutSerialNumber();
1342
          
1343
          // Execute the insert statement
1344
          PreparedStatement stmt = dbConn.prepareStatement(query);
1345
          stmt.setString(1, guid);
1346
          ResultSet rs = stmt.executeQuery();
1347
          if (rs.next()) {
1348
              db_guid = rs.getString(1);
1349
              docid = rs.getString(2);
1350
              rev = rs.getInt(3);
1351
              assert(db_guid.equals(guid));
1352
          } else {
1353
              throw new McdbDocNotFoundException("Document not found:" + guid);
1354
          }
1355
          stmt.close();
1356
      } catch (SQLException e) {
1357
          logMetacat.error("Error while looking up the local identifier: " 
1358
                  + e.getMessage());
1359
      } finally {
1360
          // Return database connection to the pool
1361
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1362
      }
1363
      return docid + "." + rev;
1364
    }
1365
    
1366
    /**
1367
     * query the systemmetadata table based on the given parameters
1368
     * @param startTime
1369
     * @param endTime
1370
     * @param objectFormat
1371
     * @param replicaStatus
1372
     * @param start
1373
     * @param count
1374
     * @return ObjectList
1375
     * @throws SQLException 
1376
     * @throws ServiceException 
1377
     * @throws PropertyNotFoundException 
1378
     */
1379
    public ObjectList querySystemMetadata(Date startTime, Date endTime, 
1380
            ObjectFormatIdentifier objectFormatId, boolean replicaStatus, int start, int count) throws SQLException, PropertyNotFoundException, ServiceException
1381
    {
1382
        ObjectList ol = new ObjectList();
1383
        int total = 0;
1384
        DBConnection dbConn = null;
1385
        int serialNumber = -1;
1386
        
1387
        try {
1388
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
1389
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
1390
                "date_modified, submitter, object_format, size from systemmetadata";
1391
            
1392
            boolean f1 = false;
1393
            boolean f2 = false;
1394
            boolean f3 = false;
1395
            
1396
            if (startTime != null) {
1397
                sql += " where systemmetadata.date_modified > ?";
1398
                f1 = true;
1399
            }
1400
            
1401
            if (endTime != null) {
1402
                if (!f1) {
1403
                    sql += " where systemmetadata.date_modified < ?";
1404
                }
1405
                else {
1406
                    sql += " and systemmetadata.date_modified < ?";
1407
                }
1408
                f2 = true;
1409
            }
1410
            
1411
            if (objectFormatId != null) {
1412
                if (!f1 && !f2) {
1413
                    sql += " where object_format = ?";
1414
                }
1415
                else {
1416
                    sql += " and object_format = ?";
1417
                }
1418
                f3 = true;
1419
            }
1420
            
1421
            if (replicaStatus) {
1422
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
1423
                if (!f1 && !f2 && !f3) {
1424
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
1425
                }
1426
                else {
1427
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
1428
                }
1429
            }
1430
            
1431
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1432
            serialNumber = dbConn.getCheckOutSerialNumber();
1433
            PreparedStatement stmt = dbConn.prepareStatement(sql);
1434
            
1435
            if (f1 && f2 && f3) {
1436
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1437
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1438
                stmt.setString(3, objectFormatId.getValue());
1439
            }
1440
            else if (f1 && f2 && !f3) {
1441
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1442
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1443
            }
1444
            else if (f1 && !f2 && f3) {
1445
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1446
                stmt.setString(2, objectFormatId.getValue());
1447
            }
1448
            else if (f1 && !f2 && !f3) {
1449
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1450
            }
1451
            else if (!f1 && f2 && f3) {
1452
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1453
                stmt.setString(2, objectFormatId.getValue());
1454
            }
1455
            else if (!f1 && !f2 && f3) {
1456
                stmt.setString(1, objectFormatId.getValue());
1457
            }
1458
            else if (!f1 && f2 && !f3) {
1459
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1460
            }
1461
            
1462
            //logMetacat.debug("LISTOBJECTS QUERY: " + stmt.toString());
1463
            
1464
            ResultSet rs = stmt.executeQuery();
1465
            for (int i=0; i<start; i++) {
1466
                if (rs.next()) {
1467
                    total++;
1468
                } else {
1469
                    break;
1470
                }
1471
            }
1472
            
1473
            int countIndex = 0;
1474
                        
1475
            while (rs.next()) {
1476
                total++;
1477
                if (countIndex >= count) {
1478
                	// allow unlimited (negative number for count)
1479
                	if (count > 0) {
1480
                		break;
1481
                	}
1482
                }
1483
                                
1484
                String guid = rs.getString(1);
1485
                //logMetacat.debug("query found doc with guid " + guid);
1486
                //Timestamp dateUploaded = rs.getTimestamp(2);
1487
                //String rightsHolder = rs.getString(3);
1488
                String checksum = rs.getString(4);
1489
                String checksumAlgorithm = rs.getString(5);
1490
                //String originMemberNode = rs.getString(6);
1491
                //String authoritiveMemberNode = rs.getString(7);
1492
                Timestamp dateModified = rs.getTimestamp(8);
1493
                //String submitter = rs.getString(9);
1494
                String fmtidStr = rs.getString(10);
1495
                String sz = rs.getString(11);
1496
                BigInteger size = new BigInteger("0");
1497
                
1498
                if (sz != null && !sz.trim().equals("")) {
1499
                    size = new BigInteger(rs.getString(11));
1500
                }
1501
                
1502
                ObjectInfo oi = new ObjectInfo();
1503
                
1504
                Identifier id = new Identifier();
1505
                id.setValue(guid);
1506
                oi.setIdentifier(id);
1507
                
1508
                if (dateModified != null) {
1509
                	oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
1510
                }
1511
                
1512
                Checksum cs = new Checksum();
1513
                cs.setValue(checksum);
1514
                try {
1515
                	//cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1516
                    cs.setAlgorithm(checksumAlgorithm);
1517
                } catch (Exception e) {
1518
					logMetacat.warn("could not parse checksum algorithm", e);
1519
				}
1520
                oi.setChecksum(cs);
1521
                
1522
                try {
1523
	                oi.setFmtid(ObjectFormatCache.getInstance().getFormat(fmtidStr).getFmtid());
1524
                } catch (NotFound e) {
1525
                	logMetacat.warn("could not find object format: " + fmtidStr, e);
1526

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

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

    
1573
            // Get a database connection from the pool
1574
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1575
            serialNumber = dbConn.getCheckOutSerialNumber();
1576

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

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

    
1616
            // Get a database connection from the pool
1617
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1618
            serialNumber = dbConn.getCheckOutSerialNumber();
1619

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

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

    
1644
            // Get a database connection from the pool
1645
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1646
            serialNumber = dbConn.getCheckOutSerialNumber();
1647

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

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

    
(37-37/65)