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
                if (originMemberNode != null) {
289
	                NodeReference omn = new NodeReference();
290
	                omn.setValue(originMemberNode);
291
	                sysMeta.setOriginMemberNode(omn);
292
                }
293
                if (authoritativeMemberNode != null) {
294
	                NodeReference amn = new NodeReference();
295
	                amn.setValue(authoritativeMemberNode);
296
	                sysMeta.setAuthoritativeMemberNode(amn);
297
                }
298
                sysMeta.setDateSysMetadataModified(dateModified);
299
                Subject submitterSubject = new Subject();
300
                submitterSubject.setValue(submitter);
301
                sysMeta.setSubmitter(submitterSubject);
302
                try {
303
                	ObjectFormatIdentifier fmtid = 
304
                		ObjectFormatCache.getInstance().getFormat(fmtidStr).getFmtid();
305
                	sysMeta.setFmtid(fmtid);
306
                } catch (NotFound nfe) {
307
                  logMetacat.error("The objectFormat " + fmtidStr +
308
                  	" is not registered. Setting the default format id.");
309
                  ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
310
                  fmtid.setValue("application/octet-stream");
311
                  sysMeta.setFmtid(fmtid);
312
                }
313
                sysMeta.setSize(size);
314
                if (obsoletes != null) {
315
	                Identifier obsoletesId = new Identifier();
316
	                obsoletesId.setValue(obsoletes);
317
	                sysMeta.setObsoletes(obsoletesId);
318
                }
319
                if (obsoletedBy != null) {
320
		            Identifier obsoletedById = new Identifier();
321
		            obsoletedById.setValue(obsoletedBy);
322
		            sysMeta.setObsoletedBy(obsoletedById);
323
                }
324
                stmt.close();
325
            } 
326
            else
327
            {
328
                stmt.close();
329
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
330
                throw new McdbDocNotFoundException("Could not find " + guid);
331
            }
332
            
333
        } 
334
        catch (SQLException e) 
335
        {
336
            e.printStackTrace();
337
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "  
338
                    + e.getMessage());
339
        } 
340
        finally 
341
        {
342
            // Return database connection to the pool
343
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
344
        }
345

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

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

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

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

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

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

    
753
            // Execute the insert statement
754
            PreparedStatement stmt = dbConn.prepareStatement(sql);
755
            stmt.setDate(1, new java.sql.Date(since.getTime()));
756
            ResultSet rs = stmt.executeQuery();
757
            while (rs.next()) 
758
            {
759
                String guid = rs.getString(1);
760
                ids.add(guid);
761
            } 
762
            stmt.close();
763
        } 
764
        catch (SQLException e) 
765
        {
766
            logMetacat.error("Error while looking up the updated guids: " 
767
                    + e.getMessage());
768
        } 
769
        finally 
770
        {
771
            // Return database connection to the pool
772
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
773
        }
774
        return ids;
775
    }
776
    
777
    /**
778
     * returns a list of system metadata-only guids since the given date
779
     * @return a list of system ids in metacat that do not correspond to objects
780
     * TODO: need to check which server they are on
781
     */
782
    public Date getLastModifiedDate() throws Exception {
783
        Date maxDate = null;
784

    
785
        List<String> ids = new Vector<String>();
786
        String sql = 
787
        	"select max(date_modified) from " + TYPE_SYSTEM_METADATA;
788
        DBConnection dbConn = null;
789
        int serialNumber = -1;
790
        try 
791
        {
792
            // Get a database connection from the pool
793
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLastModifiedDate");
794
            serialNumber = dbConn.getCheckOutSerialNumber();
795

    
796
            // Execute the insert statement
797
            PreparedStatement stmt = dbConn.prepareStatement(sql);
798
            ResultSet rs = stmt.executeQuery();
799
            if (rs.next()) {
800
            	maxDate = rs.getDate(1);
801
            } 
802
            stmt.close();
803
        } 
804
        catch (SQLException e) 
805
        {
806
            logMetacat.error("Error while looking up the latest update date: " 
807
                    + e.getMessage());
808
        } 
809
        finally 
810
        {
811
            // Return database connection to the pool
812
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
813
        }
814
        return maxDate;
815
    }
816

    
817
    
818
    /**
819
     * Determine if an identifier exists already, returning true if so.
820
     * 
821
     * @param guid the global identifier to look up
822
     * @return boolean true if the identifier exists
823
     */
