Project

General

Profile

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