Project

General

Profile

1 5282 jones
/**
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 6384 cjones
import java.math.BigInteger;
28 5282 jones
import java.sql.PreparedStatement;
29
import java.sql.ResultSet;
30
import java.sql.SQLException;
31 5895 berkley
import java.sql.Timestamp;
32 6107 leinfelder
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 5282 jones
38
import org.apache.log4j.Logger;
39 6124 cjones
import org.dataone.client.ObjectFormatCache;
40
import org.dataone.service.exceptions.NotFound;
41 6366 leinfelder
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 5282 jones
57 6108 leinfelder
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlInterface;
58
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
59
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
60 5282 jones
import edu.ucsb.nceas.metacat.database.DBConnection;
61
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
62 5887 berkley
import edu.ucsb.nceas.metacat.properties.PropertyService;
63 6108 leinfelder
import edu.ucsb.nceas.metacat.shared.AccessException;
64 6299 leinfelder
import edu.ucsb.nceas.metacat.shared.ServiceException;
65 5286 jones
import edu.ucsb.nceas.metacat.util.DocumentUtil;
66 6299 leinfelder
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
67 5282 jones
68
/**
69
 * Manage the relationship between Metacat local identifiers (LocalIDs) that are
70 6099 leinfelder
 * codified as the (docid, rev) pair with globally unique string identifiers
71 5282 jones
 * (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 5334 berkley
    public static final String TYPE_SYSTEM_METADATA = "systemmetadata";
80
    public static final String TYPE_IDENTIFIER = "identifier";
81
82 5282 jones
    /**
83
     * The single instance of the manager that is always returned.
84
     */
85
    private static IdentifierManager self = null;
86 6099 leinfelder
    private Logger logMetacat = Logger.getLogger(IdentifierManager.class);
87 5282 jones
88
    /**
89
     * A private constructor that initializes the class when getInstance() is
90
     * called.
91
     */
92 6099 leinfelder
    private IdentifierManager() {}
93 5282 jones
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 6097 leinfelder
    public SystemMetadata asSystemMetadata(Date dateUploaded, String rightsHolder,
109
            String checksum, String checksumAlgorithm, String originMemberNode,
110
            String authoritativeMemberNode, Date dateModified, String submitter,
111 6384 cjones
            String guid, String fmtidStr, BigInteger size) {
112 6097 leinfelder
        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 6397 leinfelder
        checksumObject.setAlgorithm(checksumAlgorithm);
124 6097 leinfelder
        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 6124 cjones
        try {
136 6384 cjones
        	ObjectFormatIdentifier fmtid =
137
        		ObjectFormatCache.getInstance().getFormat(fmtidStr).getFmtid();
138
        	sysMeta.setFmtid(fmtid);
139 6124 cjones
        } catch (NotFound nfe) {
140 6296 cjones
          logMetacat.error("The objectFormat " + fmtidStr +
141 6384 cjones
          	" is not registered. Setting the default format id.");
142 6124 cjones
          ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
143
          fmtid.setValue("application/octet-stream");
144 6384 cjones
          sysMeta.setFmtid(fmtid);
145 6124 cjones
        }
146 6097 leinfelder
        sysMeta.setSize(size);
147
148
        return sysMeta;
149
    }
150
151 5282 jones
    /**
152 5895 berkley
     * 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 5944 berkley
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size " +
171 5895 berkley
          "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 5917 berkley
                String objectFormat = rs.getString(10);
196
                long size = new Long(rs.getString(11)).longValue();
197 5895 berkley
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 5917 berkley
                h.put("object_format", objectFormat);
208
                h.put("size", new Long(size).toString());
209 5895 berkley
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 6097 leinfelder
     * return a hash of all of the info that is in the systemmetadata table
236 6099 leinfelder
     * @param guid
237 6097 leinfelder
     * @return
238 6108 leinfelder
     * @throws McdbDocNotFoundException
239 6097 leinfelder
     */
240 6099 leinfelder
    public SystemMetadata getSystemMetadata(String guid)
241 6097 leinfelder
    	throws McdbDocNotFoundException
242
    {
243 6099 leinfelder
244 6097 leinfelder
        SystemMetadata sysMeta = new SystemMetadata();
245
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
246 6375 leinfelder
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size, " +
247
          "obsoletes, obsoleted_by " +
248 6099 leinfelder
          "from systemmetadata where guid = ?";
249 6097 leinfelder
        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 6099 leinfelder
            stmt.setString(1, guid);
260 6097 leinfelder
            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 6296 cjones
                String fmtidStr = rs.getString(10);
272 6384 cjones
                BigInteger size = new BigInteger(rs.getString(11));
273 6375 leinfelder
                String obsoletes = rs.getString(12);
274
                String obsoletedBy = rs.getString(13);
275
276 6097 leinfelder
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 6397 leinfelder
                checksumObject.setAlgorithm(checksumAlgorithm);
287 6097 leinfelder
                sysMeta.setChecksum(checksumObject);
288
                NodeReference omn = new NodeReference();
289
                omn.setValue(originMemberNode);
290
                sysMeta.setOriginMemberNode(omn);
291
                NodeReference amn = new NodeReference();
292
                amn.setValue(authoritativeMemberNode);
293
                sysMeta.setAuthoritativeMemberNode(amn);
294
                sysMeta.setDateSysMetadataModified(dateModified);
295
                Subject submitterSubject = new Subject();
296
                submitterSubject.setValue(submitter);
297
                sysMeta.setSubmitter(submitterSubject);
298 6124 cjones
                try {
299 6384 cjones
                	ObjectFormatIdentifier fmtid =
300
                		ObjectFormatCache.getInstance().getFormat(fmtidStr).getFmtid();
301
                	sysMeta.setFmtid(fmtid);
302 6124 cjones
                } catch (NotFound nfe) {
303 6296 cjones
                  logMetacat.error("The objectFormat " + fmtidStr +
304 6384 cjones
                  	" is not registered. Setting the default format id.");
305 6124 cjones
                  ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
306
                  fmtid.setValue("application/octet-stream");
307 6384 cjones
                  sysMeta.setFmtid(fmtid);
308 6124 cjones
                }
309 6097 leinfelder
                sysMeta.setSize(size);
310 6423 leinfelder
                if (obsoletes != null) {
311
	                Identifier obsoletesId = new Identifier();
312
	                obsoletesId.setValue(obsoletes);
313
	                sysMeta.setObsoletes(obsoletesId);
314
                }
315
                if (obsoletedBy != null) {
316
		            Identifier obsoletedById = new Identifier();
317
		            obsoletedById.setValue(obsoletedBy);
318
		            sysMeta.setObsoletedBy(obsoletedById);
319
                }
320 6097 leinfelder
                stmt.close();
321
            }
322
            else
323
            {
324
                stmt.close();
325
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
326 6099 leinfelder
                throw new McdbDocNotFoundException("Could not find " + guid);
327 6097 leinfelder
            }
328
329
        }
330
        catch (SQLException e)
331
        {
332
            e.printStackTrace();
333 6099 leinfelder
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "
334 6097 leinfelder
                    + e.getMessage());
335
        }
336
        finally