824
    public boolean identifierExists(String guid)
825
    {
826
        boolean idExists = false;
827
        try {
828
            String id = getLocalId(guid);
829
            if (id != null) {
830
                idExists = true;
831
            }
832
        } catch (McdbDocNotFoundException e) {
833
        	// try system metadata only
834
        	try {
835
        		idExists = systemMetadataExists(guid);
836
            } catch (Exception e2) {
837
            	idExists = false;
838
            }
839
        }
840
        return idExists;
841
    }
842
    
843
    /**
844
     * 
845
     * @param guid
846
     * @param rev
847
     * @return
848
     */
849
    public String generateLocalId(String guid, int rev)
850
    {
851
        return generateLocalId(guid, rev, false);
852
    }
853

    
854
    /**
855
     * Given a global identifier (guid), create a suitable local identifier that
856
     * follows Metacat's docid semantics and format (scope.id.rev), and create
857
     * a mapping between these two identifiers.  This effectively reserves both
858
     * the global and the local identifier, as they will now be present in the
859
     * identifier mapping table.  If the incoming guid has the syntax of a
860
     * Metacat docid (scope.id.rev), then simply use it.
861
     * 
862
     * @param guid the global string identifier
863
     * @param rev the revision number to be used in the localId
864
     * @return String containing the localId to be used for Metacat operations
865
     */
866
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata) 
867
    {
868
        String localId = "";
869
        boolean conformsToDocidFormat = false;
870
        
871
        // Check if the guid passed in is already in docid (scope.id.rev) format
872
        try {
873
            AccessionNumber acc = new AccessionNumber(guid, "NONE");
874
            if (new Integer(acc.getRev()).intValue() > 0) {
875
                conformsToDocidFormat = true;
876
            }
877
        } catch (NumberFormatException e) {
878
            // No action needed, simply detecting invalid AccessionNumbers
879
        } catch (AccessionNumberException e) {
880
            // No action needed, simply detecting invalid AccessionNumbers
881
        } catch (SQLException e) {
882
            // No action needed, simply detecting invalid AccessionNumbers
883
        }
884
        
885
        if (conformsToDocidFormat) {
886
            // if it conforms, use it for both guid and localId
887
            localId = guid;
888
        } else {
889
            // if not, then generate a new unique localId
890
            localId = DocumentUtil.generateDocumentId(rev);
891
        }
892
        
893
        // Register this new pair in the identifier mapping table
894
        logMetacat.debug("creating mapping in generateLocalId");
895
        if(!isSystemMetadata)
896
        { //don't do this if we're generating for system metadata
897
            createMapping(guid, localId);
898
        }
899
        
900
        return localId;
901
    }
902
    
903
    /**
904
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
905
     * if the docid, rev is not found in the identifiers or systemmetadata tables
906
     *
907
     * @param docid the docid to look up
908
     * @param rev the revision of the docid to look up
909
     * @return String containing the mapped guid
910
     * @throws McdbDocNotFoundException if the docid, rev is not found
911
     */
912
    public String getGUID(String docid, int rev)
913
      throws McdbDocNotFoundException
914
    {
915
        logMetacat.debug("getting guid for " + docid);
916
        String query = "select guid from identifier where docid = ? and rev = ?";
917
        String guid = null;
918
        
919
        DBConnection dbConn = null;
920
        int serialNumber = -1;
921
        try {
922
            // Get a database connection from the pool
923
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
924
            serialNumber = dbConn.getCheckOutSerialNumber();
925
            
926
            // Execute the insert statement
927
            PreparedStatement stmt = dbConn.prepareStatement(query);
928
            stmt.setString(1, docid);
929
            stmt.setInt(2, rev);
930
            ResultSet rs = stmt.executeQuery();
931
            if (rs.next()) 
932
            {
933
                guid = rs.getString(1);
934
            } 
935
            else
936
            {
937
            	throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
938
            }
939
            
940
        } catch (SQLException e) {
941
            logMetacat.error("Error while looking up the guid: " 
942
                    + e.getMessage());
943
        } finally {
944
            // Return database connection to the pool
945
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
946
        }
947
        
948
        return guid;
949
    }
950
    
