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