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
                Identifier obsoletesId = new Identifier();
311
                obsoletesId.setValue(obsoletes);
312
                sysMeta.setObsoletes(obsoletesId);
313
                Identifier obsoletedById = new Identifier();
314
                obsoletedById.setValue(obsoletedBy);
315
                sysMeta.setObsoletedBy(obsoletedById);
316
                
317
                stmt.close();
318
            } 
319
            else
320
            {
321
                stmt.close();
322
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
323
                throw new McdbDocNotFoundException("Could not find " + guid);
324
            }
325
            
326
        } 
327
        catch (SQLException e) 
328
        {
329
            e.printStackTrace();
330
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "  
331
                    + e.getMessage());
332
        } 
333
        finally 
334
        {
335
            // Return database connection to the pool
336
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
337
        }
338

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

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

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

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

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

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

    
746
            // Execute the insert statement
747
            PreparedStatement stmt = dbConn.prepareStatement(sql);
748
            stmt.setDate(1, new java.sql.Date(since.getTime()));
749
            ResultSet rs = stmt.executeQuery();
750
            while (rs.next()) 
751
            {
752
                String guid = rs.getString(1);
753
                ids.add(guid);
754
            } 
755
            stmt.close();
756
        } 
757
        catch (SQLException e) 
758
        {
759
            logMetacat.error("Error while looking up the updated guids: " 
760
                    + e.getMessage());
761
        } 
762
        finally 
763
        {
764
            // Return database connection to the pool
765
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
766
        }
767
        return ids;
768
    }
769
    
770

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

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

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

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

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

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

    
979
            // Get a database connection from the pool
980
            dbConn = 
981
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
982
            serialNumber = dbConn.getCheckOutSerialNumber();
983

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

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

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

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

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

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

    
1125
            // remove existing values first
1126
            String delete = "delete from systemMetadataReplicationStatus " + 
1127
            "where guid = ?";
1128
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1129
	        //data values
1130
	        stmt.setString(1, guid);
1131
	        //execute
1132
	        int deletedCount = stmt.executeUpdate();
1133
	        stmt.close();
1134
            
1135
            for (Replica replica: replicas) {
1136
	            // Execute the insert statement
1137
	            String insert = "insert into systemMetadataReplicationStatus " + 
1138
	                "(guid, member_node, status, date_verified) " +
1139
	                "values (?, ?, ?, ?)";
1140
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1141
	            
1142
	            //data values
1143
	            String memberNode = replica.getReplicaMemberNode().getValue();
1144
	            String status = replica.getReplicationStatus().toString();
1145
	            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1146
	            insertStatement.setString(1, guid);
1147
	            insertStatement.setString(2, memberNode);
1148
	            insertStatement.setString(3, status);
1149
	            insertStatement.setDate(4, sqlDate);
1150

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

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

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

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

    
1570
            // Get a database connection from the pool
1571
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1572
            serialNumber = dbConn.getCheckOutSerialNumber();
1573

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

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

    
1613
            // Get a database connection from the pool
1614
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1615
            serialNumber = dbConn.getCheckOutSerialNumber();
1616

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

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

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

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

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

    
(37-37/65)