337
        {
338
            // Return database connection to the pool
339
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
340
        }
341 6377 leinfelder
342 6107 leinfelder
        // look up replication policy
343
        ReplicationPolicy replicationPolicy = new ReplicationPolicy();
344
        replicationPolicy.setBlockedMemberNodeList(getReplicationPolicy(guid, "blocked"));
345
        replicationPolicy.setPreferredMemberNodeList(getReplicationPolicy(guid, "preferred"));
346
		sysMeta.setReplicationPolicy(replicationPolicy);
347
348
		// look up replication status
349
		sysMeta.setReplicaList(getReplicationStatus(guid));
350 6108 leinfelder
351
		// look up access policy
352
		try {
353
			sysMeta.setAccessPolicy(getAccessPolicy(guid));
354
		} catch (AccessException e) {
355
			throw new McdbDocNotFoundException(e);
356
		}
357 6107 leinfelder
358 6097 leinfelder
        return sysMeta;
359
    }
360
361
362 6107 leinfelder
    private List<NodeReference> getReplicationPolicy(String guid, String policy)
363
		throws McdbDocNotFoundException {
364
365
		List<NodeReference> nodes = new ArrayList<NodeReference>();
366
		String sql = "select guid, policy, member_node " +
367
			"from systemMetadataReplicationPolicy where guid = ? and policy = ?";
368
	    DBConnection dbConn = null;
369
	    int serialNumber = -1;
370
	    try {
371
	        // Get a database connection from the pool
372
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicationPolicy");
373
	        serialNumber = dbConn.getCheckOutSerialNumber();
374
375
	        // Execute the statement
376
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
377
	        stmt.setString(1, guid);
378
	        stmt.setString(2, policy);
379
	        ResultSet rs = stmt.executeQuery();
380
	        while (rs.next())
381
	        {
382
	            String memberNode = rs.getString(3);
383
	            NodeReference node = new NodeReference();
384
	            node.setValue(memberNode);
385
	            nodes.add(node);
386
387
	        }
388
	        stmt.close();
389
390
	    } catch (SQLException e) {
391
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
392
	    }
393
	    finally {
394
	        // Return database connection to the pool
395
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
396
	    }
397
398
	    return nodes;
399
	}
400 6097 leinfelder
401 6107 leinfelder
    private List<Replica> getReplicationStatus(String guid) throws McdbDocNotFoundException {
402
403
		List<Replica> replicas = new ArrayList<Replica>();
404
		String sql = "select guid, member_node, status, date_verified " +
405
			"from systemMetadataReplicationStatus where guid = ?";
406
	    DBConnection dbConn = null;
407
	    int serialNumber = -1;
408
	    try {
409
	        // Get a database connection from the pool
410
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicas");
411
	        serialNumber = dbConn.getCheckOutSerialNumber();
412
413
	        // Execute the statement
414
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
415
	        stmt.setString(1, guid);
416
	        ResultSet rs = stmt.executeQuery();
417
	        while (rs.next())
418
	        {
419
	            String memberNode = rs.getString(2);
420
	            String status = rs.getString(3);
421
	            java.sql.Date verified = rs.getDate(4);
422
423
	            Replica replica = new Replica();
424
	            NodeReference node = new NodeReference();
425
	            node.setValue(memberNode);
426
	            replica.setReplicaMemberNode(node);
427 6454 leinfelder
	            replica.setReplicationStatus(ReplicationStatus.valueOf(status));
428 6107 leinfelder
	            replica.setReplicaVerified(new Date(verified.getTime()));
429
	            replicas.add(replica);
430
	        }
431
	        stmt.close();
432
433
	    } catch (SQLException e) {
434
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
435
	    }
436
	    finally {
437
	        // Return database connection to the pool
438
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
439
	    }
440
441
	    return replicas;
442
	}
443
444 6097 leinfelder
    /**
445 5378 berkley
     * return information on the document with localId.  These are the fields
446
     * from the xml_documents table.  They can be used to contstruct metadata
447
     * about the object that is stored.
448
     * @param localId
449
     * @return
450
     * @throws McdbDocNotFoundException
451
     */
452 5441 berkley
    public Hashtable<String, Object> getDocumentInfo(String localId)
453 5378 berkley
        throws McdbDocNotFoundException
454
    {
455 5798 berkley
        try
456
        {
457
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
458
            localId = acc.getDocid();
459
        }
460
        catch(Exception e)
461
        {
462
            //do nothing. just try the localId as it is
463
        }
464 5441 berkley
        Hashtable<String, Object> h = new Hashtable<String, Object>();
465 5378 berkley
        String sql = "select docname, doctype, user_owner, user_updated, " +
466
            "server_location, rev, date_created, date_updated from " +
467
            "xml_documents where docid like '" + localId + "'";
468
        DBConnection dbConn = null;
469
        int serialNumber = -1;
470
        try
471
        {
472
            // Get a database connection from the pool
473
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
474
            serialNumber = dbConn.getCheckOutSerialNumber();
475
476
            // Execute the insert statement
477
            PreparedStatement stmt = dbConn.prepareStatement(sql);
478
            ResultSet rs = stmt.executeQuery();
479
            if (rs.next())
480
            {
481
                String docname = rs.getString(1);
482
                String doctype = rs.getString(2);
483
                String user_owner = rs.getString(3);
484
                String user_updated = rs.getString(4);
485
                String server_location = rs.getString(5);
486
                int rev = rs.getInt(6);
487
                String date_created = rs.getString(7);
488
                String date_updated = rs.getString(8);
489 6042 cjones
                h.put("docid", localId);
490 5378 berkley
                h.put("docname", docname);
491
                h.put("doctype", doctype);
492
                h.put("user_owner", user_owner);
493
                h.put("user_updated", user_updated);
494
                h.put("server_location", server_location);
495
                h.put("rev", new Integer(rev).toString());
496
                h.put("date_created", date_created);
497
                h.put("date_updated", date_updated);
498
499
                stmt.close();
500
            }
501
            else
502
            {
503
                stmt.close();
504
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
505 5798 berkley
                throw new McdbDocNotFoundException("2Could not find document " + localId);
506 5378 berkley
            }
507 5441 berkley
508 5444 berkley
            String sql2 = "select principal_name, permission, perm_type, perm_order from xml_access " +
509 5441 berkley
            "where docid like '" + localId + "'";
510 6099 leinfelder
            logMetacat.debug("executing sql: " + sql2);
511 5441 berkley
            PreparedStatement stmt2 = dbConn.prepareStatement(sql2);
512 5442 berkley
            rs = stmt2.executeQuery();
513 5441 berkley
            Vector accessVector = new Vector();
514 5445 berkley
            while(rs.next())
515 5441 berkley
            {
516
                Hashtable accessHash = new Hashtable();
517
                String principal_name = rs.getString(1);
518
                String permission = rs.getString(2);
519
                String permissionType = rs.getString(3);
520
                String permissionOrder = rs.getString(4);
521
                accessHash.put("principal_name", principal_name);
522
                accessHash.put("permission", permission);
523
                accessHash.put("permission_type", permissionType);
524
                accessHash.put("permission_order", permissionOrder);
525 6099 leinfelder
                logMetacat.debug("accessHash: " + accessHash.toString());
526 5441 berkley
                accessVector.add(accessHash);
527
            }
528
            h.put("access", accessVector);
529 5378 berkley
        }
530
        catch (SQLException e)
531
        {
532 5444 berkley
            e.printStackTrace();
533 5378 berkley
            logMetacat.error("Error while getting document info for localid " + localId + " : "
534
                    + e.getMessage());
535
        }
536
        finally
537
        {
538
            // Return database connection to the pool
539
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
540
        }
541
        return h;
542
    }
