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