951
    public boolean systemMetadataExists(String guid) {
952
		logMetacat.debug("looking up system metadata for guid " + guid);
953
		boolean exists = false;
954
		String query = "select guid from systemmetadata where guid = ?";
955

    
956
		DBConnection dbConn = null;
957
		int serialNumber = -1;
958
		try {
959
			// Get a database connection from the pool
960
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
961
			serialNumber = dbConn.getCheckOutSerialNumber();
962

    
963
			// Execute the insert statement
964
			PreparedStatement stmt = dbConn.prepareStatement(query);
965
			stmt.setString(1, guid);
966
			ResultSet rs = stmt.executeQuery();
967
			if (rs.next()) {
968
				exists = true;
969
			}
970

    
971
		} catch (SQLException e) {
972
			logMetacat.error("Error while looking up the system metadata: "
973
					+ e.getMessage());
974
		} finally {
975
			// Return database connection to the pool
976
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
977
		}
978

    
979
		return exists;
980
	}
981
    
982
    /**
983
     * creates a system metadata mapping and adds additional fields from sysmeta
984
     * to the table for quick searching.
985
     * 
986
     * @param guid the id to insert
987
     * @param localId the systemMetadata object to get the local id for
988
     * @throws McdbDocNotFoundException 
989
     */
990
    public void createSystemMetadata(SystemMetadata sysmeta) throws McdbDocNotFoundException
991
    {
992
    	String guid = sysmeta.getIdentifier().getValue();
993
    	// insert the record
994
        insertSystemMetadata(guid);
995
        // update with the values
996
        updateSystemMetadata(sysmeta);
997
    }
998
        
999
    
1000
    /**
1001
     * update a mapping
1002
     * @param guid
1003
     * @param localId
1004
     */
1005
    public void updateMapping(String guid, String localId)
1006
    {
1007
    	
1008
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
1009
        int serialNumber = -1;
1010
        DBConnection dbConn = null;
1011
        try {
1012
            // Parse the localId into scope and rev parts
1013
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1014
            String docid = acc.getDocid();
1015
            int rev = 1;
1016
            if(acc.getRev() != null)
1017
            {
1018
              rev = (new Integer(acc.getRev()).intValue());
1019
            }
1020

    
1021
            // Get a database connection from the pool
1022
            dbConn = 
1023
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1024
            serialNumber = dbConn.getCheckOutSerialNumber();
1025

    
1026
            // Execute the update statement
1027
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid='" + guid + "'";
1028
            PreparedStatement stmt = dbConn.prepareStatement(query);
1029
            stmt.setString(1, docid);
1030
            stmt.setInt(2, rev);
1031
            int rows = stmt.executeUpdate();
1032

    
1033
            stmt.close();
1034
        } catch (SQLException e) {
1035
            e.printStackTrace();
1036
            logMetacat.error("SQL error while updating a mapping identifier: " 
1037
                    + e.getMessage());
1038
        } catch (NumberFormatException e) {
1039
            e.printStackTrace();
1040
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
1041
                    + e.getMessage());
1042
        } catch (AccessionNumberException e) {
1043
            e.printStackTrace();
1044
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
1045
                    + e.getMessage());
1046
        } finally {
1047
            // Return database connection to the pool
1048
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1049
        }
1050
        logMetacat.debug("done updating mapping");
1051
    }
1052
        
1053
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1054
            String checksum, String checksumAlgorithm, String originMemberNode,
1055
            String authoritativeMemberNode, long modifiedDate, String submitter, 
1056
            String guid, String objectFormat, BigInteger size, boolean replicationAllowed,
1057
            int numberReplicas, String obsoletes, String obsoletedBy)