543
544
    /**
545
     * return the newest rev for a given localId
546
     * @param localId
547
     * @return
548
     */
549
    public int getLatestRevForLocalId(String localId)
550
        throws McdbDocNotFoundException
551
    {
552 5798 berkley
        try
553
        {
554
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
555
            localId = acc.getDocid();
556
        }
557
        catch(Exception e)
558
        {
559
            //do nothing. just try the localId as it is
560
        }
561 5378 berkley
        int rev = 0;
562
        String sql = "select rev from xml_documents where docid like '" + localId + "'";
563
        DBConnection dbConn = null;
564
        int serialNumber = -1;
565
        try
566
        {
567
            // Get a database connection from the pool
568
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLatestRevForLocalId");
569
            serialNumber = dbConn.getCheckOutSerialNumber();
570
571
            // Execute the insert statement
572
            PreparedStatement stmt = dbConn.prepareStatement(sql);
573
            ResultSet rs = stmt.executeQuery();
574
            if (rs.next())
575
            {
576
                rev = rs.getInt(1);
577
                stmt.close();
578
            }
579
            else
580
            {
581
                stmt.close();
582
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
583 5798 berkley
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
584 5378 berkley
            }
585
        }
586
        catch (SQLException e)
587
        {
588
            logMetacat.error("Error while looking up the guid: "
589
                    + e.getMessage());
590
        }
591
        finally
592
        {
593
            // Return database connection to the pool
594
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
595
        }
596
        return rev;
597
    }
598
599
    /**
600 5377 berkley
     * return all local ids in the object store that do not have associated
601 6099 leinfelder
     * system metadata
602 5377 berkley
     */
603
    public List<String> getLocalIdsWithNoSystemMetadata()
604
    {
605
        Vector<String> ids = new Vector<String>();
606 6099 leinfelder
        String sql = "select docid, rev from xml_documents " +
607
        		"where docid not in " +
608
        		"(select docid from identifier where guid in (select guid from systemmetadata)))";
609 5377 berkley
        DBConnection dbConn = null;
610
        int serialNumber = -1;
611
        try
612
        {
613
            // Get a database connection from the pool
614
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
615
            serialNumber = dbConn.getCheckOutSerialNumber();
616
617
            // Execute the insert statement
618
            PreparedStatement stmt = dbConn.prepareStatement(sql);
619
            ResultSet rs = stmt.executeQuery();
620
            while (rs.next())
621
            {
622
                String localid = rs.getString(1);
623 5798 berkley
                String rev = rs.getString(2);
624
                localid += "." + rev;
625 6099 leinfelder
                logMetacat.debug("id to add SM for: " + localid);
626 5377 berkley
                ids.add(localid);
627
            }
628
            stmt.close();
629
        }
630
        catch (SQLException e)
631
        {
632
            logMetacat.error("Error while looking up the guid: "
633
                    + e.getMessage());
634
        }
635
        finally
636
        {
637
            // Return database connection to the pool
638
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
639
        }
640
641
        return ids;
642
    }
643
644
    /**
645
     * return a listing of all local ids in the object store
646
     * @return a list of all local ids in metacat
647
     */
648
    public List<String> getAllLocalIds()
649 6416 rnahf
    // seems to be an unnecessary and restrictive throw -rnahf 13-Sep-2011
650
    //    throws Exception
651 5377 berkley
    {
652
        Vector<String> ids = new Vector<String>();
653
        String sql = "select docid from xml_documents";
654
        DBConnection dbConn = null;
655
        int serialNumber = -1;
656
        try
657
        {
658
            // Get a database connection from the pool
659
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
660
            serialNumber = dbConn.getCheckOutSerialNumber();
661
662
            // Execute the insert statement
663
            PreparedStatement stmt = dbConn.prepareStatement(sql);
664
            ResultSet rs = stmt.executeQuery();
665
            while (rs.next())
666
            {
667
                String localid = rs.getString(1);
668
                ids.add(localid);
669
            }
670
            stmt.close();
671
        }
672
        catch (SQLException e)
673
        {
674
            logMetacat.error("Error while looking up the guid: "
675
                    + e.getMessage());
676
        }
677
        finally
678
        {
679
            // Return database connection to the pool
680
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
681
        }
682
        return ids;
683
    }
684
685 6416 rnahf
686 6118 leinfelder
    /**
687 6416 rnahf
     * return a listing of all guids in the object store
688
     * @return a list of all GUIDs in metacat
689
     */
690
    public List<String> getAllGUIDs()
691
    {
692
        Vector<String> guids = new Vector<String>();
693
        String sql = "select guid from identifier";
694
        DBConnection dbConn = null;
695
        int serialNumber = -1;
696
        try
697
        {
698
            // Get a database connection from the pool
699
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllGUIDs");
700
            serialNumber = dbConn.getCheckOutSerialNumber();
701
702
            // Execute the insert statement
703
            PreparedStatement stmt = dbConn.prepareStatement(sql);
704
            ResultSet rs = stmt.executeQuery();
705
            while (rs.next())
706
            {
707
                String guid = rs.getString(1);
708
                guids.add(guid);
709
            }
710
            stmt.close();
711
        }
712
        catch (SQLException e)
713
        {
714
            logMetacat.error("Error while retrieving the guid: "
715
                    + e.getMessage());
716
        }
717
        finally
718
        {
719
            // Return database connection to the pool
720
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
721
        }
722
        return guids;
723
    }
724
725
726
727
    /**
728 6118 leinfelder
     * returns a list of system metadata-only guids since the given date
729
     * @return a list of system ids in metacat that do not correspond to objects
730
     * TODO: need to check which server they are on
731
     */
732
    public List<String> getUpdatedSystemMetadataIds(Date since)
733
       throws Exception
734
    {
735
        List<String> ids = new Vector<String>();
736
        String sql =
737
        	"select guid from " + TYPE_SYSTEM_METADATA +
738
        	" where guid not in " +
739
        	" (select guid from " + TYPE_IDENTIFIER + ") " +
740
        	" and date_modified > ?";
741
        DBConnection dbConn = null;
742
        int serialNumber = -1;
743
        try
744
        {
745
            // Get a database connection from the pool
746
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getUpdatedSystemMetadataIds");
747
            serialNumber = dbConn.getCheckOutSerialNumber();
748 6099 leinfelder
749 6118 leinfelder
            // Execute the insert statement
750
            PreparedStatement stmt = dbConn.prepareStatement(sql);
751
            stmt.setDate(1, new java.sql.Date(since.getTime()));
752
            ResultSet rs = stmt.executeQuery();
753
            while (rs.next())
754
            {
755
                String guid = rs.getString(1);
756
                ids.add(guid);
757
            }
758
            stmt.close();
759
        }
760
        catch (SQLException e)
761
        {
762
            logMetacat.error("Error while looking up the updated guids: "
763
                    + e.getMessage());
764
        }
765
        finally
766
        {
767
            // Return database connection to the pool
768
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
769
        }
770
        return ids;
771
    }
