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
       throws Exception
647
    {
648
        Vector<String> ids = new Vector<String>();
649
        String sql = "select docid from xml_documents";
650
        DBConnection dbConn = null;
651
        int serialNumber = -1;
652
        try 
653
        {
654
            // Get a database connection from the pool
655
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
656
            serialNumber = dbConn.getCheckOutSerialNumber();
657

    
658
            // Execute the insert statement
659
            PreparedStatement stmt = dbConn.prepareStatement(sql);
660
            ResultSet rs = stmt.executeQuery();
661
            while (rs.next()) 
662
            {
663
                String localid = rs.getString(1);
664
                ids.add(localid);
665
            } 
666
            stmt.close();
667
        } 
668
        catch (SQLException e) 
669
        {
670
            logMetacat.error("Error while looking up the guid: " 
671
                    + e.getMessage());
672
        } 
673
        finally 
674
        {
675
            // Return database connection to the pool
676
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
677
        }
678
        return ids;
679
    }
680
    
681
    /**
682
     * returns a list of system metadata-only guids since the given date
683
     * @return a list of system ids in metacat that do not correspond to objects
684
     * TODO: need to check which server they are on
685
     */
686
    public List<String> getUpdatedSystemMetadataIds(Date since)
687
       throws Exception
688
    {
689
        List<String> ids = new Vector<String>();
690
        String sql = 
691
        	"select guid from " + TYPE_SYSTEM_METADATA +
692
        	" where guid not in " +
693
        	" (select guid from " + TYPE_IDENTIFIER + ") " +
694
        	" and date_modified > ?";
695
        DBConnection dbConn = null;
696
        int serialNumber = -1;
697
        try 
698
        {
699
            // Get a database connection from the pool
700
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getUpdatedSystemMetadataIds");
701
            serialNumber = dbConn.getCheckOutSerialNumber();
702

    
703
            // Execute the insert statement
704
            PreparedStatement stmt = dbConn.prepareStatement(sql);
705
            stmt.setDate(1, new java.sql.Date(since.getTime()));
706
            ResultSet rs = stmt.executeQuery();
707
            while (rs.next()) 
708
            {
709
                String guid = rs.getString(1);
710
                ids.add(guid);
711
            } 
712
            stmt.close();
713
        } 
714
        catch (SQLException e) 
715
        {
716
            logMetacat.error("Error while looking up the updated guids: " 
717
                    + e.getMessage());
718
        } 
719
        finally 
720
        {
721
            // Return database connection to the pool
722
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
723
        }
724
        return ids;
725
    }
726
    
727

    
728
    
729
    /**
730
     * Determine if an identifier exists already, returning true if so.
731
     * 
732
     * @param guid the global identifier to look up
733
     * @return boolean true if the identifier exists
734
     */
735
    public boolean identifierExists(String guid)
736
    {
737
        boolean idExists = false;
738
        try {
739
            String id = getLocalId(guid);
740
            if (id != null) {
741
                idExists = true;
742
            }
743
        } catch (McdbDocNotFoundException e) {
744
        	// try system metadata only
745
        	try {
746
        		idExists = systemMetadataExisits(guid);
747
            } catch (McdbDocNotFoundException e2) {
748
            	idExists = false;
749
            }
750
        }
751
        return idExists;
752
    }
753
    
754
    /**
755
     * 
756
     * @param guid
757
     * @param rev
758
     * @return
759
     */
760
    public String generateLocalId(String guid, int rev)
761
    {
762
        return generateLocalId(guid, rev, false);
763
    }
764

    
765
    /**
766
     * Given a global identifier (guid), create a suitable local identifier that
767
     * follows Metacat's docid semantics and format (scope.id.rev), and create
768
     * a mapping between these two identifiers.  This effectively reserves both
769
     * the global and the local identifier, as they will now be present in the
770
     * identifier mapping table.  If the incoming guid has the syntax of a
771
     * Metacat docid (scope.id.rev), then simply use it.
772
     * 
773
     * @param guid the global string identifier
774
     * @param rev the revision number to be used in the localId
775
     * @return String containing the localId to be used for Metacat operations
776
     */
