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.ChecksumAlgorithm;
45
import org.dataone.service.types.v1.Identifier;
46
import org.dataone.service.types.v1.NodeReference;
47
import org.dataone.service.types.v1.ObjectFormat;
48
import org.dataone.service.types.v1.ObjectFormatIdentifier;
49
import org.dataone.service.types.v1.ObjectInfo;
50
import org.dataone.service.types.v1.ObjectList;
51
import org.dataone.service.types.v1.Permission;
52
import org.dataone.service.types.v1.Replica;
53
import org.dataone.service.types.v1.ReplicationPolicy;
54
import org.dataone.service.types.v1.ReplicationStatus;
55
import org.dataone.service.types.v1.Subject;
56
import org.dataone.service.types.v1.SystemMetadata;
57

    
58
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlInterface;
59
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
60
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
61
import edu.ucsb.nceas.metacat.database.DBConnection;
62
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
63
import edu.ucsb.nceas.metacat.properties.PropertyService;
64
import edu.ucsb.nceas.metacat.shared.AccessException;
65
import edu.ucsb.nceas.metacat.shared.ServiceException;
66
import edu.ucsb.nceas.metacat.util.DocumentUtil;
67
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
68

    
69
/**
70
 * Manage the relationship between Metacat local identifiers (LocalIDs) that are
71
 * codified as the (docid, rev) pair with globally unique string identifiers
72
 * (GUIDs) that are opaque strings.  This class provides methods to manage these
73
 * identifiers, and to search for and look up LocalIDs based on their GUID and
74
 * vice versa. IdentifierManager is a singleton.
75
 * 
76
 * @author Matthew Jones
77
 */