772 5282 jones
773 6459 leinfelder
    /**
774
     * returns a list of system metadata-only guids since the given date
775
     * @return a list of system ids in metacat that do not correspond to objects
776
     * TODO: need to check which server they are on
777
     */
778
    public Date getLastModifiedDate() throws Exception {
779
        Date maxDate = null;
780 6118 leinfelder
781 6459 leinfelder
        List<String> ids = new Vector<String>();
782
        String sql =
783
        	"select max(date_modified) from " + TYPE_SYSTEM_METADATA;
784
        DBConnection dbConn = null;
785
        int serialNumber = -1;
786
        try
787
        {
788
            // Get a database connection from the pool
789
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLastModifiedDate");
790
            serialNumber = dbConn.getCheckOutSerialNumber();
791
792
            // Execute the insert statement
793
            PreparedStatement stmt = dbConn.prepareStatement(sql);
794
            ResultSet rs = stmt.executeQuery();
795
            if (rs.next()) {
796
            	maxDate = rs.getDate(1);
797
            }
798
            stmt.close();
799
        }
800
        catch (SQLException e)
801
        {
802
            logMetacat.error("Error while looking up the latest update date: "
803
                    + e.getMessage());
804
        }
805
        finally
806
        {
807
            // Return database connection to the pool
808
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
809
        }
810
        return maxDate;
811
    }
812
813 6118 leinfelder
814 5282 jones
    /**
815
     * Determine if an identifier exists already, returning true if so.
816
     *
817
     * @param guid the global identifier to look up
818
     * @return boolean true if the identifier exists
819
     */
820
    public boolean identifierExists(String guid)
821
    {
822
        boolean idExists = false;
823
        try {
824
            String id = getLocalId(guid);
825
            if (id != null) {
826
                idExists = true;
827
            }
828
        } catch (McdbDocNotFoundException e) {
829 6123 leinfelder
        	// try system metadata only
830
        	try {
831 6416 rnahf
        		idExists = systemMetadataExists(guid);
832 6454 leinfelder
            } catch (Exception e2) {
833 6123 leinfelder
            	idExists = false;
834
            }
835 5282 jones
        }
836
        return idExists;
837
    }
838
839
    /**
840
     *
841 5453 berkley
     * @param guid
842
     * @param rev
843
     * @return
844
     */
845
    public String generateLocalId(String guid, int rev)
846
    {
847
        return generateLocalId(guid, rev, false);
848
    }
849 5286 jones
850
    /**
851
     * Given a global identifier (guid), create a suitable local identifier that
852
     * follows Metacat's docid semantics and format (scope.id.rev), and create
853
     * a mapping between these two identifiers.  This effectively reserves both
854
     * the global and the local identifier, as they will now be present in the
855
     * identifier mapping table.  If the incoming guid has the syntax of a
856
     * Metacat docid (scope.id.rev), then simply use it.
857
     *
858
     * @param guid the global string identifier
859
     * @param rev the revision number to be used in the localId
860
     * @return String containing the localId to be used for Metacat operations
861
     */
862 5453 berkley
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata)
863 5286 jones
    {
864
        String localId = "";
865
        boolean conformsToDocidFormat = false;
866
867
        // Check if the guid passed in is already in docid (scope.id.rev) format
868
        try {
869
            AccessionNumber acc = new AccessionNumber(guid, "NONE");
870
            if (new Integer(acc.getRev()).intValue() > 0) {
871
                conformsToDocidFormat = true;
872
            }
873
        } catch (NumberFormatException e) {
874
            // No action needed, simply detecting invalid AccessionNumbers
875
        } catch (AccessionNumberException e) {
876
            // No action needed, simply detecting invalid AccessionNumbers
877
        } catch (SQLException e) {
878
            // No action needed, simply detecting invalid AccessionNumbers
879
        }
880
881
        if (conformsToDocidFormat) {
882
            // if it conforms, use it for both guid and localId
883
            localId = guid;
884
        } else {
885
            // if not, then generate a new unique localId
886
            localId = DocumentUtil.generateDocumentId(rev);
887
        }
888
889
        // Register this new pair in the identifier mapping table
890 6099 leinfelder
        logMetacat.debug("creating mapping in generateLocalId");
891 5453 berkley
        if(!isSystemMetadata)
892
        { //don't do this if we're generating for system metadata
893
            createMapping(guid, localId);
894
        }
895 5286 jones
896
        return localId;
897
    }
898 5322 berkley
899
    /**
900
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
901 5452 berkley
     * if the docid, rev is not found in the identifiers or systemmetadata tables
902 5322 berkley
     *
903
     * @param docid the docid to look up
904
     * @param rev the revision of the docid to look up
905
     * @return String containing the mapped guid
906
     * @throws McdbDocNotFoundException if the docid, rev is not found
907
     */
908
    public String getGUID(String docid, int rev)
909
      throws McdbDocNotFoundException
910
    {
911 6099 leinfelder
        logMetacat.debug("getting guid for " + docid);
912 5322 berkley
        String query = "select guid from identifier where docid = ? and rev = ?";
913
        String guid = null;
914
915
        DBConnection dbConn = null;
916
        int serialNumber = -1;
917
        try {
918
            // Get a database connection from the pool
919 5377 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
920 5322 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
921
922
            // Execute the insert statement
923
            PreparedStatement stmt = dbConn.prepareStatement(query);
924
            stmt.setString(1, docid);
925
            stmt.setInt(2, rev);
926
            ResultSet rs = stmt.executeQuery();
927 5451 berkley
            if (rs.next())
928
            {
929 5322 berkley
                guid = rs.getString(1);
930 5451 berkley
            }
931
            else
932
            {
933 6104 leinfelder
            	throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
934 5322 berkley
            }
935 5451 berkley
936 5322 berkley
        } catch (SQLException e) {
937
            logMetacat.error("Error while looking up the guid: "
938
                    + e.getMessage());
939
        } finally {
940
            // Return database connection to the pool
941
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
942
        }
943
944
        return guid;
945
    }
946 5333 berkley
947 6454 leinfelder
    public boolean systemMetadataExists(String guid) {
948 6123 leinfelder
		logMetacat.debug("looking up system metadata for guid " + guid);
949
		boolean exists = false;
950 6337 leinfelder
		String query = "select guid from systemmetadata where guid = ?";
951 6123 leinfelder
952
		DBConnection dbConn = null;
953
		int serialNumber = -1;
954
		try {
955
			// Get a database connection from the pool
956
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
957
			serialNumber = dbConn.getCheckOutSerialNumber();
958
959
			// Execute the insert statement
960
			PreparedStatement stmt = dbConn.prepareStatement(query);
961
			stmt.setString(1, guid);
962
			ResultSet rs = stmt.executeQuery();
963
			if (rs.next()) {
964
				exists = true;
965
			}
966
967
		} catch (SQLException e) {
968
			logMetacat.error("Error while looking up the system metadata: "
969
					+ e.getMessage());
970
		} finally {
971
			// Return database connection to the pool
972
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
973
		}
974
975
		return exists;
976
	}