1058
    {
1059
        DBConnection dbConn = null;
1060
        int serialNumber = -1;
1061
        
1062
        try {
1063
            // Get a database connection from the pool
1064
            dbConn = 
1065
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1066
            serialNumber = dbConn.getCheckOutSerialNumber();
1067

    
1068
            // Execute the insert statement
1069
            String query = "update " + TYPE_SYSTEM_METADATA + 
1070
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1071
                "origin_member_node, authoritive_member_node, date_modified, " +
1072
                "submitter, object_format, size, replication_allowed, number_replicas, obsoletes, obsoleted_by) " +
1073
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1074
            PreparedStatement stmt = dbConn.prepareStatement(query);
1075
            
1076
            //data values
1077
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1078
            stmt.setString(2, rightsHolder);
1079
            stmt.setString(3, checksum);
1080
            stmt.setString(4, checksumAlgorithm);
1081
            stmt.setString(5, originMemberNode);
1082
            stmt.setString(6, authoritativeMemberNode);
1083
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1084
            stmt.setString(8, submitter);
1085
            stmt.setString(9, objectFormat);
1086
            stmt.setString(10, size.toString());
1087
            stmt.setBoolean(11, replicationAllowed);
1088
            stmt.setInt(12, numberReplicas);
1089
            stmt.setString(13, obsoletes);
1090
            stmt.setString(14, obsoletedBy);
1091

    
1092
            //where clause
1093
            stmt.setString(15, guid);
1094
            logMetacat.debug("stmt: " + stmt.toString());
1095
            //execute
1096
            int rows = stmt.executeUpdate();
1097

    
1098
            stmt.close();
1099
        } catch (SQLException e) {
1100
            e.printStackTrace();
1101
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: " 
1102
                    + e.getMessage());
1103
        } catch (NumberFormatException e) {
1104
            e.printStackTrace();
1105
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: " 
1106
                    + e.getMessage());
1107
        } finally {
1108
            // Return database connection to the pool
1109
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1110
        }
1111
    }
1112
    
1113
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes)
1114
    {
1115
        DBConnection dbConn = null;
1116
        int serialNumber = -1;
1117
        
1118
        try {
1119
            // Get a database connection from the pool
1120
            dbConn = 
1121
                DBConnectionPool.getDBConnection("IdentifierManager.insertReplicationPolicy");
1122
            serialNumber = dbConn.getCheckOutSerialNumber();
1123

    
1124
            // remove existing values first
1125
            String delete = "delete from systemMetadataReplicationPolicy " + 
1126
            "where guid = ? and policy = ?";
1127
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1128
	        //data values
1129
	        stmt.setString(1, guid);
1130
	        stmt.setString(2, policy);
1131
	        //execute
1132
	        int deletedCount = stmt.executeUpdate();
1133
	        stmt.close();
1134
            
1135
            for (String memberNode: memberNodes) {
1136
	            // Execute the insert statement
1137
	            String insert = "insert into systemMetadataReplicationPolicy " + 
1138
	                "(guid, policy, member_node) " +
1139
	                "values (?, ?, ?)";
1140
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1141
	            
1142
	            //data values
1143
	            insertStatement.setString(1, guid);
1144
	            insertStatement.setString(2, policy);
1145
	            insertStatement.setString(3, memberNode);
1146
	            //execute
1147
	            int rows = insertStatement.executeUpdate();
1148
	            insertStatement.close();
1149
            }
1150
        } catch (SQLException e) {
1151
            logMetacat.error("SQL error while adding systemMetadataReplicationPolicy for: " + guid, e); 
1152
        } finally {
1153
            // Return database connection to the pool
1154
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1155
        }
1156
    }
1157
    
1158
    private void insertReplicationStatus(String guid, List<Replica> replicas) {
1159
        DBConnection dbConn = null;
1160
        int serialNumber = -1;
1161
        
1162
        try {
1163
            // Get a database connection from the pool
1164
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertReplicas");
1165
            serialNumber = dbConn.getCheckOutSerialNumber();
1166

    
1167
            // remove existing values first
1168
            String delete = "delete from systemMetadataReplicationStatus " + 
1169
            "where guid = ?";
1170
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1171
	        //data values
1172
	        stmt.setString(1, guid);
1173
	        //execute
1174
	        int deletedCount = stmt.executeUpdate();
1175
	        stmt.close();
1176
            
1177
	        if (replicas != null) {
1178
	            for (Replica replica: replicas) {
1179
		            // Execute the insert statement
1180
		            String insert = "insert into systemMetadataReplicationStatus " + 
1181
		                "(guid, member_node, status, date_verified) " +
1182
		                "values (?, ?, ?, ?)";
1183
		            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1184
		            
1185
		            //data values
1186
		            String memberNode = replica.getReplicaMemberNode().getValue();
1187
		            String status = replica.getReplicationStatus().toString();
1188
		            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1189
		            insertStatement.setString(1, guid);
1190
		            insertStatement.setString(2, memberNode);
1191
		            insertStatement.setString(3, status);
1192
		            insertStatement.setDate(4, sqlDate);
1193
	
1194
		            //execute
1195
		            int rows = insertStatement.executeUpdate();
1196
		            insertStatement.close();
1197
	            }
1198
	        }
1199
        } catch (SQLException e) {
1200
            logMetacat.error("SQL error while adding systemMetadataReplicationStatus for: " + guid, e); 
1201
        } finally {
1202
            // Return database connection to the pool
1203
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1204
        }
1205
    }