777
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata) 
778
    {
779
        String localId = "";
780
        boolean conformsToDocidFormat = false;
781
        
782
        // Check if the guid passed in is already in docid (scope.id.rev) format
783
        try {
784
            AccessionNumber acc = new AccessionNumber(guid, "NONE");
785
            if (new Integer(acc.getRev()).intValue() > 0) {
786
                conformsToDocidFormat = true;
787
            }
788
        } catch (NumberFormatException e) {
789
            // No action needed, simply detecting invalid AccessionNumbers
790
        } catch (AccessionNumberException e) {
791
            // No action needed, simply detecting invalid AccessionNumbers
792
        } catch (SQLException e) {
793
            // No action needed, simply detecting invalid AccessionNumbers
794
        }
795
        
796
        if (conformsToDocidFormat) {
797
            // if it conforms, use it for both guid and localId
798
            localId = guid;
799
        } else {
800
            // if not, then generate a new unique localId
801
            localId = DocumentUtil.generateDocumentId(rev);
802
        }
803
        
804
        // Register this new pair in the identifier mapping table
805
        logMetacat.debug("creating mapping in generateLocalId");
806
        if(!isSystemMetadata)
807
        { //don't do this if we're generating for system metadata
808
            createMapping(guid, localId);
809
        }
810
        
811
        return localId;
812
    }
813
    
814
    /**
815
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
816
     * if the docid, rev is not found in the identifiers or systemmetadata tables
817
     *
818
     * @param docid the docid to look up
819
     * @param rev the revision of the docid to look up
820
     * @return String containing the mapped guid
821
     * @throws McdbDocNotFoundException if the docid, rev is not found
822
     */
823
    public String getGUID(String docid, int rev)
824
      throws McdbDocNotFoundException
825
    {
826
        logMetacat.debug("getting guid for " + docid);
827
        String query = "select guid from identifier where docid = ? and rev = ?";
828
        String guid = null;
829
        
830
        DBConnection dbConn = null;
831
        int serialNumber = -1;
832
        try {
833
            // Get a database connection from the pool
834
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
835
            serialNumber = dbConn.getCheckOutSerialNumber();
836
            
837
            // Execute the insert statement
838
            PreparedStatement stmt = dbConn.prepareStatement(query);
839
            stmt.setString(1, docid);
840
            stmt.setInt(2, rev);
841
            ResultSet rs = stmt.executeQuery();
842
            if (rs.next()) 
843
            {
844
                guid = rs.getString(1);
845
            } 
846
            else
847
            {
848
            	throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
849
            }
850
            
851
        } catch (SQLException e) {
852
            logMetacat.error("Error while looking up the guid: " 
853
                    + e.getMessage());
854
        } finally {
855
            // Return database connection to the pool
856
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
857
        }
858
        
859
        return guid;
860
    }
861
    
862
    public boolean systemMetadataExisits(String guid)
863
			throws McdbDocNotFoundException {
864
		logMetacat.debug("looking up system metadata for guid " + guid);
865
		boolean exists = false;
866
		String query = "select guid from systemmetadata where guid = ?";
867

    
868
		DBConnection dbConn = null;
869
		int serialNumber = -1;
870
		try {
871
			// Get a database connection from the pool
872
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
873
			serialNumber = dbConn.getCheckOutSerialNumber();
874

    
875
			// Execute the insert statement
876
			PreparedStatement stmt = dbConn.prepareStatement(query);
877
			stmt.setString(1, guid);
878
			ResultSet rs = stmt.executeQuery();
879
			if (rs.next()) {
880
				exists = true;
881
			} else {
882
				throw new McdbDocNotFoundException(
883
						"No system metadata registered for guid " + guid);
884
			}
885

    
886
		} catch (SQLException e) {
887
			logMetacat.error("Error while looking up the system metadata: "
888
					+ e.getMessage());
889
		} finally {
890
			// Return database connection to the pool
891
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
892
		}
893

    
894
		return exists;
895
	}
896
    