977
978 5333 berkley
    /**
979 5887 berkley
     * creates a system metadata mapping and adds additional fields from sysmeta
980
     * to the table for quick searching.
981
     *
982
     * @param guid the id to insert
983
     * @param localId the systemMetadata object to get the local id for
984 6108 leinfelder
     * @throws McdbDocNotFoundException
985 5887 berkley
     */
986 6108 leinfelder
    public void createSystemMetadata(SystemMetadata sysmeta) throws McdbDocNotFoundException
987 5887 berkley
    {
988 6277 leinfelder
    	String guid = sysmeta.getIdentifier().getValue();
989 6337 leinfelder
    	// insert the record
990
        insertSystemMetadata(guid);
991
        // update with the values
992 6099 leinfelder
        updateSystemMetadata(sysmeta);
993 5887 berkley
    }
994 6099 leinfelder
995 5887 berkley
996
    /**
997 6079 leinfelder
     * update a mapping
998
     * @param guid
999
     * @param localId
1000
     */
1001
    public void updateMapping(String guid, String localId)
1002
    {
1003
1004 6099 leinfelder
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
1005 5350 berkley
        int serialNumber = -1;
1006
        DBConnection dbConn = null;
1007
        try {
1008
            // Parse the localId into scope and rev parts
1009
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1010
            String docid = acc.getDocid();
1011
            int rev = 1;
1012
            if(acc.getRev() != null)
1013
            {
1014
              rev = (new Integer(acc.getRev()).intValue());
1015
            }
1016
1017
            // Get a database connection from the pool
1018
            dbConn =
1019 6079 leinfelder
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1020 5350 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
1021
1022 6099 leinfelder
            // Execute the update statement
1023
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid='" + guid + "'";
1024 5350 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
1025
            stmt.setString(1, docid);
1026
            stmt.setInt(2, rev);
1027
            int rows = stmt.executeUpdate();
1028
1029
            stmt.close();
1030
        } catch (SQLException e) {
1031
            e.printStackTrace();
1032 6079 leinfelder
            logMetacat.error("SQL error while updating a mapping identifier: "
1033 5350 berkley
                    + e.getMessage());
1034
        } catch (NumberFormatException e) {
1035
            e.printStackTrace();
1036 6079 leinfelder
            logMetacat.error("NumberFormat error while updating a mapping identifier: "
1037 5350 berkley
                    + e.getMessage());
1038
        } catch (AccessionNumberException e) {
1039
            e.printStackTrace();
1040 6079 leinfelder
            logMetacat.error("AccessionNumber error while updating a mapping identifier: "
1041 5350 berkley
                    + e.getMessage());
1042
        } finally {
1043
            // Return database connection to the pool
1044
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1045
        }
1046 6099 leinfelder
        logMetacat.debug("done updating mapping");
1047 5350 berkley
    }
1048 6099 leinfelder
1049
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1050 5887 berkley
            String checksum, String checksumAlgorithm, String originMemberNode,
1051 5917 berkley
            String authoritativeMemberNode, long modifiedDate, String submitter,
1052 6384 cjones
            String guid, String objectFormat, BigInteger size, boolean replicationAllowed,
1053 6375 leinfelder
            int numberReplicas, String obsoletes, String obsoletedBy)
1054 5887 berkley
    {
1055
        DBConnection dbConn = null;
1056
        int serialNumber = -1;
1057 5957 berkley
1058 5887 berkley
        try {
1059
            // Get a database connection from the pool
1060
            dbConn =
1061
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1062
            serialNumber = dbConn.getCheckOutSerialNumber();
1063
1064
            // Execute the insert statement
1065
            String query = "update " + TYPE_SYSTEM_METADATA +
1066
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1067 5917 berkley
                "origin_member_node, authoritive_member_node, date_modified, " +
1068 6375 leinfelder
                "submitter, object_format, size, replication_allowed, number_replicas, obsoletes, obsoleted_by) " +
1069
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1070 5887 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
1071
1072
            //data values
1073
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1074
            stmt.setString(2, rightsHolder);
1075
            stmt.setString(3, checksum);
1076
            stmt.setString(4, checksumAlgorithm);
1077
            stmt.setString(5, originMemberNode);
1078
            stmt.setString(6, authoritativeMemberNode);
1079
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1080
            stmt.setString(8, submitter);
1081 5917 berkley
            stmt.setString(9, objectFormat);
1082 6384 cjones
            stmt.setString(10, size.toString());
1083 6107 leinfelder
            stmt.setBoolean(11, replicationAllowed);
1084
            stmt.setInt(12, numberReplicas);
1085 6375 leinfelder
            stmt.setString(13, obsoletes);
1086
            stmt.setString(14, obsoletedBy);
1087
1088 5887 berkley
            //where clause
1089 6381 cjones
            stmt.setString(15, guid);
1090 6099 leinfelder
            logMetacat.debug("stmt: " + stmt.toString());
1091 5887 berkley
            //execute
1092
            int rows = stmt.executeUpdate();
1093
1094
            stmt.close();
1095
        } catch (SQLException e) {
1096
            e.printStackTrace();
1097 5950 berkley
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: "
1098 5887 berkley
                    + e.getMessage());
1099
        } catch (NumberFormatException e) {
1100
            e.printStackTrace();
1101 5950 berkley
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: "
1102 5887 berkley
                    + e.getMessage());
1103
        } finally {
1104
            // Return database connection to the pool
1105
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1106
        }
1107
    }
1108
1109 6107 leinfelder
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes)
1110
    {
1111
        DBConnection dbConn = null;
1112
        int serialNumber = -1;
1113
1114
        try {
1115
            // Get a database connection from the pool
1116
            dbConn =
1117
                DBConnectionPool.getDBConnection("IdentifierManager.insertReplicationPolicy");
1118
            serialNumber = dbConn.getCheckOutSerialNumber();
1119
1120
            // remove existing values first
1121
            String delete = "delete from systemMetadataReplicationPolicy " +
1122
            "where guid = ? and policy = ?";
1123
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1124
	        //data values
1125
	        stmt.setString(1, guid);
1126
	        stmt.setString(2, policy);
1127
	        //execute
1128
	        int deletedCount = stmt.executeUpdate();
1129
	        stmt.close();
1130
1131
            for (String memberNode: memberNodes) {
1132
	            // Execute the insert statement
1133
	            String insert = "insert into systemMetadataReplicationPolicy " +
1134
	                "(guid, policy, member_node) " +
1135
	                "values (?, ?, ?)";
1136
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1137
1138
	            //data values
1139
	            insertStatement.setString(1, guid);
1140
	            insertStatement.setString(2, policy);
1141
	            insertStatement.setString(3, memberNode);
1142
	            //execute
1143
	            int rows = insertStatement.executeUpdate();
1144
	            insertStatement.close();
1145
            }
1146
        } catch (SQLException e) {
1147
            logMetacat.error("SQL error while adding systemMetadataReplicationPolicy for: " + guid, e);
1148
        } finally {
1149
            // Return database connection to the pool
1150
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1151
        }
1152
    }