1206
    
1207
    /**
1208
     * Insert the system metadata fields into the db
1209
     * @param sm
1210
     * @throws McdbDocNotFoundException 
1211
     */
1212
    public void updateSystemMetadata(SystemMetadata sm) throws McdbDocNotFoundException {
1213
    	
1214
        Boolean replicationAllowed = false;
1215
		Integer numberReplicas = -1;
1216
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1217
    	if (replicationPolicy != null) {
1218
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1219
    		numberReplicas = replicationPolicy.getNumberReplicas();
1220
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1221
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1222
    	}
1223

    
1224
    	// the main systemMetadata fields
1225
		updateSystemMetadataFields(
1226
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1227
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(), 
1228
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(), 
1229
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm(), 
1230
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1231
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(), 
1232
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1233
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(), 
1234
        sm.getIdentifier().getValue(),
1235
        sm.getFmtid() == null ? null: sm.getFmtid().getValue(),
1236
        sm.getSize(),
1237
        replicationAllowed, 
1238
        numberReplicas,
1239
        sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
1240
        sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue());
1241
        
1242
        String guid = sm.getIdentifier().getValue();
1243
        
1244
        // save replication policies
1245
        if (replicationPolicy != null) {
1246
		    List<String> nodes = null;
1247
		    String policy = null;
1248
		    
1249
		    // check for null 
1250
		    if (replicationPolicy.getBlockedMemberNodeList() != null) {
1251
			    nodes = new ArrayList<String>();
1252
			    policy = "blocked";
1253
			    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1254
			    	nodes.add(node.getValue());
1255
			    }
1256
			    this.insertReplicationPolicy(guid, policy, nodes);
1257
		    }
1258
		    
1259
		    if (replicationPolicy.getPreferredMemberNodeList() != null) {
1260
			    nodes = new ArrayList<String>();
1261
			    policy = "preferred";
1262
			    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1263
			    	nodes.add(node.getValue());
1264
			    }
1265
		        this.insertReplicationPolicy(guid, policy, nodes);
1266
		    }
1267
        }
1268
        
1269
        // save replica information
1270
        this.insertReplicationStatus(guid, sm.getReplicaList());
1271
        
1272
        // save access policy
1273
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1274
        if (accessPolicy != null) {
1275
        	try {
1276
				this.insertAccessPolicy(guid, accessPolicy);
1277
			} catch (AccessException e) {
1278
				throw new McdbDocNotFoundException(e);
1279
			}
1280
        }
1281
    }
1282
    
1283
    /**
1284
     * Creates Metacat access rules and inserts them
1285
     * @param accessPolicy
1286
     * @throws McdbDocNotFoundException
1287
     * @throws AccessException
1288
     */
1289
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1290
    	
1291
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1292
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1293
        	List<Subject> subjects = accessRule.getSubjectList();
1294
        	List<Permission> permissions = accessRule.getPermissionList();
1295
        	for (Subject subject: subjects) {
1296
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1297
        		accessDAO.setPrincipalName(subject.getValue());
1298
    			accessDAO.setGuid(guid);
1299
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1300
    			accessDAO.setPermOrder(AccessControlInterface.DENYFIRST);
1301
    			for (Permission permission: permissions) {
1302
    				Long metacatPermission = new Long(convertPermission(permission));
1303
        			accessDAO.addPermission(metacatPermission);
1304
    			}
1305
    			accessDAOs.add(accessDAO);
1306
        	}
1307
        }
1308
        
1309
        // use GUID to update
1310
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1311
        accessController.replaceAccess(guid, accessDAOs);
1312
        
1313
        
1314
    }
1315
    
1316
    /**
1317
     * Lookup access policy from Metacat
1318
     * @param guid
1319
     * @return
1320
     * @throws McdbDocNotFoundException
1321
     * @throws AccessException
1322
     */
1323
    private AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1324
        AccessPolicy accessPolicy = new AccessPolicy();
1325

    
1326
    	// use GUID to look up the access