897
    /**
898
     * creates a system metadata mapping and adds additional fields from sysmeta
899
     * to the table for quick searching.
900
     * 
901
     * @param guid the id to insert
902
     * @param localId the systemMetadata object to get the local id for
903
     * @throws McdbDocNotFoundException 
904
     */
905
    public void createSystemMetadata(SystemMetadata sysmeta) throws McdbDocNotFoundException
906
    {
907
    	String guid = sysmeta.getIdentifier().getValue();
908
    	// insert the record
909
        insertSystemMetadata(guid);
910
        // update with the values
911
        updateSystemMetadata(sysmeta);
912
    }
913
        
914
    
915
    /**
916
     * update a mapping
917
     * @param guid
918
     * @param localId
919
     */
920
    public void updateMapping(String guid, String localId)
921
    {
922
    	
923
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
924
        int serialNumber = -1;
925
        DBConnection dbConn = null;
926
        try {
927
            // Parse the localId into scope and rev parts
928
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
929
            String docid = acc.getDocid();
930
            int rev = 1;
931
            if(acc.getRev() != null)
932
            {
933
              rev = (new Integer(acc.getRev()).intValue());
934
            }
935

    
936
            // Get a database connection from the pool
937
            dbConn = 
938
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
939
            serialNumber = dbConn.getCheckOutSerialNumber();
940

    
941
            // Execute the update statement
942
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid='" + guid + "'";
943
            PreparedStatement stmt = dbConn.prepareStatement(query);
944
            stmt.setString(1, docid);
945
            stmt.setInt(2, rev);
946
            int rows = stmt.executeUpdate();
947

    
948
            stmt.close();
949
        } catch (SQLException e) {
950
            e.printStackTrace();
951
            logMetacat.error("SQL error while updating a mapping identifier: " 
952
                    + e.getMessage());
953
        } catch (NumberFormatException e) {
954
            e.printStackTrace();
955
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
956
                    + e.getMessage());
957
        } catch (AccessionNumberException e) {
958
            e.printStackTrace();
959
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
960
                    + e.getMessage());
961
        } finally {
962
            // Return database connection to the pool
963
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
964
        }
965
        logMetacat.debug("done updating mapping");
966
    }
967
        
968
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
969
            String checksum, String checksumAlgorithm, String originMemberNode,
970
            String authoritativeMemberNode, long modifiedDate, String submitter, 
971
            String guid, String objectFormat, BigInteger size, boolean replicationAllowed,
972
            int numberReplicas, String obsoletes, String obsoletedBy)
973
    {
974
        DBConnection dbConn = null;
975
        int serialNumber = -1;
976
        
977
        try {
978
            // Get a database connection from the pool
979
            dbConn = 
980
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
981
            serialNumber = dbConn.getCheckOutSerialNumber();
982

    
983
            // Execute the insert statement
984
            String query = "update " + TYPE_SYSTEM_METADATA + 
985
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
986
                "origin_member_node, authoritive_member_node, date_modified, " +
987
                "submitter, object_format, size, replication_allowed, number_replicas, obsoletes, obsoleted_by) " +
988
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
989
            PreparedStatement stmt = dbConn.prepareStatement(query);
990
            
991
            //data values
992
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
993
            stmt.setString(2, rightsHolder);
994
            stmt.setString(3, checksum);
995
            stmt.setString(4, checksumAlgorithm);
996
            stmt.setString(5, originMemberNode);
997
            stmt.setString(6, authoritativeMemberNode);
998
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
999
            stmt.setString(8, submitter);
1000
            stmt.setString(9, objectFormat);
1001
            stmt.setString(10, size.toString());
1002
            stmt.setBoolean(11, replicationAllowed);
1003
            stmt.setInt(12, numberReplicas);
1004
            stmt.setString(13, obsoletes);
1005
            stmt.setString(14, obsoletedBy);
1006

    
1007
            //where clause
1008
            stmt.setString(15, guid);
1009
            logMetacat.debug("stmt: " + stmt.toString());
1010
            //execute
1011
            int rows = stmt.executeUpdate();
1012

    
1013
            stmt.close();
1014
        } catch (SQLException e) {
1015
            e.printStackTrace();
1016
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: " 
1017
                    + e.getMessage());
1018
        } catch (NumberFormatException e) {
1019
            e.printStackTrace();
1020
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: " 
1021
                    + e.getMessage());