1153
1154
    private void insertReplicationStatus(String guid, List<Replica> replicas) {
1155
        DBConnection dbConn = null;
1156
        int serialNumber = -1;
1157
1158
        try {
1159
            // Get a database connection from the pool
1160
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertReplicas");
1161
            serialNumber = dbConn.getCheckOutSerialNumber();
1162
1163
            // remove existing values first
1164
            String delete = "delete from systemMetadataReplicationStatus " +
1165
            "where guid = ?";
1166
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1167
	        //data values
1168
	        stmt.setString(1, guid);
1169
	        //execute
1170
	        int deletedCount = stmt.executeUpdate();
1171
	        stmt.close();
1172
1173 6443 leinfelder
	        if (replicas != null) {
1174
	            for (Replica replica: replicas) {
1175
		            // Execute the insert statement
1176
		            String insert = "insert into systemMetadataReplicationStatus " +
1177
		                "(guid, member_node, status, date_verified) " +
1178
		                "values (?, ?, ?, ?)";
1179
		            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1180
1181
		            //data values
1182
		            String memberNode = replica.getReplicaMemberNode().getValue();
1183
		            String status = replica.getReplicationStatus().toString();
1184
		            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1185
		            insertStatement.setString(1, guid);
1186
		            insertStatement.setString(2, memberNode);
1187
		            insertStatement.setString(3, status);
1188
		            insertStatement.setDate(4, sqlDate);
1189
1190
		            //execute
1191
		            int rows = insertStatement.executeUpdate();
1192
		            insertStatement.close();
1193
	            }
1194
	        }
1195 6107 leinfelder
        } catch (SQLException e) {
1196
            logMetacat.error("SQL error while adding systemMetadataReplicationStatus for: " + guid, e);
1197
        } finally {
1198
            // Return database connection to the pool
1199
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1200
        }
1201
    }
1202
1203 5334 berkley
    /**
1204 5887 berkley
     * Insert the system metadata fields into the db
1205
     * @param sm
1206 6108 leinfelder
     * @throws McdbDocNotFoundException
1207 5887 berkley
     */
1208 6108 leinfelder
    public void updateSystemMetadata(SystemMetadata sm) throws McdbDocNotFoundException {
1209 6107 leinfelder
1210
        Boolean replicationAllowed = false;
1211
		Integer numberReplicas = -1;
1212
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1213
    	if (replicationPolicy != null) {
1214
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1215
    		numberReplicas = replicationPolicy.getNumberReplicas();
1216
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1217
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1218
    	}
1219
1220
    	// the main systemMetadata fields
1221
		updateSystemMetadataFields(
1222 6311 leinfelder
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1223
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(),
1224
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(),
1225 6397 leinfelder
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm(),
1226 6311 leinfelder
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1227
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(),
1228
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1229
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(),
1230 6384 cjones
        sm.getIdentifier().getValue(),
1231
        sm.getFmtid() == null ? null: sm.getFmtid().getValue(),
1232
        sm.getSize(),
1233
        replicationAllowed,
1234
        numberReplicas,
1235
        sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
1236
        sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue());
1237 6097 leinfelder
1238
        String guid = sm.getIdentifier().getValue();
1239
1240 6107 leinfelder
        // save replication policies
1241
        if (replicationPolicy != null) {
1242
		    List<String> nodes = null;
1243
		    String policy = null;
1244
1245
		    nodes = new ArrayList<String>();
1246
		    policy = "blocked";
1247
		    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1248
		    	nodes.add(node.getValue());
1249
		    }
1250
		    this.insertReplicationPolicy(guid, policy, nodes);
1251
1252
		    nodes = new ArrayList<String>();
1253
		    policy = "preferred";
1254
		    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1255
		    	nodes.add(node.getValue());
1256
		    }
1257
	        this.insertReplicationPolicy(guid, policy, nodes);
1258
        }
1259 6097 leinfelder
1260 6107 leinfelder
        // save replica information
1261
        this.insertReplicationStatus(guid, sm.getReplicaList());
1262
1263 6108 leinfelder
        // save access policy
1264
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1265
        if (accessPolicy != null) {
1266
        	try {
1267
				this.insertAccessPolicy(guid, accessPolicy);
1268
			} catch (AccessException e) {
1269
				throw new McdbDocNotFoundException(e);
1270
			}
1271
        }
1272 5887 berkley
    }
1273
1274
    /**
1275 6108 leinfelder
     * Creates Metacat access rules and inserts them
1276
     * @param accessPolicy
1277
     * @throws McdbDocNotFoundException
1278
     * @throws AccessException
1279
     */
1280
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1281
1282
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1283
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1284
        	List<Subject> subjects = accessRule.getSubjectList();
1285
        	List<Permission> permissions = accessRule.getPermissionList();
1286
        	for (Subject subject: subjects) {
1287 6122 leinfelder
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1288
        		accessDAO.setPrincipalName(subject.getValue());
1289
    			accessDAO.setGuid(guid);
1290
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1291
    			accessDAO.setPermOrder(AccessControlInterface.DENYFIRST);
1292
    			for (Permission permission: permissions) {
1293
    				Long metacatPermission = new Long(convertPermission(permission));
1294
        			accessDAO.addPermission(metacatPermission);
1295
    			}
1296
    			accessDAOs.add(accessDAO);
1297 6108 leinfelder
        	}
1298
        }
1299
1300 6122 leinfelder
        // use GUID to update
1301
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1302
        accessController.replaceAccess(guid, accessDAOs);
1303 6108 leinfelder
1304
1305
    }
1306
1307
    /**
1308
     * Lookup access policy from Metacat
1309
     * @param guid
1310
     * @return
1311
     * @throws McdbDocNotFoundException
1312
     * @throws AccessException
1313
     */
1314
    private AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1315 6450 leinfelder
        AccessPolicy accessPolicy = new AccessPolicy();
1316
1317 6122 leinfelder
    	// use GUID to look up the access
1318
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1319
    	List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1320 6108 leinfelder
        for (XMLAccessDAO accessDAO: accessDAOs) {
1321 6450 leinfelder
        	AccessRule accessRule = new AccessRule();
1322 6108 leinfelder
        	Permission permission = convertPermission(accessDAO.getPermission().intValue());
1323
        	accessRule.addPermission(permission);
1324
        	Subject subject = new Subject();
1325
        	subject.setValue(accessDAO.getPrincipalName());
1326
        	accessRule.addSubject(subject);
1327 6450 leinfelder
            accessPolicy.addAllow(accessRule);
1328 6108 leinfelder
        }
1329
        return accessPolicy;
1330
    }
1331
1332
    public int convertPermission(Permission permission) {
1333
    	if (permission.equals(Permission.READ)) {
1334
    		return AccessControlInterface.READ;
1335
    	}
1336
    	if (permission.equals(Permission.WRITE)) {
1337
    		return AccessControlInterface.WRITE;
1338
    	}
1339
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1340
    		return AccessControlInterface.CHMOD;
1341
    	}