78
public class IdentifierManager {
79
    
80
    public static final String TYPE_SYSTEM_METADATA = "systemmetadata";
81
    public static final String TYPE_IDENTIFIER = "identifier";
82
  
83
    /**
84
     * The single instance of the manager that is always returned.
85
     */
86
    private static IdentifierManager self = null;
87
    private Logger logMetacat = Logger.getLogger(IdentifierManager.class);
88

    
89
    /**
90
     * A private constructor that initializes the class when getInstance() is
91
     * called.
92
     */
93
    private IdentifierManager() {}
94

    
95
    /**
96
     * Return the single instance of the manager after initializing it if it
97
     * wasn't previously initialized.
98
     * 
99
     * @return the single IdentifierManager instance
100
     */
101
    public static IdentifierManager getInstance()
102
    {
103
        if (self == null) {
104
            self = new IdentifierManager();
105
        }
106
        return self;
107
    }
108
    
109
    public SystemMetadata asSystemMetadata(Date dateUploaded, String rightsHolder,
110
            String checksum, String checksumAlgorithm, String originMemberNode,
111
            String authoritativeMemberNode, Date dateModified, String submitter, 
112
            String guid, String fmtidStr, BigInteger size) {
113
        SystemMetadata sysMeta = new SystemMetadata();
114

    
115
        Identifier sysMetaId = new Identifier();
116
        sysMetaId.setValue(guid);
117
        sysMeta.setIdentifier(sysMetaId);
118
        sysMeta.setDateUploaded(dateUploaded);
119
        Subject rightsHolderSubject = new Subject();
120
        rightsHolderSubject.setValue(rightsHolder);
121
        sysMeta.setRightsHolder(rightsHolderSubject);
122
        Checksum checksumObject = new Checksum();
123
        checksumObject.setValue(checksum);
124
        checksumObject.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
125
        sysMeta.setChecksum(checksumObject);
126
        NodeReference omn = new NodeReference();
127
        omn.setValue(originMemberNode);
128
        sysMeta.setOriginMemberNode(omn);
129
        NodeReference amn = new NodeReference();
130
        amn.setValue(authoritativeMemberNode);
131
        sysMeta.setAuthoritativeMemberNode(amn);
132
        sysMeta.setDateSysMetadataModified(dateModified);
133
        Subject submitterSubject = new Subject();
134
        submitterSubject.setValue(submitter);
135
        sysMeta.setSubmitter(submitterSubject);
136
        try {
137
        	ObjectFormatIdentifier fmtid = 
138
        		ObjectFormatCache.getInstance().getFormat(fmtidStr).getFmtid();
139
        	sysMeta.setFmtid(fmtid);
140
        } catch (NotFound nfe) {
141
          logMetacat.error("The objectFormat " + fmtidStr +
142
          	" is not registered. Setting the default format id.");
143
          ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
144
          fmtid.setValue("application/octet-stream");
145
          sysMeta.setFmtid(fmtid);
146
        }
147
        sysMeta.setSize(size);
148
        
149
        return sysMeta;
150
    }
151
    
152
    /**
153
     * return a hash of all of the info that is in the systemmetadata table
154
     * @param localId
155
     * @return
156
     */
157
    public Hashtable<String, String> getSystemMetadataInfo(String localId)
158
    throws McdbDocNotFoundException
159
    {
160
        try
161
        {
162
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
163
            localId = acc.getDocid();
164
        }
165
        catch(Exception e)
166
        {
167
            //do nothing. just try the localId as it is
168
        }
169
        Hashtable<String, String> h = new Hashtable<String, String>();
170
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
171
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size " +
172
          "from systemmetadata where docid = ?";
173
        DBConnection dbConn = null;
174
        int serialNumber = -1;
175
        try 
176
        {
177
            // Get a database connection from the pool
178
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
179
            serialNumber = dbConn.getCheckOutSerialNumber();
180

    
181
            // Execute the insert statement
182
            PreparedStatement stmt = dbConn.prepareStatement(sql);
183
            stmt.setString(1, localId);
184
            ResultSet rs = stmt.executeQuery();
185
            if (rs.next()) 
186
            {
187
                String guid = rs.getString(1);
188
                Timestamp dateUploaded = rs.getTimestamp(2);
189
                String rightsHolder = rs.getString(3);
190
                String checksum = rs.getString(4);
191
                String checksumAlgorithm = rs.getString(5);
192
                String originMemberNode = rs.getString(6);
193
                String authoritativeMemberNode = rs.getString(7);
194
                Timestamp dateModified = rs.getTimestamp(8);
195
                String submitter = rs.getString(9);
196
                String objectFormat = rs.getString(10);
197
                long size = new Long(rs.getString(11)).longValue();
198
                
199
                h.put("guid", guid);
200
                h.put("date_uploaded", new Long(dateUploaded.getTime()).toString());
201
                h.put("rights_holder", rightsHolder);
202
                h.put("checksum", checksum);
203
                h.put("checksum_algorithm", checksumAlgorithm);
204
                h.put("origin_member_node", originMemberNode);
205
                h.put("authoritative_member_node", authoritativeMemberNode);
206
                h.put("date_modified", new Long(dateModified.getTime()).toString());
207
                h.put("submitter", submitter);
208
                h.put("object_format", objectFormat);
209
                h.put("size", new Long(size).toString());
210
                
211
                stmt.close();
212
            } 
213
            else
214
            {
215
                stmt.close();
216
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
217
                throw new McdbDocNotFoundException("2Could not find document " + localId);
218
            }
219
            
220
        } 
221
        catch (SQLException e) 
222
        {
223
            e.printStackTrace();
224
            logMetacat.error("Error while getting system metadata info for localid " + localId + " : "  
225
                    + e.getMessage());
226
        } 
227
        finally 
228
        {
229
            // Return database connection to the pool
230
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
231
        }
232
        return h;
233
    }
234
    
235
    /**
236
     * return a hash of all of the info that is in the systemmetadata table
237
     * @param guid
238
     * @return
239
     * @throws McdbDocNotFoundException 
240
     */
241
    public SystemMetadata getSystemMetadata(String guid)
242
    	throws McdbDocNotFoundException
243
    {
244
        
245
        SystemMetadata sysMeta = new SystemMetadata();
246
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
247
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size, " +
248
          "obsoletes, obsoleted_by " +
249
          "from systemmetadata where guid = ?";
250
        DBConnection dbConn = null;
251
        int serialNumber = -1;
252
        try 
253
        {
254
            // Get a database connection from the pool
255
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getSystemMetadata");
256
            serialNumber = dbConn.getCheckOutSerialNumber();
257

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

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

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

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

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

    
615
            // Execute the insert statement
616
            PreparedStatement stmt = dbConn.prepareStatement(sql);
617
            ResultSet rs = stmt.executeQuery();
618
            while (rs.next()) 
619
            {
620
                String localid = rs.getString(1);
621
                String rev = rs.getString(2);
622
                localid += "." + rev;
623
                logMetacat.debug("id to add SM for: " + localid);
624
                ids.add(localid);
625
            } 
626
            stmt.close();
627
        } 
628
        catch (SQLException e) 
629
        {
630
            logMetacat.error("Error while looking up the guid: " 
631
                    + e.getMessage());
632
        } 
633
        finally 
634
        {
635
            // Return database connection to the pool
636
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
637
        }
638
        
639
        return ids;
640
    }
641
    
642
    /**
643
     * return a listing of all local ids in the object store
644
     * @return a list of all local ids in metacat
645
     */
646
    public List<String> getAllLocalIds()
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
     * returns a list of system metadata-only guids since the given date
684
     * @return a list of system ids in metacat that do not correspond to objects
685
     * TODO: need to check which server they are on
686
     */
687
    public List<String> getUpdatedSystemMetadataIds(Date since)
688
       throws Exception
689
    {
690
        List<String> ids = new Vector<String>();
691
        String sql = 
692
        	"select guid from " + TYPE_SYSTEM_METADATA +
693
        	" where guid not in " +
694
        	" (select guid from " + TYPE_IDENTIFIER + ") " +
695
        	" and date_modified > ?";
696
        DBConnection dbConn = null;
697
        int serialNumber = -1;
698
        try 
699
        {
700
            // Get a database connection from the pool
701
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getUpdatedSystemMetadataIds");
702
            serialNumber = dbConn.getCheckOutSerialNumber();
703

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
(37-37/65)