1022
        } finally {
1023
            // Return database connection to the pool
1024
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1025
        }
1026
    }
1027
    
1028
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes)
1029
    {
1030
        DBConnection dbConn = null;
1031
        int serialNumber = -1;
1032
        
1033
        try {
1034
            // Get a database connection from the pool
1035
            dbConn = 
1036
                DBConnectionPool.getDBConnection("IdentifierManager.insertReplicationPolicy");
1037
            serialNumber = dbConn.getCheckOutSerialNumber();
1038

    
1039
            // remove existing values first
1040
            String delete = "delete from systemMetadataReplicationPolicy " + 
1041
            "where guid = ? and policy = ?";
1042
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1043
	        //data values
1044
	        stmt.setString(1, guid);
1045
	        stmt.setString(2, policy);
1046
	        //execute
1047
	        int deletedCount = stmt.executeUpdate();
1048
	        stmt.close();
1049
            
1050
            for (String memberNode: memberNodes) {
1051
	            // Execute the insert statement
1052
	            String insert = "insert into systemMetadataReplicationPolicy " + 
1053
	                "(guid, policy, member_node) " +
1054
	                "values (?, ?, ?)";
1055
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1056
	            
1057
	            //data values
1058
	            insertStatement.setString(1, guid);
1059
	            insertStatement.setString(2, policy);
1060
	            insertStatement.setString(3, memberNode);
1061
	            //execute
1062
	            int rows = insertStatement.executeUpdate();
1063
	            insertStatement.close();
1064
            }
1065
        } catch (SQLException e) {
1066
            logMetacat.error("SQL error while adding systemMetadataReplicationPolicy for: " + guid, e); 
1067
        } finally {
1068
            // Return database connection to the pool
1069
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1070
        }
1071
    }
1072
    
1073
    private void insertReplicationStatus(String guid, List<Replica> replicas) {
1074
        DBConnection dbConn = null;
1075
        int serialNumber = -1;
1076
        
1077
        try {
1078
            // Get a database connection from the pool
1079
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertReplicas");
1080
            serialNumber = dbConn.getCheckOutSerialNumber();
1081

    
1082
            // remove existing values first
1083
            String delete = "delete from systemMetadataReplicationStatus " + 
1084
            "where guid = ?";
1085
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1086
	        //data values
1087
	        stmt.setString(1, guid);
1088
	        //execute
1089
	        int deletedCount = stmt.executeUpdate();
1090
	        stmt.close();
1091
            
1092
            for (Replica replica: replicas) {
1093
	            // Execute the insert statement
1094
	            String insert = "insert into systemMetadataReplicationStatus " + 
1095
	                "(guid, member_node, status, date_verified) " +
1096
	                "values (?, ?, ?, ?)";
1097
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1098
	            
1099
	            //data values
1100
	            String memberNode = replica.getReplicaMemberNode().getValue();
1101
	            String status = replica.getReplicationStatus().toString();
1102
	            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1103
	            insertStatement.setString(1, guid);
1104
	            insertStatement.setString(2, memberNode);
1105
	            insertStatement.setString(3, status);
1106
	            insertStatement.setDate(4, sqlDate);
1107

    
1108
	            //execute
1109
	            int rows = insertStatement.executeUpdate();
1110
	            insertStatement.close();
1111
            }
1112
        } catch (SQLException e) {
1113
            logMetacat.error("SQL error while adding systemMetadataReplicationStatus for: " + guid, e); 
1114
        } finally {
1115
            // Return database connection to the pool
1116
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1117
        }
1118
    }
1119
    
1120
    /**
1121
     * Insert the system metadata fields into the db
1122
     * @param sm
1123
     * @throws McdbDocNotFoundException 
1124
     */
1125
    public void updateSystemMetadata(SystemMetadata sm) throws McdbDocNotFoundException {
1126
    	
1127
        Boolean replicationAllowed = false;
1128
		Integer numberReplicas = -1;
1129
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1130
    	if (replicationPolicy != null) {
1131
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1132
    		numberReplicas = replicationPolicy.getNumberReplicas();
1133
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1134
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1135
    	}
1136

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

    
1481
				}