1342
		return -1;
1343
    }
1344
1345
    public Permission convertPermission(int permission) {
1346
    	if (permission == AccessControlInterface.READ) {
1347
    		return Permission.READ;
1348
    	}
1349
    	if (permission == AccessControlInterface.WRITE) {
1350
    		return Permission.WRITE;
1351
    	}
1352
    	if (permission == AccessControlInterface.CHMOD) {
1353
    		return Permission.CHANGE_PERMISSION;
1354
    	}
1355
		return null;
1356
    }
1357
1358
    /**
1359 6099 leinfelder
     * Lookup a localId given the GUID. If
1360
     * the identifier is not found, throw an exception.
1361
     *
1362
     * @param guid the global identifier to look up
1363
     * @return String containing the corresponding LocalId
1364
     * @throws McdbDocNotFoundException if the identifier is not found
1365 5334 berkley
     */
1366 6099 leinfelder
    public String getLocalId(String guid) throws McdbDocNotFoundException {
1367 5334 berkley
1368
      String db_guid = "";
1369
      String docid = "";
1370
      int rev = 0;
1371
1372 6099 leinfelder
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1373 5334 berkley
1374
      DBConnection dbConn = null;
1375 5333 berkley
      int serialNumber = -1;
1376 5334 berkley
      try {
1377
          // Get a database connection from the pool
1378
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1379
          serialNumber = dbConn.getCheckOutSerialNumber();
1380
1381
          // Execute the insert statement
1382
          PreparedStatement stmt = dbConn.prepareStatement(query);
1383
          stmt.setString(1, guid);
1384
          ResultSet rs = stmt.executeQuery();
1385
          if (rs.next()) {
1386
              db_guid = rs.getString(1);
1387
              docid = rs.getString(2);
1388
              rev = rs.getInt(3);
1389
              assert(db_guid.equals(guid));
1390
          } else {
1391
              throw new McdbDocNotFoundException("Document not found:" + guid);
1392
          }
1393
          stmt.close();
1394
      } catch (SQLException e) {
1395
          logMetacat.error("Error while looking up the local identifier: "
1396
                  + e.getMessage());
1397
      } finally {
1398
          // Return database connection to the pool
1399
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1400
      }
1401
      return docid + "." + rev;
1402
    }
1403
1404 5377 berkley
    /**
1405 5895 berkley
     * query the systemmetadata table based on the given parameters
1406
     * @param startTime
1407
     * @param endTime
1408
     * @param objectFormat
1409
     * @param replicaStatus
1410
     * @param start
1411
     * @param count
1412
     * @return ObjectList
1413 6299 leinfelder
     * @throws SQLException
1414
     * @throws ServiceException
1415
     * @throws PropertyNotFoundException
1416 5895 berkley
     */
1417
    public ObjectList querySystemMetadata(Date startTime, Date endTime,
1418 6337 leinfelder
            ObjectFormatIdentifier objectFormatId, boolean replicaStatus, int start, int count) throws SQLException, PropertyNotFoundException, ServiceException
1419 5895 berkley
    {
1420
        ObjectList ol = new ObjectList();
1421
        int total = 0;
1422 5943 berkley
        DBConnection dbConn = null;
1423
        int serialNumber = -1;
1424 5895 berkley
1425 6299 leinfelder
        try {
1426 5895 berkley
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
1427
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
1428 5917 berkley
                "date_modified, submitter, object_format, size from systemmetadata";
1429 5895 berkley
1430
            boolean f1 = false;
1431
            boolean f2 = false;
1432
            boolean f3 = false;
1433
1434 6299 leinfelder
            if (startTime != null) {
1435 5917 berkley
                sql += " where systemmetadata.date_modified > ?";
1436 5895 berkley
                f1 = true;
1437
            }
1438
1439 6299 leinfelder
            if (endTime != null) {
1440
                if (!f1) {
1441 5917 berkley
                    sql += " where systemmetadata.date_modified < ?";
1442
                }
1443 6299 leinfelder
                else {
1444 5917 berkley
                    sql += " and systemmetadata.date_modified < ?";
1445
                }
1446 5895 berkley
                f2 = true;
1447
            }
1448
1449 6337 leinfelder
            if (objectFormatId != null) {
1450 6299 leinfelder
                if (!f1 && !f2) {
1451 5917 berkley
                    sql += " where object_format = ?";
1452
                }
1453 6299 leinfelder
                else {
1454 5917 berkley
                    sql += " and object_format = ?";
1455
                }
1456 5895 berkley
                f3 = true;
1457
            }
1458
1459 6299 leinfelder
            if (replicaStatus) {
1460 5895 berkley
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
1461 6299 leinfelder
                if (!f1 && !f2 && !f3) {
1462 5917 berkley
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
1463
                }
1464 6299 leinfelder
                else {
1465 5917 berkley
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
1466
                }
1467 5895 berkley
            }
1468
1469 5943 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1470
            serialNumber = dbConn.getCheckOutSerialNumber();
1471 5895 berkley
            PreparedStatement stmt = dbConn.prepareStatement(sql);
1472
1473 6299 leinfelder
            if (f1 && f2 && f3) {
1474 5895 berkley
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1475
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1476 6337 leinfelder
                stmt.setString(3, objectFormatId.getValue());
1477 5895 berkley
            }
1478 6299 leinfelder
            else if (f1 && f2 && !f3) {
1479 5895 berkley
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1480
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1481
            }
1482 6299 leinfelder
            else if (f1 && !f2 && f3) {
1483 5895 berkley
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1484 6337 leinfelder
                stmt.setString(2, objectFormatId.getValue());
1485 5895 berkley
            }
1486 6299 leinfelder
            else if (f1 && !f2 && !f3) {
1487 5895 berkley
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1488
            }
1489 6299 leinfelder
            else if (!f1 && f2 && f3) {
1490 5895 berkley
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1491 6337 leinfelder
                stmt.setString(2, objectFormatId.getValue());
1492 5895 berkley
            }
1493 6299 leinfelder
            else if (!f1 && !f2 && f3) {
1494 6337 leinfelder
                stmt.setString(1, objectFormatId.getValue());
1495 5895 berkley
            }
1496 6299 leinfelder
            else if (!f1 && f2 && !f3) {
1497 5895 berkley
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1498
            }
1499
1500 6099 leinfelder
            //logMetacat.debug("LISTOBJECTS QUERY: " + stmt.toString());
1501 5895 berkley
1502
            ResultSet rs = stmt.executeQuery();
1503 6299 leinfelder
            for (int i=0; i<start; i++) {
1504
                if (rs.next()) {
1505 5917 berkley
                    total++;
1506 6299 leinfelder
                } else {
1507 5917 berkley
                    break;
1508
                }
1509 5895 berkley
            }
1510 5917 berkley
1511 5895 berkley
            int countIndex = 0;
1512
1513 6299 leinfelder
            while (rs.next()) {
1514 5895 berkley
                total++;
1515 6299 leinfelder
                if (countIndex >= count) {
1516
                	// allow unlimited (negative number for count)
1517
                	if (count > 0) {
1518
                		break;
1519
                	}
1520 5895 berkley
                }
1521 6318 cjones
1522 5895 berkley
                String guid = rs.getString(1);
1523 6099 leinfelder
                //logMetacat.debug("query found doc with guid " + guid);
1524 5895 berkley
                //Timestamp dateUploaded = rs.getTimestamp(2);
1525
                //String rightsHolder = rs.getString(3);
1526 6318 cjones
                String checksum = rs.getString(4);
1527
                String checksumAlgorithm = rs.getString(5);
1528 5895 berkley
                //String originMemberNode = rs.getString(6);
1529 6318 cjones
                //String authoritiveMemberNode = rs.getString(7);
1530
                Timestamp dateModified = rs.getTimestamp(8);
1531 5895 berkley
                //String submitter = rs.getString(9);
1532 6318 cjones
                String fmtidStr = rs.getString(10);
1533
                String sz = rs.getString(11);
1534 6384 cjones
                BigInteger size = new BigInteger("0");
1535 6299 leinfelder
1536
                if (sz != null && !sz.trim().equals("")) {
1537 6384 cjones
                    size = new BigInteger(rs.getString(11));
1538 5917 berkley
                }
1539 5895 berkley
1540
                ObjectInfo oi = new ObjectInfo();
1541
1542
                Identifier id = new Identifier();
1543
                id.setValue(guid);
1544
                oi.setIdentifier(id);
1545
1546 6299 leinfelder
                if (dateModified != null) {
1547
                	oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
1548
                }
1549 5895 berkley
1550
                Checksum cs = new Checksum();
1551
                cs.setValue(checksum);
1552 6299 leinfelder
                try {
1553 6368 leinfelder
                	//cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1554 6397 leinfelder
                    cs.setAlgorithm(checksumAlgorithm);
1555 6299 leinfelder
                } catch (Exception e) {
1556
					logMetacat.warn("could not parse checksum algorithm", e);
1557
				}
1558 5895 berkley
                oi.setChecksum(cs);
1559
1560 6296 cjones
                try {
1561 6384 cjones
	                oi.setFmtid(ObjectFormatCache.getInstance().getFormat(fmtidStr).getFmtid());
1562 6316 cjones
                } catch (NotFound e) {
1563 6299 leinfelder
                	logMetacat.warn("could not find object format: " + fmtidStr, e);
1564 6384 cjones
1565 6299 leinfelder
				}
1566 5917 berkley
1567
                oi.setSize(size);
1568 5895 berkley
1569
                ol.addObjectInfo(oi);
1570
                countIndex++;
1571
            }
1572
1573 6299 leinfelder
            // expend the resultset to get the total count of possible rows
1574
            while (rs.next()) {
1575 5895 berkley
                total++;
1576
            }
1577
        }
1578 6299 leinfelder
1579
        finally {
1580 5943 berkley
            // Return database connection to the pool
1581
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1582
        }
1583 5895 berkley
1584
        ol.setStart(start);
1585 5922 berkley
        ol.setCount(ol.sizeObjectInfoList());
1586 5895 berkley
        ol.setTotal(total);
1587
1588
        return ol;
1589
    }