1327
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1328
    	List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1329
        for (XMLAccessDAO accessDAO: accessDAOs) {
1330
        	AccessRule accessRule = new AccessRule();    	
1331
        	Permission permission = convertPermission(accessDAO.getPermission().intValue());
1332
        	accessRule.addPermission(permission);
1333
        	Subject subject = new Subject();
1334
        	subject.setValue(accessDAO.getPrincipalName());
1335
        	accessRule.addSubject(subject);
1336
            accessPolicy.addAllow(accessRule);
1337
        }
1338
        return accessPolicy;
1339
    }
1340
    
1341
    public int convertPermission(Permission permission) {
1342
    	if (permission.equals(Permission.READ)) {
1343
    		return AccessControlInterface.READ;
1344
    	}
1345
    	if (permission.equals(Permission.WRITE)) {
1346
    		return AccessControlInterface.WRITE;
1347
    	}
1348
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1349
    		return AccessControlInterface.CHMOD;
1350
    	}
1351
		return -1;
1352
    }
1353
    
1354
    public Permission convertPermission(int permission) {
1355
    	if (permission == AccessControlInterface.READ) {
1356
    		return Permission.READ;
1357
    	}
1358
    	if (permission == AccessControlInterface.WRITE) {
1359
    		return Permission.WRITE;
1360
    	}
1361
    	if (permission == AccessControlInterface.CHMOD) {
1362
    		return Permission.CHANGE_PERMISSION;
1363
    	}
1364
		return null;
1365
    }
1366
    
1367
    /**
1368
     * Lookup a localId given the GUID. If
1369
     * the identifier is not found, throw an exception.
1370
     * 
1371
     * @param guid the global identifier to look up
1372
     * @return String containing the corresponding LocalId
1373
     * @throws McdbDocNotFoundException if the identifier is not found
1374
     */
1375
    public String getLocalId(String guid) throws McdbDocNotFoundException {
1376
      
1377
      String db_guid = "";
1378
      String docid = "";
1379
      int rev = 0;
1380
      
1381
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1382
      
1383
      DBConnection dbConn = null;
1384
      int serialNumber = -1;
1385
      try {
1386
          // Get a database connection from the pool
1387
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1388
          serialNumber = dbConn.getCheckOutSerialNumber();
1389
          
1390
          // Execute the insert statement
1391
          PreparedStatement stmt = dbConn.prepareStatement(query);
1392
          stmt.setString(1, guid);
1393
          ResultSet rs = stmt.executeQuery();
1394
          if (rs.next()) {
1395
              db_guid = rs.getString(1);
1396
              docid = rs.getString(2);
1397
              rev = rs.getInt(3);
1398
              assert(db_guid.equals(guid));
1399
          } else {
1400
              throw new McdbDocNotFoundException("Document not found:" + guid);
1401
          }
1402
          stmt.close();
1403
      } catch (SQLException e) {
1404
          logMetacat.error("Error while looking up the local identifier: " 
1405
                  + e.getMessage());
1406
      } finally {
1407
          // Return database connection to the pool
1408
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1409
      }
1410
      return docid + "." + rev;
1411
    }
1412
    
1413
    /**
1414
     * query the systemmetadata table based on the given parameters
1415
     * @param startTime
1416
     * @param endTime
1417
     * @param objectFormat
1418
     * @param replicaStatus
1419
     * @param start
1420
     * @param count
1421
     * @return ObjectList
1422
     * @throws SQLException 
1423
     * @throws ServiceException 
1424
     * @throws PropertyNotFoundException 
1425
     */
1426
    public ObjectList querySystemMetadata(Date startTime, Date endTime, 
1427
            ObjectFormatIdentifier objectFormatId, boolean replicaStatus, int start, int count) throws SQLException, PropertyNotFoundException, ServiceException
