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