1590
1591
    /**
1592 6099 leinfelder
     * create a mapping in the identifier table
1593 5377 berkley
     * @param guid
1594
     * @param localId
1595
     */
1596 6099 leinfelder
    public void createMapping(String guid, String localId)
1597 5453 berkley
    {
1598 5334 berkley
1599
        int serialNumber = -1;
1600 5333 berkley
        DBConnection dbConn = null;
1601
        try {
1602
1603
            // Parse the localId into scope and rev parts
1604
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1605
            String docid = acc.getDocid();
1606 5344 berkley
            int rev = 1;
1607 6099 leinfelder
            if (acc.getRev() != null) {
1608 5344 berkley
              rev = (new Integer(acc.getRev()).intValue());
1609
            }
1610 5333 berkley
1611
            // Get a database connection from the pool
1612 6099 leinfelder
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1613 5333 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
1614
1615
            // Execute the insert statement
1616 6099 leinfelder
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1617 5333 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
1618
            stmt.setString(1, guid);
1619
            stmt.setString(2, docid);
1620
            stmt.setInt(3, rev);
1621 6099 leinfelder
            logMetacat.debug("mapping query: " + stmt.toString());
1622 5333 berkley
            int rows = stmt.executeUpdate();
1623
1624
            stmt.close();
1625
        } catch (SQLException e) {
1626 5344 berkley
            e.printStackTrace();
1627 6099 leinfelder
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: "
1628 5333 berkley
                    + e.getMessage());
1629
        } catch (NumberFormatException e) {
1630 5344 berkley
            e.printStackTrace();
1631 6099 leinfelder
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: "
1632 5333 berkley
                    + e.getMessage());
1633
        } catch (AccessionNumberException e) {
1634 5344 berkley
            e.printStackTrace();
1635 6099 leinfelder
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: "
1636 5333 berkley
                    + e.getMessage());
1637
        } finally {
1638
            // Return database connection to the pool
1639
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1640
        }
1641
    }
1642 6099 leinfelder
1643
    /**
1644
     * create the systemmetadata record
1645
     * @param guid
1646
     */
1647 6337 leinfelder
    private void insertSystemMetadata(String guid)
1648 6099 leinfelder
    {
1649
1650
        int serialNumber = -1;
1651
        DBConnection dbConn = null;
1652
        try {
1653
1654
            // Get a database connection from the pool
1655
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1656
            serialNumber = dbConn.getCheckOutSerialNumber();
1657
1658
            // Execute the insert statement
1659 6337 leinfelder
            String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1660 6099 leinfelder
            PreparedStatement stmt = dbConn.prepareStatement(query);
1661
            stmt.setString(1, guid);
1662
            logMetacat.debug("system metadata query: " + stmt.toString());
1663
            int rows = stmt.executeUpdate();
1664
1665
            stmt.close();
1666
        } catch (Exception e) {
1667
            e.printStackTrace();
1668 6277 leinfelder
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1669 6099 leinfelder
        } finally {
1670
            // Return database connection to the pool
1671
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1672
        }
1673
    }
1674 6277 leinfelder
1675
    private void deleteSystemMetadata(String guid)
1676
    {
1677
1678
        int serialNumber = -1;
1679
        DBConnection dbConn = null;
1680
        try {
1681
1682
            // Get a database connection from the pool
1683
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1684
            serialNumber = dbConn.getCheckOutSerialNumber();
1685
1686
            // Execute the statement
1687
            String query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
1688
            PreparedStatement stmt = dbConn.prepareStatement(query);
1689
            stmt.setString(1, guid);
1690
            logMetacat.debug("delete system metadata: " + stmt.toString());
1691
            int rows = stmt.executeUpdate();
1692
1693
            stmt.close();
1694
        } catch (Exception e) {
1695
            e.printStackTrace();
1696
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1697
        } finally {
1698
            // Return database connection to the pool
1699
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1700
        }
1701
    }
1702 5282 jones
}