1428
    {
1429
        ObjectList ol = new ObjectList();
1430
        int total = 0;
1431
        DBConnection dbConn = null;
1432
        int serialNumber = -1;
1433
        
1434
        try {
1435
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
1436
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
1437
                "date_modified, submitter, object_format, size from systemmetadata";
1438
            
1439
            boolean f1 = false;
1440
            boolean f2 = false;
1441
            boolean f3 = false;
1442
            
1443
            if (startTime != null) {
1444
                sql += " where systemmetadata.date_modified > ?";
1445
                f1 = true;
1446
            }
1447
            
1448
            if (endTime != null) {
1449
                if (!f1) {
1450
                    sql += " where systemmetadata.date_modified < ?";
1451
                }
1452
                else {
1453
                    sql += " and systemmetadata.date_modified < ?";
1454
                }
1455
                f2 = true;
1456
            }
1457
            
1458
            if (objectFormatId != null) {
1459
                if (!f1 && !f2) {
1460
                    sql += " where object_format = ?";
1461
                }
1462
                else {
1463
                    sql += " and object_format = ?";
1464
                }
1465
                f3 = true;
1466
            }
1467
            
1468
            if (replicaStatus) {
1469
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
1470
                if (!f1 && !f2 && !f3) {
1471
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
1472
                }
1473
                else {
1474
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
1475
                }
1476
            }
1477
            
1478
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1479
            serialNumber = dbConn.getCheckOutSerialNumber();
1480
            PreparedStatement stmt = dbConn.prepareStatement(sql);
1481
            
1482
            if (f1 && f2 && f3) {
1483
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1484
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1485
                stmt.setString(3, objectFormatId.getValue());
1486
            }
1487
            else if (f1 && f2 && !f3) {
1488
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1489
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1490
            }
1491
            else if (f1 && !f2 && f3) {
1492
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1493
                stmt.setString(2, objectFormatId.getValue());
1494
            }
1495
            else if (f1 && !f2 && !f3) {
1496
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1497
            }
1498
            else if (!f1 && f2 && f3) {
1499
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1500
                stmt.setString(2, objectFormatId.getValue());
1501
            }
1502
            else if (!f1 && !f2 && f3) {
1503
                stmt.setString(1, objectFormatId.getValue());
1504
            }
1505
            else if (!f1 && f2 && !f3) {
1506
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1507
            }
1508
            
1509
            //logMetacat.debug("LISTOBJECTS QUERY: " + stmt.toString());
1510
            
1511
            ResultSet rs = stmt.executeQuery();
1512
            for (int i=0; i<start; i++) {
1513
                if (rs.next()) {
1514
                    total++;
1515
                } else {
1516
                    break;
1517
                }
1518
            }
1519
            
1520
            int countIndex = 0;
1521
                        
1522
            while (rs.next()) {
1523
                total++;
1524
                if (countIndex >= count) {
1525
                	// allow unlimited (negative number for count)
1526
                	if (count > 0) {
1527
                		break;
1528
                	}
1529
                }
1530
                                
1531
                String guid = rs.getString(1);
1532
                //logMetacat.debug("query found doc with guid " + guid);
1533
                //Timestamp dateUploaded = rs.getTimestamp(2);
1534
                //String rightsHolder = rs.getString(3);
1535
                String checksum = rs.getString(4);
1536
                String checksumAlgorithm = rs.getString(5);
1537
                //String originMemberNode = rs.getString(6);
1538
                //String authoritiveMemberNode = rs.getString(7);
1539
                Timestamp dateModified = rs.getTimestamp(8);
1540
                //String submitter = rs.getString(9);
1541
                String fmtidStr = rs.getString(10);
1542
                String sz = rs.getString(11);
1543
                BigInteger size = new BigInteger("0");
1544
                
1545
                if (sz != null && !sz.trim().equals("")) {
1546
                    size = new BigInteger(rs.getString(11));
1547
                }
1548
                
1549
                ObjectInfo oi = new ObjectInfo();
1550
                
1551
                Identifier id = new Identifier();
1552
                id.setValue(guid);
1553
                oi.setIdentifier(id);
1554
                
1555
                if (dateModified != null) {
1556
                	oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
1557
                }
1558
                
1559
                Checksum cs = new Checksum();
1560
                cs.setValue(checksum);
1561
                try {
1562
                	//cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1563
                    cs.setAlgorithm(checksumAlgorithm);
1564
                } catch (Exception e) {
1565
					logMetacat.error("could not parse checksum algorithm", e);
1566
					continue;
1567
				}
1568
                oi.setChecksum(cs);
1569
                
1570
                // set the format type
1571
                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
1572
            	fmtid.setValue(fmtidStr);
1573
                oi.setFmtid(fmtid);
1574
                
1575
//                try {
1576
//	                oi.setFmtid(ObjectFormatCache.getInstance().getFormat(fmtidStr).getFmtid());
1577
//                } catch (NotFound e) {
1578
//                	logMetacat.error("could not find object format: " + fmtidStr, e);
1579
//                	// skip this one
1580
//                	continue;
1581
//				}
1582
                                
1583
                oi.setSize(size);
1584
                
1585
                ol.addObjectInfo(oi);
1586
                countIndex++;
1587
            }
1588
            
1589
            // expend the resultset to get the total count of possible rows
1590
            while (rs.next()) { 
1591
                total++;
1592
            }
1593
        }
1594
        
1595
        finally {
1596
            // Return database connection to the pool
1597
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1598
        }
1599
        
1600
        ol.setStart(start);
1601
        ol.setCount(ol.sizeObjectInfoList());
1602
        ol.setTotal(total);
1603
        
1604
        return ol;
1605
    }