1482
                                
1483
                oi.setSize(size);
1484
                
1485
                ol.addObjectInfo(oi);
1486
                countIndex++;
1487
            }
1488
            
1489
            // expend the resultset to get the total count of possible rows
1490
            while (rs.next()) { 
1491
                total++;
1492
            }
1493
        }
1494
        
1495
        finally {
1496
            // Return database connection to the pool
1497
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1498
        }
1499
        
1500
        ol.setStart(start);
1501
        ol.setCount(ol.sizeObjectInfoList());
1502
        ol.setTotal(total);
1503
        
1504
        return ol;
1505
    }
1506
    
1507
    /**
1508
     * create a mapping in the identifier table
1509
     * @param guid
1510
     * @param localId
1511
     */
1512
    public void createMapping(String guid, String localId)
1513
    {        
1514
        
1515
        int serialNumber = -1;
1516
        DBConnection dbConn = null;
1517
        try {
1518

    
1519
            // Parse the localId into scope and rev parts
1520
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1521
            String docid = acc.getDocid();
1522
            int rev = 1;
1523
            if (acc.getRev() != null) {
1524
              rev = (new Integer(acc.getRev()).intValue());
1525
            }
1526

    
1527
            // Get a database connection from the pool
1528
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1529
            serialNumber = dbConn.getCheckOutSerialNumber();
1530

    
1531
            // Execute the insert statement
1532
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1533
            PreparedStatement stmt = dbConn.prepareStatement(query);
1534
            stmt.setString(1, guid);
1535
            stmt.setString(2, docid);
1536
            stmt.setInt(3, rev);
1537
            logMetacat.debug("mapping query: " + stmt.toString());
1538
            int rows = stmt.executeUpdate();
1539

    
1540
            stmt.close();
1541
        } catch (SQLException e) {
1542
            e.printStackTrace();
1543
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1544
                    + e.getMessage());
1545
        } catch (NumberFormatException e) {
1546
            e.printStackTrace();
1547
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1548
                    + e.getMessage());
1549
        } catch (AccessionNumberException e) {
1550
            e.printStackTrace();
1551
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1552
                    + e.getMessage());
1553
        } finally {
1554
            // Return database connection to the pool
1555
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1556
        }
1557
    }
1558
    
1559
    /**
1560
     * create the systemmetadata record
1561
     * @param guid
1562
     */
1563
    private void insertSystemMetadata(String guid)
1564
    {        
1565
        
1566
        int serialNumber = -1;
1567
        DBConnection dbConn = null;
1568
        try {
1569

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

    
1574
            // Execute the insert statement
1575
            String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1576
            PreparedStatement stmt = dbConn.prepareStatement(query);
1577
            stmt.setString(1, guid);
1578
            logMetacat.debug("system metadata query: " + stmt.toString());
1579
            int rows = stmt.executeUpdate();
1580

    
1581
            stmt.close();
1582
        } catch (Exception e) {
1583
            e.printStackTrace();
1584
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1585
        } finally {
1586
            // Return database connection to the pool
1587
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1588
        }
1589
    }
1590
    
1591
    private void deleteSystemMetadata(String guid)
1592
    {        
1593
        
1594
        int serialNumber = -1;
1595
        DBConnection dbConn = null;
1596
        try {
1597

    
1598
            // Get a database connection from the pool
1599
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1600
            serialNumber = dbConn.getCheckOutSerialNumber();
1601

    
1602
            // Execute the statement
1603
            String query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
1604
            PreparedStatement stmt = dbConn.prepareStatement(query);
1605
            stmt.setString(1, guid);
1606
            logMetacat.debug("delete system metadata: " + stmt.toString());
1607
            int rows = stmt.executeUpdate();
1608

    
1609
            stmt.close();
1610
        } catch (Exception e) {
1611
            e.printStackTrace();
1612
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1613
        } finally {
1614
            // Return database connection to the pool
1615
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1616
        }
1617
    }
1618
}
1619

    
(37-37/65)