1606
    
1607
    /**
1608
     * create a mapping in the identifier table
1609
     * @param guid
1610
     * @param localId
1611
     */
1612
    public void createMapping(String guid, String localId)
1613
    {        
1614
        
1615
        int serialNumber = -1;
1616
        DBConnection dbConn = null;
1617
        try {
1618

    
1619
            // Parse the localId into scope and rev parts
1620
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1621
            String docid = acc.getDocid();
1622
            int rev = 1;
1623
            if (acc.getRev() != null) {
1624
              rev = (new Integer(acc.getRev()).intValue());
1625
            }
1626

    
1627
            // Get a database connection from the pool
1628
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1629
            serialNumber = dbConn.getCheckOutSerialNumber();
1630

    
1631
            // Execute the insert statement
1632
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1633
            PreparedStatement stmt = dbConn.prepareStatement(query);
1634
            stmt.setString(1, guid);
1635
            stmt.setString(2, docid);
1636
            stmt.setInt(3, rev);
1637
            logMetacat.debug("mapping query: " + stmt.toString());
1638
            int rows = stmt.executeUpdate();
1639

    
1640
            stmt.close();
1641
        } catch (SQLException e) {
1642
            e.printStackTrace();
1643
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1644
                    + e.getMessage());
1645
        } catch (NumberFormatException e) {
1646
            e.printStackTrace();
1647
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1648
                    + e.getMessage());
1649
        } catch (AccessionNumberException e) {
1650
            e.printStackTrace();
1651
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1652
                    + e.getMessage());
1653
        } finally {
1654
            // Return database connection to the pool
1655
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1656
        }
1657
    }
1658
    
1659
    /**
1660
     * create the systemmetadata record
1661
     * @param guid
1662
     */
1663
    private void insertSystemMetadata(String guid)
1664
    {        
1665
        
1666
        int serialNumber = -1;
1667
        DBConnection dbConn = null;
1668
        try {
1669

    
1670
            // Get a database connection from the pool
1671
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1672
            serialNumber = dbConn.getCheckOutSerialNumber();
1673

    
1674
            // Execute the insert statement
1675
            String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1676
            PreparedStatement stmt = dbConn.prepareStatement(query);
1677
            stmt.setString(1, guid);
1678
            logMetacat.debug("system metadata query: " + stmt.toString());
1679
            int rows = stmt.executeUpdate();
1680

    
1681
            stmt.close();
1682
        } catch (Exception e) {
1683
            e.printStackTrace();
1684
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1685
        } finally {
1686
            // Return database connection to the pool
1687
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1688
        }
1689
    }
1690
    
1691
    private void deleteSystemMetadata(String guid)
1692
    {        
1693
        
1694
        int serialNumber = -1;
1695
        DBConnection dbConn = null;
1696
        try {
1697

    
1698
            // Get a database connection from the pool
1699
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1700
            serialNumber = dbConn.getCheckOutSerialNumber();
1701

    
1702
            // Execute the statement
1703
            String query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
1704
            PreparedStatement stmt = dbConn.prepareStatement(query);
1705
            stmt.setString(1, guid);
1706
            logMetacat.debug("delete system metadata: " + stmt.toString());
1707
            int rows = stmt.executeUpdate();
1708

    
1709
            stmt.close();
1710
        } catch (Exception e) {
1711
            e.printStackTrace();
1712
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1713
        } finally {
1714
            // Return database connection to the pool
1715
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1716
        }
1717
    }
1718
}
1719

    
(37-37/65)