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 10123 tao
import java.io.File;
28 6384 cjones
import java.math.BigInteger;
29 5282 jones
import java.sql.PreparedStatement;
30
import java.sql.ResultSet;
31
import java.sql.SQLException;
32 5895 berkley
import java.sql.Timestamp;
33 6107 leinfelder
import java.util.ArrayList;
34
import java.util.Date;
35 9629 tao
import java.util.HashMap;
36 6107 leinfelder
import java.util.Hashtable;
37
import java.util.List;
38
import java.util.Vector;
39 5282 jones
40
import org.apache.log4j.Logger;
41 8810 leinfelder
import org.dataone.client.v2.formats.ObjectFormatCache;
42 10239 tao
import org.dataone.configuration.Settings;
43 7010 cjones
import org.dataone.service.exceptions.BaseException;
44 6904 cjones
import org.dataone.service.exceptions.InvalidSystemMetadata;
45 6366 leinfelder
import org.dataone.service.types.v1.AccessPolicy;
46
import org.dataone.service.types.v1.AccessRule;
47
import org.dataone.service.types.v1.Checksum;
48
import org.dataone.service.types.v1.Identifier;
49
import org.dataone.service.types.v1.NodeReference;
50
import org.dataone.service.types.v1.ObjectFormatIdentifier;
51
import org.dataone.service.types.v1.ObjectInfo;
52
import org.dataone.service.types.v1.ObjectList;
53
import org.dataone.service.types.v1.Permission;
54
import org.dataone.service.types.v1.Replica;
55
import org.dataone.service.types.v1.ReplicationPolicy;
56
import org.dataone.service.types.v1.ReplicationStatus;
57
import org.dataone.service.types.v1.Subject;
58 9230 tao
import org.dataone.service.types.v2.MediaType;
59
import org.dataone.service.types.v2.MediaTypeProperty;
60 8810 leinfelder
import org.dataone.service.types.v2.SystemMetadata;
61 5282 jones
62 6108 leinfelder
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
63 5282 jones
import edu.ucsb.nceas.metacat.database.DBConnection;
64
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
65 7438 leinfelder
import edu.ucsb.nceas.metacat.database.DatabaseService;
66 9119 tao
import edu.ucsb.nceas.metacat.dataone.hazelcast.HazelcastService;
67 5887 berkley
import edu.ucsb.nceas.metacat.properties.PropertyService;
68 6108 leinfelder
import edu.ucsb.nceas.metacat.shared.AccessException;
69 6299 leinfelder
import edu.ucsb.nceas.metacat.shared.ServiceException;
70 5286 jones
import edu.ucsb.nceas.metacat.util.DocumentUtil;
71 10123 tao
import edu.ucsb.nceas.utilities.FileUtil;
72 6299 leinfelder
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
73 7475 leinfelder
import edu.ucsb.nceas.utilities.access.AccessControlInterface;
74
import edu.ucsb.nceas.utilities.access.XMLAccessDAO;
75 5282 jones
76
/**
77
 * Manage the relationship between Metacat local identifiers (LocalIDs) that are
78 6099 leinfelder
 * codified as the (docid, rev) pair with globally unique string identifiers
79 5282 jones
 * (GUIDs) that are opaque strings.  This class provides methods to manage these
80
 * identifiers, and to search for and look up LocalIDs based on their GUID and
81
 * vice versa. IdentifierManager is a singleton.
82
 *
83
 * @author Matthew Jones
84
 */
85
public class IdentifierManager {
86
87 5334 berkley
    public static final String TYPE_SYSTEM_METADATA = "systemmetadata";
88
    public static final String TYPE_IDENTIFIER = "identifier";
89 10239 tao
90
    private static boolean filterWhiteSpaces = Settings.getConfiguration().getBoolean("dataone.listingidentifier.filteringwhitespaces", true);
91 5334 berkley
92 5282 jones
    /**
93
     * The single instance of the manager that is always returned.
94
     */
95
    private static IdentifierManager self = null;
96 6099 leinfelder
    private Logger logMetacat = Logger.getLogger(IdentifierManager.class);
97 5282 jones
98
    /**
99
     * A private constructor that initializes the class when getInstance() is
100
     * called.
101
     */
102 6099 leinfelder
    private IdentifierManager() {}
103 5282 jones
104
    /**
105
     * Return the single instance of the manager after initializing it if it
106
     * wasn't previously initialized.
107
     *
108
     * @return the single IdentifierManager instance
109
     */
110
    public static IdentifierManager getInstance()
111
    {
112
        if (self == null) {
113
            self = new IdentifierManager();
114
        }
115
        return self;
116
    }
117
118 9230 tao
    /*public SystemMetadata asSystemMetadata(Date dateUploaded, String rightsHolder,
119 6097 leinfelder
            String checksum, String checksumAlgorithm, String originMemberNode,
120
            String authoritativeMemberNode, Date dateModified, String submitter,
121 6561 leinfelder
            String guid, String fmtidStr, BigInteger size, BigInteger serialVersion) {
122 6097 leinfelder
        SystemMetadata sysMeta = new SystemMetadata();
123
124
        Identifier sysMetaId = new Identifier();
125
        sysMetaId.setValue(guid);
126
        sysMeta.setIdentifier(sysMetaId);
127
        sysMeta.setDateUploaded(dateUploaded);
128
        Subject rightsHolderSubject = new Subject();
129
        rightsHolderSubject.setValue(rightsHolder);
130
        sysMeta.setRightsHolder(rightsHolderSubject);
131
        Checksum checksumObject = new Checksum();
132
        checksumObject.setValue(checksum);
133 6397 leinfelder
        checksumObject.setAlgorithm(checksumAlgorithm);
134 6097 leinfelder
        sysMeta.setChecksum(checksumObject);
135
        NodeReference omn = new NodeReference();
136
        omn.setValue(originMemberNode);
137
        sysMeta.setOriginMemberNode(omn);
138
        NodeReference amn = new NodeReference();
139
        amn.setValue(authoritativeMemberNode);
140
        sysMeta.setAuthoritativeMemberNode(amn);
141
        sysMeta.setDateSysMetadataModified(dateModified);
142
        Subject submitterSubject = new Subject();
143
        submitterSubject.setValue(submitter);
144
        sysMeta.setSubmitter(submitterSubject);
145 7010 cjones
        ObjectFormatIdentifier fmtid = null;
146 6124 cjones
        try {
147 7010 cjones
        	ObjectFormatIdentifier formatId = new ObjectFormatIdentifier();
148
        	formatId.setValue(fmtidStr);
149
        	fmtid = ObjectFormatCache.getInstance().getFormat(formatId).getFormatId();
150 6561 leinfelder
        	sysMeta.setFormatId(fmtid);
151 7010 cjones
152
        } catch (BaseException nfe) {
153
            logMetacat.error("The objectFormat " + fmtidStr +
154 6384 cjones
          	" is not registered. Setting the default format id.");
155 7010 cjones
            fmtid = new ObjectFormatIdentifier();
156
            fmtid.setValue("application/octet-stream");
157
            sysMeta.setFormatId(fmtid);
158
159 6124 cjones
        }
160 6097 leinfelder
        sysMeta.setSize(size);
161 6561 leinfelder
        sysMeta.setSerialVersion(serialVersion);
162 6097 leinfelder
163
        return sysMeta;
164 9230 tao
    }*/
165 6097 leinfelder
166 5282 jones
    /**
167 5895 berkley
     * return a hash of all of the info that is in the systemmetadata table
168
     * @param localId
169
     * @return
170
     */
171 9230 tao
    /*public Hashtable<String, String> getSystemMetadataInfo(String localId)
172 5895 berkley
    throws McdbDocNotFoundException
173
    {
174
        try
175
        {
176
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
177
            localId = acc.getDocid();
178
        }
179
        catch(Exception e)
180
        {
181
            //do nothing. just try the localId as it is
182
        }
183
        Hashtable<String, String> h = new Hashtable<String, String>();
184
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
185 5944 berkley
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size " +
186 5895 berkley
          "from systemmetadata where docid = ?";
187
        DBConnection dbConn = null;
188
        int serialNumber = -1;
189
        try
190
        {
191
            // Get a database connection from the pool
192
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
193
            serialNumber = dbConn.getCheckOutSerialNumber();
194
195
            // Execute the insert statement
196
            PreparedStatement stmt = dbConn.prepareStatement(sql);
197
            stmt.setString(1, localId);
198
            ResultSet rs = stmt.executeQuery();
199
            if (rs.next())
200
            {
201
                String guid = rs.getString(1);
202
                Timestamp dateUploaded = rs.getTimestamp(2);
203
                String rightsHolder = rs.getString(3);
204
                String checksum = rs.getString(4);
205
                String checksumAlgorithm = rs.getString(5);
206
                String originMemberNode = rs.getString(6);
207
                String authoritativeMemberNode = rs.getString(7);
208
                Timestamp dateModified = rs.getTimestamp(8);
209
                String submitter = rs.getString(9);
210 5917 berkley
                String objectFormat = rs.getString(10);
211
                long size = new Long(rs.getString(11)).longValue();
212 5895 berkley
213
                h.put("guid", guid);
214
                h.put("date_uploaded", new Long(dateUploaded.getTime()).toString());
215
                h.put("rights_holder", rightsHolder);
216
                h.put("checksum", checksum);
217
                h.put("checksum_algorithm", checksumAlgorithm);
218
                h.put("origin_member_node", originMemberNode);
219
                h.put("authoritative_member_node", authoritativeMemberNode);
220
                h.put("date_modified", new Long(dateModified.getTime()).toString());
221
                h.put("submitter", submitter);
222 5917 berkley
                h.put("object_format", objectFormat);
223
                h.put("size", new Long(size).toString());
224 5895 berkley
225
                stmt.close();
226
            }
227
            else
228
            {
229
                stmt.close();
230
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
231
                throw new McdbDocNotFoundException("2Could not find document " + localId);
232
            }
233
234
        }
235
        catch (SQLException e)
236
        {
237
            e.printStackTrace();
238
            logMetacat.error("Error while getting system metadata info for localid " + localId + " : "
239
                    + e.getMessage());
240
        }
241
        finally
242
        {
243
            // Return database connection to the pool
244
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
245
        }
246
        return h;
247 9230 tao
    }*/
248 5895 berkley
249
    /**
250 6097 leinfelder
     * return a hash of all of the info that is in the systemmetadata table
251 6099 leinfelder
     * @param guid
252 6097 leinfelder
     * @return
253 6108 leinfelder
     * @throws McdbDocNotFoundException
254 6097 leinfelder
     */
255 6099 leinfelder
    public SystemMetadata getSystemMetadata(String guid)
256 6097 leinfelder
    	throws McdbDocNotFoundException
257
    {
258 6099 leinfelder
259 6097 leinfelder
        SystemMetadata sysMeta = new SystemMetadata();
260
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
261 6375 leinfelder
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size, " +
262 9230 tao
          "replication_allowed, number_replicas, obsoletes, obsoleted_by, serial_version, archived, series_id, file_name, media_type " +
263 6099 leinfelder
          "from systemmetadata where guid = ?";
264 6097 leinfelder
        DBConnection dbConn = null;
265
        int serialNumber = -1;
266 6533 cjones
        Boolean replicationAllowed = new Boolean(false);
267
        BigInteger numberOfReplicas = new BigInteger("-1");
268 6561 leinfelder
        BigInteger serialVersion = new BigInteger("-1");
269 7428 leinfelder
        Boolean archived = new Boolean(false);
270 6561 leinfelder
271 6097 leinfelder
        try
272
        {
273
            // Get a database connection from the pool
274
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getSystemMetadata");
275
            serialNumber = dbConn.getCheckOutSerialNumber();
276
277
            // Execute the statement
278
            PreparedStatement stmt = dbConn.prepareStatement(sql);
279 6099 leinfelder
            stmt.setString(1, guid);
280 6097 leinfelder
            ResultSet rs = stmt.executeQuery();
281
            if (rs.next())
282
            {
283
                Timestamp dateUploaded = rs.getTimestamp(2);
284
                String rightsHolder = rs.getString(3);
285
                String checksum = rs.getString(4);
286
                String checksumAlgorithm = rs.getString(5);
287
                String originMemberNode = rs.getString(6);
288
                String authoritativeMemberNode = rs.getString(7);
289
                Timestamp dateModified = rs.getTimestamp(8);
290
                String submitter = rs.getString(9);
291 6296 cjones
                String fmtidStr = rs.getString(10);
292 6384 cjones
                BigInteger size = new BigInteger(rs.getString(11));
293 6535 cjones
                replicationAllowed = new Boolean(rs.getBoolean(12));
294 6533 cjones
                numberOfReplicas = new BigInteger(rs.getString(13));
295
                String obsoletes = rs.getString(14);
296
                String obsoletedBy = rs.getString(15);
297 6561 leinfelder
                serialVersion = new BigInteger(rs.getString(16));
298 7428 leinfelder
                archived = new Boolean(rs.getBoolean(17));
299 9038 tao
                String series_id = rs.getString(18);
300 9230 tao
                String file_name = rs.getString(19);
301
                String media_type = rs.getString(20);
302 6375 leinfelder
303 6097 leinfelder
                Identifier sysMetaId = new Identifier();
304
                sysMetaId.setValue(guid);
305
                sysMeta.setIdentifier(sysMetaId);
306 6561 leinfelder
                sysMeta.setSerialVersion(serialVersion);
307 6097 leinfelder
                sysMeta.setDateUploaded(dateUploaded);
308
                Subject rightsHolderSubject = new Subject();
309
                rightsHolderSubject.setValue(rightsHolder);
310
                sysMeta.setRightsHolder(rightsHolderSubject);
311
                Checksum checksumObject = new Checksum();
312
                checksumObject.setValue(checksum);
313 6397 leinfelder
                checksumObject.setAlgorithm(checksumAlgorithm);
314 6097 leinfelder
                sysMeta.setChecksum(checksumObject);
315 6519 leinfelder
                if (originMemberNode != null) {
316
	                NodeReference omn = new NodeReference();
317
	                omn.setValue(originMemberNode);
318
	                sysMeta.setOriginMemberNode(omn);
319
                }
320
                if (authoritativeMemberNode != null) {
321
	                NodeReference amn = new NodeReference();
322
	                amn.setValue(authoritativeMemberNode);
323
	                sysMeta.setAuthoritativeMemberNode(amn);
324
                }
325 6097 leinfelder
                sysMeta.setDateSysMetadataModified(dateModified);
326 7639 leinfelder
                if (submitter != null) {
327
	                Subject submitterSubject = new Subject();
328
	                submitterSubject.setValue(submitter);
329
	                sysMeta.setSubmitter(submitterSubject);
330
                }
331 7023 leinfelder
                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
332
                fmtid.setValue(fmtidStr);
333
            	sysMeta.setFormatId(fmtid);
334 6097 leinfelder
                sysMeta.setSize(size);
335 6423 leinfelder
                if (obsoletes != null) {
336
	                Identifier obsoletesId = new Identifier();
337
	                obsoletesId.setValue(obsoletes);
338
	                sysMeta.setObsoletes(obsoletesId);
339
                }
340
                if (obsoletedBy != null) {
341
		            Identifier obsoletedById = new Identifier();
342
		            obsoletedById.setValue(obsoletedBy);
343
		            sysMeta.setObsoletedBy(obsoletedById);
344
                }
345 7428 leinfelder
                sysMeta.setArchived(archived);
346 9038 tao
                if(series_id != null) {
347
                    Identifier seriesId = new Identifier();
348
                    seriesId.setValue(series_id);
349
                    sysMeta.setSeriesId(seriesId);
350
                }
351 9230 tao
                if(file_name != null ) {
352
                    sysMeta.setFileName(file_name);
353
                }
354
355
                if(media_type != null ) {
356
                    MediaType mediaType = new MediaType();
357
                    mediaType.setName(media_type);
358
                    // get media type properties from another table.
359
                    String mediaTypePropertyQuery = "select name, value from smmediatypeproperties where guid = ?";
360
                    PreparedStatement stmt2 = dbConn.prepareStatement(mediaTypePropertyQuery);
361
                    stmt2.setString(1, guid);
362
                    ResultSet rs2 = stmt2.executeQuery();
363
                    while (rs2.next()) {
364
                        String name = rs2.getString(1);
365
                        String value = rs2.getString(2);
366
                        MediaTypeProperty property = new MediaTypeProperty();
367
                        property.setName(name);
368
                        property.setValue(value);
369
                        mediaType.addProperty(property);
370
                    }
371
                    sysMeta.setMediaType(mediaType);
372
                    rs2.close();
373
                    stmt2.close();
374
                }
375 6097 leinfelder
                stmt.close();
376
            }
377
            else
378
            {
379
                stmt.close();
380
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
381 6099 leinfelder
                throw new McdbDocNotFoundException("Could not find " + guid);
382 6097 leinfelder
            }
383
384
        }
385
        catch (SQLException e)
386
        {
387
            e.printStackTrace();
388 6099 leinfelder
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "
389 6097 leinfelder
                    + e.getMessage());
390
        }
391
        finally
392
        {
393
            // Return database connection to the pool
394
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
395
        }
396 6377 leinfelder
397 6533 cjones
        // populate the replication policy
398 6107 leinfelder
        ReplicationPolicy replicationPolicy = new ReplicationPolicy();
399 6533 cjones
        if ( numberOfReplicas != null  && numberOfReplicas.intValue() != -1 ) {
400
            replicationPolicy.setNumberReplicas(numberOfReplicas.intValue());
401
402
        }
403
404
        if ( replicationAllowed != null ) {
405
            replicationPolicy.setReplicationAllowed(replicationAllowed);
406
407
        }
408 6107 leinfelder
        replicationPolicy.setBlockedMemberNodeList(getReplicationPolicy(guid, "blocked"));
409
        replicationPolicy.setPreferredMemberNodeList(getReplicationPolicy(guid, "preferred"));
410 6533 cjones
		    sysMeta.setReplicationPolicy(replicationPolicy);
411 6107 leinfelder
412 6533 cjones
		    // look up replication status
413
		    sysMeta.setReplicaList(getReplicationStatus(guid));
414 6108 leinfelder
415 6533 cjones
		    // look up access policy
416
		    try {
417
		    	sysMeta.setAccessPolicy(getAccessPolicy(guid));
418
		    } catch (AccessException e) {
419
		    	throw new McdbDocNotFoundException(e);
420
		    }
421 6107 leinfelder
422 6097 leinfelder
        return sysMeta;
423
    }
424
425
426 6107 leinfelder
    private List<NodeReference> getReplicationPolicy(String guid, String policy)
427
		throws McdbDocNotFoundException {
428
429
		List<NodeReference> nodes = new ArrayList<NodeReference>();
430
		String sql = "select guid, policy, member_node " +
431 9482 tao
			"from smReplicationPolicy where guid = ? and policy = ? order by policy_id ASC";
432 6107 leinfelder
	    DBConnection dbConn = null;
433
	    int serialNumber = -1;
434
	    try {
435
	        // Get a database connection from the pool
436
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicationPolicy");
437
	        serialNumber = dbConn.getCheckOutSerialNumber();
438
439
	        // Execute the statement
440
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
441
	        stmt.setString(1, guid);
442
	        stmt.setString(2, policy);
443
	        ResultSet rs = stmt.executeQuery();
444
	        while (rs.next())
445
	        {
446
	            String memberNode = rs.getString(3);
447
	            NodeReference node = new NodeReference();
448
	            node.setValue(memberNode);
449
	            nodes.add(node);
450
451
	        }
452
	        stmt.close();
453
454
	    } catch (SQLException e) {
455
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
456
	    }
457
	    finally {
458
	        // Return database connection to the pool
459
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
460
	    }
461
462
	    return nodes;
463
	}
464 6097 leinfelder
465 6107 leinfelder
    private List<Replica> getReplicationStatus(String guid) throws McdbDocNotFoundException {
466
467
		List<Replica> replicas = new ArrayList<Replica>();
468
		String sql = "select guid, member_node, status, date_verified " +
469 7392 leinfelder
			"from smReplicationStatus where guid = ?";
470 6107 leinfelder
	    DBConnection dbConn = null;
471
	    int serialNumber = -1;
472
	    try {
473
	        // Get a database connection from the pool
474
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicas");
475
	        serialNumber = dbConn.getCheckOutSerialNumber();
476
477
	        // Execute the statement
478
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
479
	        stmt.setString(1, guid);
480
	        ResultSet rs = stmt.executeQuery();
481
	        while (rs.next())
482
	        {
483
	            String memberNode = rs.getString(2);
484
	            String status = rs.getString(3);
485 7399 cjones
	            java.sql.Timestamp verified = rs.getTimestamp(4);
486 6107 leinfelder
487
	            Replica replica = new Replica();
488
	            NodeReference node = new NodeReference();
489
	            node.setValue(memberNode);
490
	            replica.setReplicaMemberNode(node);
491 6454 leinfelder
	            replica.setReplicationStatus(ReplicationStatus.valueOf(status));
492 6107 leinfelder
	            replica.setReplicaVerified(new Date(verified.getTime()));
493
	            replicas.add(replica);
494
	        }
495
	        stmt.close();
496
497
	    } catch (SQLException e) {
498
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
499
	    }
500
	    finally {
501
	        // Return database connection to the pool
502
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
503
	    }
504
505
	    return replicas;
506
	}
507
508 5378 berkley
509
    /**
510
     * return the newest rev for a given localId
511
     * @param localId
512
     * @return
513
     */
514
    public int getLatestRevForLocalId(String localId)
515
        throws McdbDocNotFoundException
516
    {
517 5798 berkley
        try
518
        {
519
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
520
            localId = acc.getDocid();
521
        }
522
        catch(Exception e)
523
        {
524
            //do nothing. just try the localId as it is
525
        }
526 5378 berkley
        int rev = 0;
527 6595 leinfelder
        String sql = "select rev from xml_documents where docid like ? ";
528 5378 berkley
        DBConnection dbConn = null;
529
        int serialNumber = -1;
530
        try
531
        {
532
            // Get a database connection from the pool
533
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLatestRevForLocalId");
534
            serialNumber = dbConn.getCheckOutSerialNumber();
535
536
            // Execute the insert statement
537
            PreparedStatement stmt = dbConn.prepareStatement(sql);
538 6595 leinfelder
            stmt.setString(1, localId);
539 5378 berkley
            ResultSet rs = stmt.executeQuery();
540
            if (rs.next())
541
            {
542
                rev = rs.getInt(1);
543
                stmt.close();
544
            }
545
            else
546
            {
547
                stmt.close();
548
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
549 5798 berkley
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
550 5378 berkley
            }
551
        }
552
        catch (SQLException e)
553
        {
554
            logMetacat.error("Error while looking up the guid: "
555
                    + e.getMessage());
556
        }
557
        finally
558
        {
559
            // Return database connection to the pool
560
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
561
        }
562
        return rev;
563
    }
564
565
    /**
566 5377 berkley
     * return all local ids in the object store that do not have associated
567 6099 leinfelder
     * system metadata
568 5377 berkley
     */
569 7168 leinfelder
    public List<String> getLocalIdsWithNoSystemMetadata(boolean includeRevisions, int serverLocation)
570 5377 berkley
    {
571
        Vector<String> ids = new Vector<String>();
572 6099 leinfelder
        String sql = "select docid, rev from xml_documents " +
573
        		"where docid not in " +
574 6720 leinfelder
        		"(select docid from identifier where guid in (select guid from systemmetadata))";
575 7168 leinfelder
        if (serverLocation > 0) {
576
        	sql = sql + " and server_location = ? ";
577
        }
578 6704 leinfelder
579 6745 leinfelder
        String revisionSql = "select docid, rev from xml_revisions " +
580 6704 leinfelder
				"where docid not in " +
581 6720 leinfelder
				"(select docid from identifier where guid in (select guid from systemmetadata))";
582 7168 leinfelder
        if (serverLocation > 0) {
583
        	revisionSql = revisionSql + " and server_location = ? ";
584
        }
585 6704 leinfelder
586
        if (includeRevisions) {
587
        	sql = sql + " UNION ALL " + revisionSql;
588
        }
589
590 5377 berkley
        DBConnection dbConn = null;
591
        int serialNumber = -1;
592
        try
593
        {
594
            // Get a database connection from the pool
595
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
596
            serialNumber = dbConn.getCheckOutSerialNumber();
597
598
            // Execute the insert statement
599
            PreparedStatement stmt = dbConn.prepareStatement(sql);
600 7168 leinfelder
            // set params based on what we have in the query string
601
            if (serverLocation > 0) {
602
            	stmt.setInt(1, serverLocation);
603
            	if (includeRevisions) {
604
            		stmt.setInt(2, serverLocation);
605
            	}
606
            }
607 5377 berkley
            ResultSet rs = stmt.executeQuery();
608
            while (rs.next())
609
            {
610
                String localid = rs.getString(1);
611 5798 berkley
                String rev = rs.getString(2);
612
                localid += "." + rev;
613 6099 leinfelder
                logMetacat.debug("id to add SM for: " + localid);
614 5377 berkley
                ids.add(localid);
615
            }
616
            stmt.close();
617
        }
618
        catch (SQLException e)
619
        {
620
            logMetacat.error("Error while looking up the guid: "
621
                    + e.getMessage());
622
        }
623
        finally
624
        {
625
            // Return database connection to the pool
626
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
627
        }
628
629
        return ids;
630
    }
631
632
    /**
633
     * return a listing of all local ids in the object store
634
     * @return a list of all local ids in metacat
635
     */
636
    public List<String> getAllLocalIds()
637 6416 rnahf
    // seems to be an unnecessary and restrictive throw -rnahf 13-Sep-2011
638
    //    throws Exception
639 5377 berkley
    {
640
        Vector<String> ids = new Vector<String>();
641
        String sql = "select docid from xml_documents";
642
        DBConnection dbConn = null;
643
        int serialNumber = -1;
644
        try
645
        {
646
            // Get a database connection from the pool
647
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
648
            serialNumber = dbConn.getCheckOutSerialNumber();
649
650
            // Execute the insert statement
651
            PreparedStatement stmt = dbConn.prepareStatement(sql);
652
            ResultSet rs = stmt.executeQuery();
653
            while (rs.next())
654
            {
655
                String localid = rs.getString(1);
656
                ids.add(localid);
657
            }
658
            stmt.close();
659
        }
660
        catch (SQLException e)
661
        {
662
            logMetacat.error("Error while looking up the guid: "
663
                    + e.getMessage());
664
        }
665
        finally
666
        {
667
            // Return database connection to the pool
668
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
669
        }
670
        return ids;
671
    }
672
673 6416 rnahf
674 6118 leinfelder
    /**
675 6416 rnahf
     * return a listing of all guids in the object store
676
     * @return a list of all GUIDs in metacat
677
     */
678 7187 leinfelder
    public List<String> getAllSystemMetadataGUIDs()
679 6416 rnahf
    {
680
        Vector<String> guids = new Vector<String>();
681 7187 leinfelder
        String sql = "select guid from systemmetadata";
682 6416 rnahf
        DBConnection dbConn = null;
683
        int serialNumber = -1;
684
        try
685
        {
686
            // Get a database connection from the pool
687
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllGUIDs");
688
            serialNumber = dbConn.getCheckOutSerialNumber();
689
690
            // Execute the insert statement
691
            PreparedStatement stmt = dbConn.prepareStatement(sql);
692
            ResultSet rs = stmt.executeQuery();
693
            while (rs.next())
694
            {
695
                String guid = rs.getString(1);
696
                guids.add(guid);
697
            }
698
            stmt.close();
699
        }
700
        catch (SQLException e)
701
        {
702
            logMetacat.error("Error while retrieving the guid: "
703
                    + e.getMessage());
704
        }
705
        finally
706
        {
707
            // Return database connection to the pool
708
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
709
        }
710
        return guids;
711
    }
712
713
714
715
    /**
716 6118 leinfelder
     * 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 List<String> getUpdatedSystemMetadataIds(Date since)
721
       throws Exception
722
    {
723
        List<String> ids = new Vector<String>();
724
        String sql =
725
        	"select guid from " + TYPE_SYSTEM_METADATA +
726
        	" where guid not in " +
727
        	" (select guid from " + TYPE_IDENTIFIER + ") " +
728
        	" and date_modified > ?";
729
        DBConnection dbConn = null;
730
        int serialNumber = -1;
731
        try
732
        {
733
            // Get a database connection from the pool
734
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getUpdatedSystemMetadataIds");
735
            serialNumber = dbConn.getCheckOutSerialNumber();
736 6099 leinfelder
737 6118 leinfelder
            // Execute the insert statement
738
            PreparedStatement stmt = dbConn.prepareStatement(sql);
739
            stmt.setDate(1, new java.sql.Date(since.getTime()));
740
            ResultSet rs = stmt.executeQuery();
741
            while (rs.next())
742
            {
743
                String guid = rs.getString(1);
744
                ids.add(guid);
745
            }
746
            stmt.close();
747
        }
748
        catch (SQLException e)
749
        {
750
            logMetacat.error("Error while looking up the updated guids: "
751
                    + e.getMessage());
752
        }
753
        finally
754
        {
755
            // Return database connection to the pool
756
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
757
        }
758
        return ids;
759
    }
760 5282 jones
761 6459 leinfelder
    /**
762
     * returns a list of system metadata-only guids since the given date
763
     * @return a list of system ids in metacat that do not correspond to objects
764
     * TODO: need to check which server they are on
765
     */
766
    public Date getLastModifiedDate() throws Exception {
767
        Date maxDate = null;
768 6118 leinfelder
769 6459 leinfelder
        List<String> ids = new Vector<String>();
770
        String sql =
771
        	"select max(date_modified) from " + TYPE_SYSTEM_METADATA;
772
        DBConnection dbConn = null;
773
        int serialNumber = -1;
774
        try
775
        {
776
            // Get a database connection from the pool
777
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLastModifiedDate");
778
            serialNumber = dbConn.getCheckOutSerialNumber();
779
780
            // Execute the insert statement
781
            PreparedStatement stmt = dbConn.prepareStatement(sql);
782
            ResultSet rs = stmt.executeQuery();
783
            if (rs.next()) {
784
            	maxDate = rs.getDate(1);
785
            }
786
            stmt.close();
787
        }
788
        catch (SQLException e)
789
        {
790
            logMetacat.error("Error while looking up the latest update date: "
791
                    + e.getMessage());
792
        }
793
        finally
794
        {
795
            // Return database connection to the pool
796
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
797
        }
798
        return maxDate;
799
    }
800
801 6118 leinfelder
802 5282 jones
    /**
803
     * Determine if an identifier exists already, returning true if so.
804 7045 leinfelder
     * NOTE: looks in the identifier and system metadata table for a match
805
     * (in that order)
806 5282 jones
     *
807
     * @param guid the global identifier to look up
808
     * @return boolean true if the identifier exists
809
     */
810 9017 tao
    public boolean identifierExists(String guid) throws SQLException
811 5282 jones
    {
812
        boolean idExists = false;
813
        try {
814
            String id = getLocalId(guid);
815
            if (id != null) {
816
                idExists = true;
817
            }
818
        } catch (McdbDocNotFoundException e) {
819 6123 leinfelder
        	// try system metadata only
820 9017 tao
        	    //this will check if the guid field on the system metadata table has the id
821 9030 tao
        		idExists = systemMetadataPIDExists(guid);
822 9017 tao
        		if(!idExists) {
823
        		    //if the guid field of the system metadata table doesn't have the id,
824
        		    //we will check if the serial_id field of the system metadata table has it
825
        		    idExists=systemMetadataSIDExists(guid);
826
        		}
827
828 5282 jones
        }
829
        return idExists;
830
    }
831
832
    /**
833 7045 leinfelder
     * Determine if an identifier mapping exists already,
834
     * returning true if so.
835 5282 jones
     *
836 7045 leinfelder
     * @param guid the global identifier to look up
837
     * @return boolean true if the identifier exists
838
     */
839 9024 tao
    public boolean mappingExists(String guid) throws SQLException
840 7045 leinfelder
    {
841
        boolean idExists = false;
842
        try {
843
            String id = getLocalId(guid);
844
            if (id != null) {
845
                idExists = true;
846
            }
847
        } catch (McdbDocNotFoundException e) {
848
        	// nope!
849
        }
850
        return idExists;
851
    }
852
853
    /**
854
     *
855 5453 berkley
     * @param guid
856
     * @param rev
857
     * @return
858
     */
859
    public String generateLocalId(String guid, int rev)
860
    {
861
        return generateLocalId(guid, rev, false);
862
    }
863 5286 jones
864
    /**
865
     * Given a global identifier (guid), create a suitable local identifier that
866
     * follows Metacat's docid semantics and format (scope.id.rev), and create
867
     * a mapping between these two identifiers.  This effectively reserves both
868
     * the global and the local identifier, as they will now be present in the
869 7070 leinfelder
     * identifier mapping table.
870
     *
871
     * REMOVED feature: If the incoming guid has the syntax of a
872 5286 jones
     * Metacat docid (scope.id.rev), then simply use it.
873 7070 leinfelder
     * WHY: because "test.1.001" becomes "test.1.1" which is not correct for DataONE
874
     * identifier use (those revision numbers are just chartacters and should not be interpreted)
875 5286 jones
     *
876
     * @param guid the global string identifier
877
     * @param rev the revision number to be used in the localId
878
     * @return String containing the localId to be used for Metacat operations
879
     */
880 5453 berkley
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata)
881 5286 jones
    {
882
        String localId = "";
883
        boolean conformsToDocidFormat = false;
884
885 7070 leinfelder
        // BRL -- do not allow Metacat-conforming IDs to be used:
886
        // test.1.001 becomes test.1.1 which is NOT correct for DataONE identifiers
887 5286 jones
        // Check if the guid passed in is already in docid (scope.id.rev) format
888 7070 leinfelder
//        try {
889
//            AccessionNumber acc = new AccessionNumber(guid, "NONE");
890
//            if (new Integer(acc.getRev()).intValue() > 0) {
891
//                conformsToDocidFormat = true;
892
//            }
893
//        } catch (NumberFormatException e) {
894
//            // No action needed, simply detecting invalid AccessionNumbers
895
//        } catch (AccessionNumberException e) {
896
//            // No action needed, simply detecting invalid AccessionNumbers
897
//        } catch (SQLException e) {
898
//            // No action needed, simply detecting invalid AccessionNumbers
899
//        }
900 5286 jones
901
        if (conformsToDocidFormat) {
902
            // if it conforms, use it for both guid and localId
903
            localId = guid;
904
        } else {
905
            // if not, then generate a new unique localId
906
            localId = DocumentUtil.generateDocumentId(rev);
907
        }
908
909
        // Register this new pair in the identifier mapping table
910 6099 leinfelder
        logMetacat.debug("creating mapping in generateLocalId");
911 5453 berkley
        if(!isSystemMetadata)
912
        { //don't do this if we're generating for system metadata
913
            createMapping(guid, localId);
914
        }
915 5286 jones
916
        return localId;
917
    }
918 5322 berkley
919
    /**
920
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
921 5452 berkley
     * if the docid, rev is not found in the identifiers or systemmetadata tables
922 5322 berkley
     *
923
     * @param docid the docid to look up
924
     * @param rev the revision of the docid to look up
925
     * @return String containing the mapped guid
926
     * @throws McdbDocNotFoundException if the docid, rev is not found
927
     */
928
    public String getGUID(String docid, int rev)
929
      throws McdbDocNotFoundException
930
    {
931 6099 leinfelder
        logMetacat.debug("getting guid for " + docid);
932 5322 berkley
        String query = "select guid from identifier where docid = ? and rev = ?";
933
        String guid = null;
934
935
        DBConnection dbConn = null;
936
        int serialNumber = -1;
937 9465 tao
        PreparedStatement stmt = null;
938 5322 berkley
        try {
939
            // Get a database connection from the pool
940 5377 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
941 5322 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
942
943
            // Execute the insert statement
944 9465 tao
            stmt = dbConn.prepareStatement(query);
945 5322 berkley
            stmt.setString(1, docid);
946
            stmt.setInt(2, rev);
947
            ResultSet rs = stmt.executeQuery();
948 5451 berkley
            if (rs.next())
949
            {
950 5322 berkley
                guid = rs.getString(1);
951 5451 berkley
            }
952
            else
953
            {
954 6104 leinfelder
            	throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
955 5322 berkley
            }
956 9465 tao
            if(rs != null) {
957
                rs.close();
958
            }
959 5322 berkley
        } catch (SQLException e) {
960
            logMetacat.error("Error while looking up the guid: "
961
                    + e.getMessage());
962
        } finally {
963 9465 tao
            try {
964
                if(stmt != null) {
965
                    stmt.close();
966
                }
967
            } catch (Exception e) {
968
                logMetacat.warn("Couldn't close the prepared statement since "+e.getMessage());
969
            } finally {
970
                // Return database connection to the pool
971
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
972
            }
973
974 5322 berkley
        }
975
976
        return guid;
977
    }
978 5333 berkley
979 9015 tao
    /**
980
     * Get the pid of the head (current) version of objects match the specified sid.
981 9119 tao
     * 1. locate all candidate chain-ends for S1:
982
     *      determined by:  seriesId == S1 AND (obsoletedBy == null  OR obsoletedBy.seriesId != S1) // these are the type1 and type2 ends
983
     *      If obsoletedBy is missing, we generally consider it a type 2 end except:
984
     *      there is another object in the chain (has the same series id) that obsoletes the missing object.
985
     * 2. if only 1 candidate chain-end, return it as the HEAD
986 9637 tao
     * 3. otherwise return the one in the chain with the latest dateUploaded value. However, we find that dateUpload doesn't refect the obsoletes information
987
     * (espically on the cn), so we will check osoletes information as well. https://redmine.dataone.org/issues/7624
988 9015 tao
     * @param sid specified sid which should match.
989
     * @return the pid of the head version. The null will be returned if there is no pid found.
990 9016 tao
     * @throws SQLException
991 9015 tao
     */
992 9016 tao
    public Identifier getHeadPID(Identifier sid) throws SQLException {
993 9015 tao
        Identifier pid = null;
994
        if(sid != null && sid.getValue() != null && !sid.getValue().trim().equals("")) {
995
            logMetacat.debug("getting pid of the head version for matching the sid: " + sid.getValue());
996 9628 tao
            String sql = "select guid, obsoleted_by, obsoletes from systemMetadata where series_id = ? order by date_uploaded DESC";
997 9015 tao
            DBConnection dbConn = null;
998
            int serialNumber = -1;
999 9465 tao
            PreparedStatement stmt = null;
1000 9634 tao
            PreparedStatement stmt2 = null;
1001
            ResultSet rs = null;
1002
            ResultSet result = null;
1003 9637 tao
            //int endsCount = 0;
1004 9119 tao
            boolean hasError = false;
1005 9629 tao
            HashMap<String, String> obsoletesIdGuidMap = new HashMap<String, String>();//the key is an obsoletes id, the value is an guid
1006 9637 tao
            Vector<Identifier> endsList = new Vector<Identifier>();//the vector storing ends
1007 9015 tao
            try {
1008
                // Get a database connection from the pool
1009
                dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getHeadPID");
1010
                serialNumber = dbConn.getCheckOutSerialNumber();
1011
                // Execute the insert statement
1012 9465 tao
                stmt = dbConn.prepareStatement(sql);
1013 9015 tao
                stmt.setString(1, sid.getValue());
1014 9634 tao
                rs = stmt.executeQuery();
1015 9119 tao
                boolean hasNext = rs.next();
1016
                boolean first = true;
1017
                Identifier firstOne = new Identifier();//since the sql using the desc order, the first one has the latest upload date.
1018
                if (hasNext)
1019 9015 tao
                {
1020 9119 tao
                    while(hasNext) {
1021
                        String guidStr = rs.getString(1);
1022 9628 tao
                        String obsoletedByStr = rs.getString(2);
1023 9629 tao
                        String obsoletesStr = rs.getString(3);
1024 9119 tao
                        Identifier guid = new Identifier();
1025
                        guid.setValue(guidStr);
1026 9629 tao
                        if(obsoletesStr != null && !obsoletesStr.trim().equals("")) {
1027
                            if(obsoletesIdGuidMap.containsKey(obsoletesStr) && !guidStr.equals(obsoletesIdGuidMap.get(obsoletesStr))) {
1028
                                logMetacat.error("Both id "+guidStr+" and id "+obsoletesIdGuidMap.get(obsoletesStr)+" obsoletes the id"+obsoletesStr+
1029
                                        ". It is illegal. So the head pid maybe is wrong.");
1030
                                hasError = true;
1031
                            }
1032 9638 tao
                            logMetacat.debug("Put "+guidStr+"(a value) Obsoletes "+obsoletesStr+" (a key) into the vector.");
1033 9629 tao
                            obsoletesIdGuidMap.put(obsoletesStr, guidStr);
1034
                        }
1035 9119 tao
                        if(first) {
1036
                            firstOne = guid;
1037
                            first =false;
1038
                        }
1039 9628 tao
                        //SystemMetadata sysmeta = HazelcastService.getInstance().getSystemMetadataMap().get(guid);
1040
                        //if(sysmeta.getObsoletedBy() == null) {
1041
                        if(obsoletedByStr == null || obsoletedByStr.trim().equals("")) {
1042 9119 tao
                            //type 1 end
1043 9128 tao
                            logMetacat.debug(""+guidStr+" is a type 1 end for sid "+sid.getValue());
1044 9637 tao
                            //pid = guid;
1045
                            //endsCount++;
1046
                            endsList.add(guid);
1047 9119 tao
                        } else {
1048 9628 tao
                            //Identifier obsoletedBy = sysmeta.getObsoletedBy();
1049
                            Identifier obsoletedBy = new Identifier();
1050
                            obsoletedBy.setValue(obsoletedByStr);
1051 9634 tao
                            //SystemMetadata obsoletedBySysmeta = HazelcastService.getInstance().getSystemMetadataMap().get(obsoletedBy);
1052
                            String sql2 = "select series_id, guid from systemMetadata where guid = ? ";
1053
                            stmt2 = dbConn.prepareStatement(sql2);
1054
                            stmt2.setString(1, obsoletedByStr);
1055
                            result = stmt2.executeQuery();
1056
                            boolean next = result.next();
1057
                            //if(obsoletedBySysmeta != null) {
1058
                            if(next) {
1059
                                logMetacat.debug("The object "+obsoletedBy+" which obsoletes "+guidStr+" does have a system metadata on the table.");
1060
                                //Identifier sidInObsoletedBy = obsoletedBySysmeta.getSeriesId();
1061
                                String sidInObsoletedBy = result.getString(1);
1062
                                if(sidInObsoletedBy == null|| !sidInObsoletedBy.equals(sid.getValue())) {
1063 9119 tao
                                    // type 2 end
1064 9634 tao
                                    logMetacat.debug(""+guidStr+" is a type 2 end for sid "+sid.getValue()+ "since it is obsoleted by the object "+sidInObsoletedBy+
1065
                                            " which has a different sid or no sids");
1066 9637 tao
                                    //pid = guid;
1067
                                    //endsCount++;
1068
                                    endsList.add(guid);
1069 9119 tao
                                }
1070
                            } else {
1071 9634 tao
                                logMetacat.debug("The object "+obsoletedBy+" which obsoletes "+guidStr+" is missing on the host.");
1072 9119 tao
                                //obsoletedBySysmeta doesn't exist; it means the object is missing
1073
                                //generally, we consider it we generally consider it a type 2 end except:
1074
                                 //there is another object in the chain (has the same series id) that obsoletes the missing object.
1075 9629 tao
                                /*String sql2 = "select guid from systemMetadata where  obsoletes = ? and series_id = ?";
1076 9119 tao
                                PreparedStatement stmt2 = dbConn.prepareStatement(sql2);
1077
                                stmt2.setString(1, obsoletedBy.getValue());
1078
                                stmt2.setString(2, sid.getValue());
1079
                                ResultSet result = stmt2.executeQuery();
1080
                                boolean next = result.next();
1081
                                int count = 0;
1082
                                while(next) {
1083
                                    count++;
1084
                                    next = result.next();
1085
                                }
1086
                                if(count == 0) {
1087
                                    //the exception (another object in the chain (has the same series id) that obsoletes the missing object) doesn't exist
1088
                                    // it is a type 2 end
1089 9128 tao
                                    logMetacat.debug(""+guidStr+" is a type 2 end for sid "+sid.getValue());
1090 9119 tao
                                    pid = guid;
1091
                                    endsCount++;
1092
                                } else if (count ==1) {
1093
                                    // it is not end, do nothing;
1094
                                } else {
1095
                                    // something is wrong - there are more than one objects obsolete the missing object!
1096
                                    hasError = true;
1097
                                    break;
1098 9629 tao
                                }*/
1099
                                if(obsoletesIdGuidMap != null && obsoletesIdGuidMap.containsKey(obsoletedByStr)) {
1100
                                   //This is the exception - another object in the chain (has the same series id) that obsoletes the missing object
1101
                                    //The obsoletesIdGuidMap maintains the relationship (with the same  series id)
1102
                                    logMetacat.debug("Though the object "+obsoletedBy+" which obsoletes "+guidStr+" is missing."+
1103
                                            " However, there is another object "+obsoletesIdGuidMap.get(obsoletedByStr)+" in the chain obsoleting it. So it is not an end.");
1104
1105
                                } else {
1106
                                    //the exception (another object in the chain (has the same series id) that obsoletes the missing object) doesn't exist
1107
                                    // it is a type 2 end
1108
                                    logMetacat.debug(""+guidStr+" is a type 2 end for sid "+sid.getValue());
1109 9637 tao
                                    //pid = guid;
1110
                                    //endsCount++;
1111
                                    endsList.add(guid);
1112 9119 tao
                                }
1113
                            }
1114
                        }
1115
                        hasNext = rs.next();
1116
                    }
1117 9637 tao
                    if(hasError) {
1118
                        logMetacat.info("The sid chain "+sid.getValue()+" was messed up and we will return the object with the latest upload date.");
1119 9119 tao
                        pid = firstOne;
1120 9637 tao
                    } else {
1121
                        if(endsList.size() == 1) {
1122
                            //it has one end and it is an ideal chain. We already assign the guid to the pid. So do nothing.
1123
                            logMetacat.info("It is an ideal chain for sid "+sid.getValue());
1124
                            pid = endsList.get(0);
1125
                        } else if (endsList.size() ==0) {
1126
                            logMetacat.info("This is weird situation and we don't find any end. We use the latest DateOfupload");
1127
                            pid=checkObsoletesChain(firstOne, obsoletesIdGuidMap);
1128
                        } else if(endsList.size() >1) {
1129
                            // it is not an ideal chain, use the one with latest upload date(the first one in the result set since we have the desc order)
1130
                            logMetacat.info("It is NOT an ideal chain for sid "+sid.getValue());
1131
                            pid = checkObsoletesChain(endsList.get(0), obsoletesIdGuidMap);
1132
                        }
1133 9119 tao
                    }
1134 9637 tao
1135 9026 tao
                } else {
1136 9119 tao
                    //it is not a sid or at least we don't have anything to match it.
1137
                    //do nothing, so null will be returned
1138 9637 tao
                    logMetacat.info("We don't find anything matching the id "+sid.getValue()+" as sid. The null will be returned since it is probably a pid");
1139 9026 tao
                }
1140 9015 tao
1141 9634 tao
1142 9015 tao
            } catch (SQLException e) {
1143
                logMetacat.error("Error while get the head pid for the sid "+sid.getValue()+" : "
1144
                        + e.getMessage());
1145 9016 tao
                throw e;
1146 9015 tao
            } finally {
1147 9465 tao
                try {
1148 9634 tao
                    if(rs != null) {
1149
                        rs.close();
1150
                    }
1151
                    if(result != null) {
1152
                        result.close();
1153
                    }
1154 9465 tao
                    if(stmt != null) {
1155
                        stmt.close();
1156
                    }
1157 9634 tao
                    if(stmt2 != null) {
1158
                        stmt2.close();
1159
                    }
1160 9465 tao
                } catch (Exception e) {
1161
                    logMetacat.warn("Couldn't close the prepared statement since "+e.getMessage());
1162
                } finally {
1163
                    // Return database connection to the pool
1164
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1165
                }
1166 9015 tao
            }
1167
        }
1168 9637 tao
        if(pid != null && sid != null) {
1169
            logMetacat.info("The head of chain for sid "+sid.getValue()+"  --is--  "+pid.getValue());
1170
        } else if(pid == null && sid != null) {
1171
            logMetacat.info("The head of chain for sid "+sid.getValue()+" is null. So it is pid.");
1172
        }
1173
1174 9015 tao
        return pid;
1175
    }
1176
1177 9637 tao
    /*
1178
     * For the non-ideal chain, we used to return the latest Dateupload object as the head pid. However, Dateupload
1179
     * sometimes doesn't refect the obsoletes chain. We need to check if any other objects obsoletes it recursively.
1180
     * see ticket:https://redmine.dataone.org/issues/7624
1181
     */
1182
    private Identifier checkObsoletesChain(Identifier latestDateUpload, HashMap<String, String>obsoletesIdGuidMap) {
1183
        Identifier pid = latestDateUpload;
1184 9638 tao
        if(obsoletesIdGuidMap != null && latestDateUpload != null && obsoletesIdGuidMap.containsKey(latestDateUpload.getValue())) {
1185 9637 tao
            logMetacat.debug("Another object obsoletes the lasted uploaded object "+latestDateUpload.getValue());
1186
            //another object obsoletes the lastedDateUpload object
1187 9638 tao
            String pidStr = obsoletesIdGuidMap.get(latestDateUpload.getValue());
1188 9637 tao
            while (obsoletesIdGuidMap.containsKey(pidStr)) {
1189
                pidStr = obsoletesIdGuidMap.get(pidStr);
1190
                logMetacat.debug("Another object "+pidStr+" obsoletes the object ");
1191
            }
1192
            pid = new Identifier();
1193
            pid.setValue(pidStr);
1194
1195
        }
1196
        if(pid != null && latestDateUpload != null){
1197
            logMetacat.debug("IdnetifierManager.checkObsoletesChain - The final return value is "+pid.getValue()+ " for given value "+latestDateUpload.getValue());
1198
        }
1199
        return pid;
1200
    }
1201 9016 tao
    /**
1202 9032 tao
     * Check if the specified sid object exists on the serial id field on the system metadata table
1203
     * @param sid
1204
     * @return true if it exists; false otherwise.
1205
     * @throws SQLException
1206
     */
1207
    public boolean systemMetadataSIDExists(Identifier sid) throws SQLException {
1208
        if (sid != null && sid.getValue() != null && !sid.getValue().trim().equals("")) {
1209
            return systemMetadataSIDExists(sid.getValue());
1210
        } else {
1211
            return false;
1212
        }
1213
    }
1214
1215
    /**
1216 9016 tao
     * Check if the specified sid exists on the serial id field on the system metadata table
1217
     * @param id
1218
     * @return true if it exists; false otherwise.
1219
     */
1220 9017 tao
    public boolean systemMetadataSIDExists(String sid) throws SQLException {
1221 9016 tao
        boolean exists = false;
1222 9032 tao
        logMetacat.debug("Check if the  sid: " + sid +" exists on the series_id field of the system metadata table.");
1223 9016 tao
        if(sid != null && !sid.trim().equals("")) {
1224
            String sql = "select guid from systemMetadata where series_id = ?";
1225
            DBConnection dbConn = null;
1226
            int serialNumber = -1;
1227 9465 tao
            PreparedStatement stmt = null;
1228 9016 tao
            try {
1229
                // Get a database connection from the pool
1230
                dbConn = DBConnectionPool.getDBConnection("IdentifierManager.serialIdExists");
1231
                serialNumber = dbConn.getCheckOutSerialNumber();
1232
                // Execute the insert statement
1233 9465 tao
                stmt = dbConn.prepareStatement(sql);
1234 9016 tao
                stmt.setString(1, sid);
1235
                ResultSet rs = stmt.executeQuery();
1236
                if (rs.next())
1237
                {
1238
                    exists = true;
1239
                }
1240 9465 tao
                if(rs != null) {
1241
                    rs.close();
1242
                }
1243 9016 tao
            } catch (SQLException e) {
1244
                logMetacat.error("Error while checking if the sid "+sid+" exists on the series_id field of the system metadata table: "
1245
                        + e.getMessage());
1246
                throw e;
1247
            } finally {
1248 9465 tao
                try {
1249
                    if(stmt != null) {
1250
                        stmt.close();
1251
                    }
1252
                } catch (Exception e) {
1253
                    logMetacat.warn("Couldn't close the prepared statement since "+e.getMessage());
1254
                } finally {
1255
                    // Return database connection to the pool
1256
                    DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1257
                }
1258 9016 tao
            }
1259
        }
1260
        return exists;
1261
    }
1262
1263 9032 tao
    /**
1264
     * Determine if the specified identifier object exists or not.
1265
     * @param pid - the specified identifier
1266
     * @return true if it is exists.
1267
     * @throws SQLException
1268
     * @throws NullPointerException
1269
     */
1270
    public boolean systemMetadataPIDExists(Identifier pid) throws SQLException {
1271
        if (pid != null && pid.getValue() != null && !pid.getValue().trim().equals("")) {
1272
            return systemMetadataPIDExists(pid.getValue());
1273
        } else {
1274
            return false;
1275
        }
1276
    }
1277
1278 9030 tao
    public boolean systemMetadataPIDExists(String guid) throws SQLException {
1279 6123 leinfelder
		logMetacat.debug("looking up system metadata for guid " + guid);
1280
		boolean exists = false;
1281 6337 leinfelder
		String query = "select guid from systemmetadata where guid = ?";
1282 6123 leinfelder
		DBConnection dbConn = null;
1283
		int serialNumber = -1;
1284 9465 tao
		PreparedStatement stmt = null;
1285 9032 tao
		if(guid != null && !guid.trim().equals("")) {
1286
		    try {
1287
	            // Get a database connection from the pool
1288
	            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
1289
	            serialNumber = dbConn.getCheckOutSerialNumber();
1290 6123 leinfelder
1291 9032 tao
	            // Execute the insert statement
1292 9465 tao
	            stmt = dbConn.prepareStatement(query);
1293 9032 tao
	            stmt.setString(1, guid);
1294
	            ResultSet rs = stmt.executeQuery();
1295
	            if (rs.next()) {
1296
	                exists = true;
1297
	            }
1298 9465 tao
	            if(rs != null) {
1299
	                rs.close();
1300
	            }
1301 6123 leinfelder
1302 9032 tao
	        } catch (SQLException e) {
1303
	            logMetacat.error("Error while looking up the system metadata: "
1304
	                    + e.getMessage());
1305
	            throw e;
1306
	        } finally {
1307 9465 tao
	            try {
1308
	                if(stmt != null) {
1309
	                    stmt.close();
1310
	                }
1311
	            } catch (Exception e) {
1312
	                logMetacat.warn("Couldn't close the prepared statement since "+e.getMessage());
1313
	            } finally {
1314
	                // Return database connection to the pool
1315
	                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1316
	            }
1317 9032 tao
	        }
1318 6123 leinfelder
		}
1319
		return exists;
1320
	}
1321
1322 5333 berkley
    /**
1323 5887 berkley
     * creates a system metadata mapping and adds additional fields from sysmeta
1324
     * to the table for quick searching.
1325
     *
1326
     * @param guid the id to insert
1327
     * @param localId the systemMetadata object to get the local id for
1328 6108 leinfelder
     * @throws McdbDocNotFoundException
1329 6892 cjones
     * @throws SQLException
1330 6904 cjones
     * @throws InvalidSystemMetadata
1331 5887 berkley
     */
1332 7188 leinfelder
    public void insertOrUpdateSystemMetadata(SystemMetadata sysmeta)
1333 6904 cjones
        throws McdbDocNotFoundException, SQLException, InvalidSystemMetadata {
1334 6277 leinfelder
    	String guid = sysmeta.getIdentifier().getValue();
1335 7188 leinfelder
1336
    	 // Get a database connection from the pool
1337
        DBConnection dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1338
        int serialNumber = dbConn.getCheckOutSerialNumber();
1339 6892 cjones
1340 7188 leinfelder
        try {
1341
        	// use a single transaction for it all
1342
        	dbConn.setAutoCommit(false);
1343
1344
	    	// insert the record if needed
1345 9030 tao
        	if (!IdentifierManager.getInstance().systemMetadataPIDExists(guid)) {
1346 7188 leinfelder
    	        insertSystemMetadata(guid, dbConn);
1347
			}
1348
	        // update with the values
1349
	        updateSystemMetadata(sysmeta, dbConn);
1350
1351
	        // commit if we got here with no errors
1352
	        dbConn.commit();
1353
        } catch (Exception e) {
1354
            e.printStackTrace();
1355
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1356
            dbConn.rollback();
1357 9220 tao
            throw new SQLException("Can't save system metadata "+e.getMessage());
1358 7188 leinfelder
        } finally {
1359
            // Return database connection to the pool
1360
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1361
        }
1362
1363
1364 5887 berkley
    }
1365 6099 leinfelder
1366 5887 berkley
1367
    /**
1368 6079 leinfelder
     * update a mapping
1369
     * @param guid
1370
     * @param localId
1371
     */
1372
    public void updateMapping(String guid, String localId)
1373
    {
1374
1375 6099 leinfelder
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
1376 5350 berkley
        int serialNumber = -1;
1377
        DBConnection dbConn = null;
1378
        try {
1379
            // Parse the localId into scope and rev parts
1380
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1381
            String docid = acc.getDocid();
1382
            int rev = 1;
1383
            if(acc.getRev() != null)
1384
            {
1385
              rev = (new Integer(acc.getRev()).intValue());
1386
            }
1387
1388
            // Get a database connection from the pool
1389
            dbConn =
1390 6079 leinfelder
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1391 5350 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
1392
1393 6099 leinfelder
            // Execute the update statement
1394 6595 leinfelder
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid = ?";
1395 5350 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
1396
            stmt.setString(1, docid);
1397
            stmt.setInt(2, rev);
1398 6595 leinfelder
            stmt.setString(3, guid);
1399 5350 berkley
            int rows = stmt.executeUpdate();
1400
1401
            stmt.close();
1402
        } catch (SQLException e) {
1403
            e.printStackTrace();
1404 6079 leinfelder
            logMetacat.error("SQL error while updating a mapping identifier: "
1405 5350 berkley
                    + e.getMessage());
1406
        } catch (NumberFormatException e) {
1407
            e.printStackTrace();
1408 6079 leinfelder
            logMetacat.error("NumberFormat error while updating a mapping identifier: "
1409 5350 berkley
                    + e.getMessage());
1410
        } catch (AccessionNumberException e) {
1411
            e.printStackTrace();
1412 6079 leinfelder
            logMetacat.error("AccessionNumber error while updating a mapping identifier: "
1413 5350 berkley
                    + e.getMessage());
1414
        } finally {
1415
            // Return database connection to the pool
1416
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1417
        }
1418 6099 leinfelder
        logMetacat.debug("done updating mapping");
1419 5350 berkley
    }
1420 6099 leinfelder
1421
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1422 6892 cjones
        String checksum, String checksumAlgorithm, String originMemberNode,
1423
        String authoritativeMemberNode, long modifiedDate, String submitter,
1424
        String guid, String objectFormat, BigInteger size, boolean archived,
1425
        boolean replicationAllowed, int numberReplicas, String obsoletes,
1426 9230 tao
        String obsoletedBy, BigInteger serialVersion, String seriesId,
1427
        String fileName, MediaType mediaType, DBConnection dbConn) throws SQLException  {
1428
        PreparedStatement stmt = null;
1429
        PreparedStatement stmt2 = null;
1430
        try {
1431
            dbConn.setAutoCommit(false);
1432
            // Execute the insert statement
1433
            String query = "update " + TYPE_SYSTEM_METADATA +
1434
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1435
                "origin_member_node, authoritive_member_node, date_modified, " +
1436
                "submitter, object_format, size, archived, replication_allowed, number_replicas, " +
1437 9231 tao
                "obsoletes, obsoleted_by, serial_version, series_id, file_name, media_type) " +
1438 9230 tao
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?,?,?) where guid = ?";
1439
            stmt = dbConn.prepareStatement(query);
1440
1441
            //data values
1442
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1443
            stmt.setString(2, rightsHolder);
1444
            stmt.setString(3, checksum);
1445
            stmt.setString(4, checksumAlgorithm);
1446
            stmt.setString(5, originMemberNode);
1447
            stmt.setString(6, authoritativeMemberNode);
1448
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1449
            stmt.setString(8, submitter);
1450
            stmt.setString(9, objectFormat);
1451
            stmt.setString(10, size.toString());
1452
            stmt.setBoolean(11, archived);
1453
            stmt.setBoolean(12, replicationAllowed);
1454
            stmt.setInt(13, numberReplicas);
1455
            stmt.setString(14, obsoletes);
1456
            stmt.setString(15, obsoletedBy);
1457 9342 tao
            if(serialVersion != null) {
1458
                stmt.setString(16, serialVersion.toString());
1459
            } else {
1460
                stmt.setString(16, null);
1461
            }
1462
1463 9230 tao
            stmt.setString(17, seriesId);
1464
            stmt.setString(18, fileName);
1465
            if (mediaType == null) {
1466
                stmt.setString(19, null);
1467
            } else {
1468
                stmt.setString(19, mediaType.getName());
1469
            }
1470
            //where clause
1471
            stmt.setString(20, guid);
1472
            logMetacat.debug("stmt: " + stmt.toString());
1473
            //execute
1474
            int rows = stmt.executeUpdate();
1475
1476
            //insert media type properties into another table
1477
            if(mediaType != null && mediaType.getPropertyList() != null) {
1478
                String sql2 = "insert into smmediatypeproperties " +
1479
                        "(guid, name, value) " + "values (?, ?, ?)";
1480
                stmt2 = dbConn.prepareStatement(sql2);
1481
                for(MediaTypeProperty item : mediaType.getPropertyList()) {
1482
                    if(item != null) {
1483
                        String name = item.getName();
1484
                        String value = item.getValue();
1485
                        stmt2.setString(1, guid);
1486
                        stmt2.setString(2, name);
1487
                        stmt2.setString(3, value);
1488
                        logMetacat.debug("insert media type properties query: " + stmt2.toString());
1489
                        int row =stmt2.executeUpdate();
1490
                    }
1491
1492
                }
1493
            }
1494
            dbConn.commit();
1495
            dbConn.setAutoCommit(true);
1496
        } catch (Exception e) {
1497
            dbConn.rollback();
1498
            dbConn.setAutoCommit(true);
1499 9342 tao
            e.printStackTrace();
1500 9230 tao
            throw new SQLException(e.getMessage());
1501
        } finally {
1502
            if(stmt != null) {
1503
                stmt.close();
1504
            }
1505
            if(stmt2 != null) {
1506
                stmt2.close();
1507
            }
1508
        }
1509 6892 cjones
1510 7188 leinfelder
1511
    }
1512
1513
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes, DBConnection dbConn) throws SQLException
1514
    {
1515
1516
        // remove existing values first
1517 7392 leinfelder
        String delete = "delete from smReplicationPolicy " +
1518 7188 leinfelder
        "where guid = ? and policy = ?";
1519
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1520
        //data values
1521
        stmt.setString(1, guid);
1522
        stmt.setString(2, policy);
1523
        //execute
1524
        int deletedCount = stmt.executeUpdate();
1525
        stmt.close();
1526 5957 berkley
1527 7188 leinfelder
        for (String memberNode: memberNodes) {
1528 5887 berkley
            // Execute the insert statement
1529 7392 leinfelder
            String insert = "insert into smReplicationPolicy " +
1530 7188 leinfelder
                "(guid, policy, member_node) " +
1531
                "values (?, ?, ?)";
1532
            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1533 5887 berkley
1534
            //data values
1535 7188 leinfelder
            insertStatement.setString(1, guid);
1536
            insertStatement.setString(2, policy);
1537
            insertStatement.setString(3, memberNode);
1538
1539 7392 leinfelder
            logMetacat.debug("smReplicationPolicy sql: " + insertStatement.toString());
1540 6375 leinfelder
1541 5887 berkley
            //execute
1542 7188 leinfelder
            int rows = insertStatement.executeUpdate();
1543
            insertStatement.close();
1544 5887 berkley
        }
1545 7188 leinfelder
1546 5887 berkley
    }
1547
1548 7188 leinfelder
    private void insertReplicationStatus(String guid, List<Replica> replicas, DBConnection dbConn) throws SQLException {
1549
1550
        // remove existing values first
1551 7392 leinfelder
        String delete = "delete from smReplicationStatus " +
1552 7188 leinfelder
        "where guid = ?";
1553
        PreparedStatement stmt = dbConn.prepareStatement(delete);
1554
        //data values
1555
        stmt.setString(1, guid);
1556
        //execute
1557
        int deletedCount = stmt.executeUpdate();
1558
        stmt.close();
1559 6107 leinfelder
1560 7188 leinfelder
        if (replicas != null) {
1561
            for (Replica replica: replicas) {
1562 6107 leinfelder
	            // Execute the insert statement
1563 7392 leinfelder
	            String insert = "insert into smReplicationStatus " +
1564 7188 leinfelder
	                "(guid, member_node, status, date_verified) " +
1565
	                "values (?, ?, ?, ?)";
1566 6107 leinfelder
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1567
1568
	            //data values
1569 7188 leinfelder
	            String memberNode = replica.getReplicaMemberNode().getValue();
1570
	            String status = replica.getReplicationStatus().toString();
1571 7399 cjones
	            java.sql.Timestamp sqlDate = new java.sql.Timestamp(replica.getReplicaVerified().getTime());
1572 6107 leinfelder
	            insertStatement.setString(1, guid);
1573 7188 leinfelder
	            insertStatement.setString(2, memberNode);
1574
	            insertStatement.setString(3, status);
1575 7399 cjones
	            insertStatement.setTimestamp(4, sqlDate);
1576 7188 leinfelder
1577 7392 leinfelder
	            logMetacat.debug("smReplicationStatus sql: " + insertStatement.toString());
1578 7102 leinfelder
1579 6107 leinfelder
	            //execute
1580
	            int rows = insertStatement.executeUpdate();
1581
	            insertStatement.close();
1582
            }
1583
        }
1584 7188 leinfelder
1585 6107 leinfelder
    }
1586
1587 5334 berkley
    /**
1588 5887 berkley
     * Insert the system metadata fields into the db
1589
     * @param sm
1590 6108 leinfelder
     * @throws McdbDocNotFoundException
1591 6892 cjones
     * @throws SQLException
1592 6904 cjones
     * @throws InvalidSystemMetadata
1593 7188 leinfelder
     * @throws AccessException
1594 5887 berkley
     */
1595 7188 leinfelder
    public void updateSystemMetadata(SystemMetadata sm, DBConnection dbConn)
1596
      throws McdbDocNotFoundException, SQLException, InvalidSystemMetadata, AccessException {
1597 6107 leinfelder
1598 6892 cjones
      Boolean replicationAllowed = false;
1599
		  Integer numberReplicas = -1;
1600 6107 leinfelder
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1601
    	if (replicationPolicy != null) {
1602
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1603
    		numberReplicas = replicationPolicy.getNumberReplicas();
1604
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1605
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1606
    	}
1607 6904 cjones
1608 6107 leinfelder
    	// the main systemMetadata fields
1609 6892 cjones
		  updateSystemMetadataFields(
1610 6311 leinfelder
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1611
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(),
1612
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(),
1613 6397 leinfelder
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm(),
1614 6311 leinfelder
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1615
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(),
1616
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1617
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(),
1618 6904 cjones
		    sm.getIdentifier().getValue(),
1619
		    sm.getFormatId() == null ? null: sm.getFormatId().getValue(),
1620
		    sm.getSize(),
1621
		    sm.getArchived() == null ? false: sm.getArchived(),
1622
		    replicationAllowed,
1623
		    numberReplicas,
1624
		    sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
1625
		    sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue(),
1626 7188 leinfelder
		    sm.getSerialVersion(),
1627 8810 leinfelder
		    sm.getSeriesId() == null ? null: sm.getSeriesId().getValue(),
1628 9230 tao
		    sm.getFileName() == null ? null: sm.getFileName(),
1629
		    sm.getMediaType() == null ? null: sm.getMediaType(),
1630 7188 leinfelder
		    dbConn
1631 6561 leinfelder
        );
1632 6097 leinfelder
1633
        String guid = sm.getIdentifier().getValue();
1634
1635 6107 leinfelder
        // save replication policies
1636
        if (replicationPolicy != null) {
1637
		    List<String> nodes = null;
1638
		    String policy = null;
1639
1640 6494 leinfelder
		    // check for null
1641
		    if (replicationPolicy.getBlockedMemberNodeList() != null) {
1642
			    nodes = new ArrayList<String>();
1643
			    policy = "blocked";
1644
			    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1645
			    	nodes.add(node.getValue());
1646
			    }
1647 7188 leinfelder
			    this.insertReplicationPolicy(guid, policy, nodes, dbConn);
1648 6107 leinfelder
		    }
1649
1650 6494 leinfelder
		    if (replicationPolicy.getPreferredMemberNodeList() != null) {
1651
			    nodes = new ArrayList<String>();
1652
			    policy = "preferred";
1653
			    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1654
			    	nodes.add(node.getValue());
1655
			    }
1656 7188 leinfelder
		        this.insertReplicationPolicy(guid, policy, nodes, dbConn);
1657 6107 leinfelder
		    }
1658
        }
1659 6097 leinfelder
1660 6107 leinfelder
        // save replica information
1661 7188 leinfelder
        this.insertReplicationStatus(guid, sm.getReplicaList(), dbConn);
1662 6107 leinfelder
1663 6108 leinfelder
        // save access policy
1664
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1665
        if (accessPolicy != null) {
1666 7188 leinfelder
			this.insertAccessPolicy(guid, accessPolicy);
1667 6108 leinfelder
        }
1668 5887 berkley
    }
1669
1670
    /**
1671 6108 leinfelder
     * Creates Metacat access rules and inserts them
1672
     * @param accessPolicy
1673
     * @throws McdbDocNotFoundException
1674
     * @throws AccessException
1675
     */
1676
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1677
1678 6744 leinfelder
    	// check for the existing permOrder so that we remain compatible with it (DataONE does not care)
1679
        XMLAccessAccess accessController  = new XMLAccessAccess();
1680
		String existingPermOrder = AccessControlInterface.ALLOWFIRST;
1681
        Vector<XMLAccessDAO> existingAccess = accessController.getXMLAccessForDoc(guid);
1682
        if (existingAccess != null && existingAccess.size() > 0) {
1683
        	existingPermOrder = existingAccess.get(0).getPermOrder();
1684
        }
1685
1686 6108 leinfelder
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1687
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1688
        	List<Subject> subjects = accessRule.getSubjectList();
1689
        	List<Permission> permissions = accessRule.getPermissionList();
1690
        	for (Subject subject: subjects) {
1691 6122 leinfelder
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1692
        		accessDAO.setPrincipalName(subject.getValue());
1693
    			accessDAO.setGuid(guid);
1694
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1695 6744 leinfelder
				accessDAO.setPermOrder(existingPermOrder);
1696
    			if (permissions != null) {
1697
	    			for (Permission permission: permissions) {
1698
	    				Long metacatPermission = new Long(convertPermission(permission));
1699
	        			accessDAO.addPermission(metacatPermission);
1700
	    			}
1701 6122 leinfelder
    			}
1702
    			accessDAOs.add(accessDAO);
1703 6108 leinfelder
        	}
1704
        }
1705
1706
1707 6744 leinfelder
        // remove all existing allow records
1708
        accessController.deleteXMLAccessForDoc(guid, AccessControlInterface.ALLOW);
1709
        // add the ones we can for this guid
1710
        accessController.insertAccess(guid, accessDAOs);
1711 6108 leinfelder
1712 6744 leinfelder
1713 6108 leinfelder
    }
1714
1715
    /**
1716
     * Lookup access policy from Metacat
1717
     * @param guid
1718
     * @return
1719
     * @throws McdbDocNotFoundException
1720
     * @throws AccessException
1721
     */
1722 6720 leinfelder
    public AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1723 6450 leinfelder
        AccessPolicy accessPolicy = new AccessPolicy();
1724
1725 6122 leinfelder
    	// use GUID to look up the access
1726 6744 leinfelder
        XMLAccessAccess accessController  = new XMLAccessAccess();
1727 6720 leinfelder
        List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1728
1729 6108 leinfelder
        for (XMLAccessDAO accessDAO: accessDAOs) {
1730 6744 leinfelder
        	// only add allow rule
1731
        	if (accessDAO.getPermType().equals(AccessControlInterface.ALLOW)) {
1732
	        	AccessRule accessRule = new AccessRule();
1733
	        	List <Permission> permissions = convertPermission(accessDAO.getPermission().intValue());
1734 7088 leinfelder
	        	// cannot include if we have no permissions
1735
	        	if (permissions == null || permissions.isEmpty()) {
1736
	        		logMetacat.warn("skipping empty access rule permissions for " + guid);
1737
	        		continue;
1738
	        	}
1739 6744 leinfelder
	        	accessRule.setPermissionList(permissions);
1740
	        	Subject subject = new Subject();
1741
	        	subject.setValue(accessDAO.getPrincipalName());
1742
	        	accessRule.addSubject(subject);
1743
	            accessPolicy.addAllow(accessRule);
1744
        	}
1745 6108 leinfelder
        }
1746
        return accessPolicy;
1747
    }
1748
1749
    public int convertPermission(Permission permission) {
1750
    	if (permission.equals(Permission.READ)) {
1751
    		return AccessControlInterface.READ;
1752
    	}
1753
    	if (permission.equals(Permission.WRITE)) {
1754
    		return AccessControlInterface.WRITE;
1755
    	}
1756
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1757 9780 cjones
    		// implies all permission, rather than just CHMOD
1758
    		return AccessControlInterface.ALL;
1759 6108 leinfelder
    	}
1760
		return -1;
1761
    }
1762
1763 6722 leinfelder
    public List<Permission> convertPermission(int permission) {
1764 6744 leinfelder
1765 6722 leinfelder
    	List<Permission> permissions = new ArrayList<Permission>();
1766 6744 leinfelder
    	if (permission == AccessControlInterface.ALL) {
1767 6722 leinfelder
    		permissions.add(Permission.READ);
1768
    		permissions.add(Permission.WRITE);
1769 6744 leinfelder
    		permissions.add(Permission.CHANGE_PERMISSION);
1770 6722 leinfelder
    		return permissions;
1771 6108 leinfelder
    	}
1772 6744 leinfelder
1773
    	if ((permission & AccessControlInterface.CHMOD) == AccessControlInterface.CHMOD) {
1774 6722 leinfelder
    		permissions.add(Permission.CHANGE_PERMISSION);
1775 6108 leinfelder
    	}
1776 6744 leinfelder
    	if ((permission & AccessControlInterface.READ) == AccessControlInterface.READ) {
1777 6722 leinfelder
    		permissions.add(Permission.READ);
1778 6744 leinfelder
    	}
1779
    	if ((permission & AccessControlInterface.WRITE) == AccessControlInterface.WRITE) {
1780 6722 leinfelder
    		permissions.add(Permission.WRITE);
1781 6720 leinfelder
    	}
1782 6744 leinfelder
1783
		return permissions;
1784 6108 leinfelder
    }
1785
1786
    /**
1787 6099 leinfelder
     * Lookup a localId given the GUID. If
1788
     * the identifier is not found, throw an exception.
1789
     *
1790
     * @param guid the global identifier to look up
1791
     * @return String containing the corresponding LocalId
1792
     * @throws McdbDocNotFoundException if the identifier is not found
1793 5334 berkley
     */
1794 9024 tao
    public String getLocalId(String guid) throws McdbDocNotFoundException, SQLException {
1795 5334 berkley
1796
      String db_guid = "";
1797
      String docid = "";
1798
      int rev = 0;
1799
1800 6099 leinfelder
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1801 5334 berkley
1802
      DBConnection dbConn = null;
1803 5333 berkley
      int serialNumber = -1;
1804 5334 berkley
      try {
1805
          // Get a database connection from the pool
1806
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1807
          serialNumber = dbConn.getCheckOutSerialNumber();
1808
1809
          // Execute the insert statement
1810
          PreparedStatement stmt = dbConn.prepareStatement(query);
1811
          stmt.setString(1, guid);
1812
          ResultSet rs = stmt.executeQuery();
1813
          if (rs.next()) {
1814
              db_guid = rs.getString(1);
1815
              docid = rs.getString(2);
1816
              rev = rs.getInt(3);
1817
              assert(db_guid.equals(guid));
1818
          } else {
1819
              throw new McdbDocNotFoundException("Document not found:" + guid);
1820
          }
1821
          stmt.close();
1822
      } catch (SQLException e) {
1823
          logMetacat.error("Error while looking up the local identifier: "
1824
                  + e.getMessage());
1825 9024 tao
          throw e;
1826 5334 berkley
      } finally {
1827
          // Return database connection to the pool
1828
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1829
      }
1830
      return docid + "." + rev;
1831
    }
1832
1833 5377 berkley
    /**
1834 5895 berkley
     * query the systemmetadata table based on the given parameters
1835
     * @param startTime
1836
     * @param endTime
1837
     * @param objectFormat
1838 9249 tao
     * @param nodeId
1839 5895 berkley
     * @param start
1840
     * @param count
1841
     * @return ObjectList
1842 6299 leinfelder
     * @throws SQLException
1843
     * @throws ServiceException
1844
     * @throws PropertyNotFoundException
1845 5895 berkley
     */
1846 6836 cjones
    public ObjectList querySystemMetadata(Date startTime, Date endTime,
1847 9249 tao
        ObjectFormatIdentifier objectFormatId, NodeReference nodeId,
1848 9072 tao
        int start, int count, Identifier identifier, boolean isSID)
1849 6836 cjones
        throws SQLException, PropertyNotFoundException, ServiceException {
1850 5895 berkley
        ObjectList ol = new ObjectList();
1851 5943 berkley
        DBConnection dbConn = null;
1852
        int serialNumber = -1;
1853 9307 tao
        PreparedStatement countStmt=null;
1854
        ResultSet totalResult=null;
1855
        PreparedStatement fieldStmt = null;
1856
        ResultSet rs= null;
1857 6836 cjones
1858 6299 leinfelder
        try {
1859 7452 leinfelder
            String fieldSql = "select guid, date_uploaded, rights_holder, checksum, "
1860 6836 cjones
                    + "checksum_algorithm, origin_member_node, authoritive_member_node, "
1861
                    + "date_modified, submitter, object_format, size from systemmetadata";
1862 7410 leinfelder
1863
            // handle special case quickly
1864
            String countSql = "select count(guid) from systemmetadata";
1865 7452 leinfelder
1866
            // the clause
1867
            String whereClauseSql = "";
1868 9307 tao
1869 6836 cjones
1870 5895 berkley
            boolean f1 = false;
1871
            boolean f2 = false;
1872
            boolean f3 = false;
1873 9072 tao
            boolean f4 = false;
1874 10239 tao
            boolean f5 = false;
1875 6836 cjones
1876 9072 tao
1877 6299 leinfelder
            if (startTime != null) {
1878 7452 leinfelder
                whereClauseSql += " where systemmetadata.date_modified >= ?";
1879 5895 berkley
                f1 = true;
1880
            }
1881 6836 cjones
1882 6299 leinfelder
            if (endTime != null) {
1883
                if (!f1) {
1884 7452 leinfelder
                    whereClauseSql += " where systemmetadata.date_modified < ?";
1885 6836 cjones
                } else {
1886 7452 leinfelder
                    whereClauseSql += " and systemmetadata.date_modified < ?";
1887 5917 berkley
                }
1888 5895 berkley
                f2 = true;
1889
            }
1890 6836 cjones
1891 6337 leinfelder
            if (objectFormatId != null) {
1892 6299 leinfelder
                if (!f1 && !f2) {
1893 7452 leinfelder
                    whereClauseSql += " where object_format = ?";
1894 6836 cjones
                } else {
1895 7452 leinfelder
                    whereClauseSql += " and object_format = ?";
1896 5917 berkley
                }
1897 5895 berkley
                f3 = true;
1898
            }
1899 9072 tao
1900
            if(identifier != null && identifier.getValue() != null && !identifier.getValue().equals("")) {
1901
                if (!f1 && !f2 && !f3 ) {
1902
                    if(isSID) {
1903
                        whereClauseSql += " where series_id = ?";
1904
                    } else {
1905
                        whereClauseSql += " where guid = ?";
1906
                    }
1907
1908
                } else {
1909
                    if(isSID) {
1910
                        whereClauseSql += " and series_id = ?";
1911
                    } else {
1912
                        whereClauseSql += " and guid = ?";
1913
                    }
1914
                }
1915
                f4 = true;
1916
            }
1917 6836 cjones
1918 9249 tao
            /*if (!replicaStatus) {
1919 7030 cjones
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.nodeId");
1920 9072 tao
                if (!f1 && !f2 && !f3 && !f4) {
1921 7462 leinfelder
                    whereClauseSql += " where authoritive_member_node = '" +
1922 6836 cjones
                        currentNodeId.trim() + "'";
1923
                } else {
1924 7462 leinfelder
                    whereClauseSql += " and authoritive_member_node = '" +
1925 6836 cjones
                        currentNodeId.trim() + "'";
1926 5917 berkley
                }
1927 9249 tao
            }*/
1928
1929
            if (nodeId != null && nodeId.getValue() != null && !nodeId.getValue().trim().equals("")) {
1930
                if (!f1 && !f2 && !f3 && !f4) {
1931
                    whereClauseSql += " where authoritive_member_node = '" +
1932
                        nodeId.getValue().trim() + "'";
1933
                } else {
1934
                    whereClauseSql += " and authoritive_member_node = '" +
1935
                        nodeId.getValue().trim() + "'";
1936
                }
1937 10239 tao
                f5 = true;
1938 5895 berkley
            }
1939 10239 tao
1940
          //add a filter to remove pids whith white spaces
1941
            if(filterWhiteSpaces) {
1942
                logMetacat.debug("IdnetifierManager.querySystemMetadata - the default value of the property \"dataone.listingidentifier.filteringwhitespaces\" is true, so we will filter the white spaces in the query");
1943
                if(!f1 && !f2 && !f3 && !f4 && !f5) {
1944
                    whereClauseSql += " where guid not like '% %' ";
1945
                } else {
1946
                    whereClauseSql += " and guid not like '% %' ";
1947
                }
1948
            } else {
1949
                logMetacat.debug("IdnetifierManager.querySystemMetadata - the property \"dataone.listingidentifier.filteringwhitespaces\" is configured to be false, so we don't filter the white spaces in the query.");
1950
            }
1951 9072 tao
1952
1953 7452 leinfelder
            // connection
1954 5943 berkley
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1955
            serialNumber = dbConn.getCheckOutSerialNumber();
1956 6836 cjones
1957 7452 leinfelder
            // the field query
1958
            String orderBySql = " order by guid ";
1959
            String fieldQuery = fieldSql + whereClauseSql + orderBySql;
1960
            String finalQuery = DatabaseService.getInstance().getDBAdapter().getPagedQuery(fieldQuery, start, count);
1961 9307 tao
            fieldStmt = dbConn.prepareStatement(finalQuery);
1962 7452 leinfelder
1963
            // construct the count query and statment
1964
            String countQuery = countSql + whereClauseSql;
1965 9307 tao
            countStmt = dbConn.prepareStatement(countQuery);
1966 7452 leinfelder
1967 9072 tao
            if (f1 && f2 && f3 && f4) {
1968 7452 leinfelder
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1969
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1970
                fieldStmt.setString(3, objectFormatId.getValue());
1971 9072 tao
                fieldStmt.setString(4, identifier.getValue());
1972 7452 leinfelder
                // count
1973
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1974
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1975
                countStmt.setString(3, objectFormatId.getValue());
1976 9072 tao
                countStmt.setString(4, identifier.getValue());
1977
            } if (f1 && f2 && f3 && !f4) {
1978 7452 leinfelder
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1979
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1980 9072 tao
                fieldStmt.setString(3, objectFormatId.getValue());
1981 7452 leinfelder
                // count
1982
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1983
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1984 9072 tao
                countStmt.setString(3, objectFormatId.getValue());
1985
            } else if (f1 && f2 && !f3 && f4) {
1986 7452 leinfelder
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1987 9072 tao
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1988
                fieldStmt.setString(3, identifier.getValue());
1989
                // count
1990
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1991
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1992
                countStmt.setString(3, identifier.getValue());
1993
            } else if (f1 && f2 && !f3 && !f4) {
1994
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1995
                fieldStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1996
                // count
1997
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1998
                countStmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1999
            } else if (f1 && !f2 && f3 && f4) {
2000
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2001 7452 leinfelder
                fieldStmt.setString(2, objectFormatId.getValue());
2002 9072 tao
                fieldStmt.setString(3, identifier.getValue());
2003 7452 leinfelder
                // count
2004
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2005
                countStmt.setString(2, objectFormatId.getValue());
2006 9072 tao
                countStmt.setString(3, identifier.getValue());
2007
            } else if (f1 && !f2 && f3 && !f4) {
2008 7452 leinfelder
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2009 9072 tao
                fieldStmt.setString(2, objectFormatId.getValue());
2010 7452 leinfelder
                // count
2011
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2012 9072 tao
                countStmt.setString(2, objectFormatId.getValue());
2013
            } else if (f1 && !f2 && !f3 && f4) {
2014
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2015
                fieldStmt.setString(2, identifier.getValue());
2016
                // count
2017
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2018
                countStmt.setString(2, identifier.getValue());
2019
            } else if (f1 && !f2 && !f3 && !f4) {
2020
                fieldStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2021
                // count
2022
                countStmt.setTimestamp(1, new Timestamp(startTime.getTime()));
2023
            } else if (!f1 && f2 && f3 && f4) {
2024 7452 leinfelder
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2025
                fieldStmt.setString(2, objectFormatId.getValue());
2026 9072 tao
                fieldStmt.setString(3, identifier.getValue());
2027 7452 leinfelder
                // count
2028
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2029
                countStmt.setString(2, objectFormatId.getValue());
2030 9072 tao
                countStmt.setString(3, identifier.getValue());
2031
            } else if (!f1 && f2 && f3 && !f4) {
2032
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2033
                fieldStmt.setString(2, objectFormatId.getValue());
2034
                // count
2035
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2036
                countStmt.setString(2, objectFormatId.getValue());
2037
            } else if (!f1 && !f2 && f3 && f4) {
2038 7452 leinfelder
                fieldStmt.setString(1, objectFormatId.getValue());
2039 9072 tao
                fieldStmt.setString(2, identifier.getValue());
2040 7452 leinfelder
                // count
2041
                countStmt.setString(1, objectFormatId.getValue());
2042 9072 tao
                countStmt.setString(2, identifier.getValue());
2043
            } else if (!f1 && !f2 && f3 && !f4) {
2044
                fieldStmt.setString(1, objectFormatId.getValue());
2045
                // count
2046
                countStmt.setString(1, objectFormatId.getValue());
2047
            } else if (!f1 && f2 && !f3 && f4) {
2048 7452 leinfelder
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2049 9072 tao
                fieldStmt.setString(2, identifier.getValue());
2050 7452 leinfelder
                // count
2051
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2052 9072 tao
                countStmt.setString(2, identifier.getValue());
2053
            } else if (!f1 && f2 && !f3 && !f4) {
2054
                fieldStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2055
                // count
2056
                countStmt.setTimestamp(1, new Timestamp(endTime.getTime()));
2057
            } else if (!f1 && !f2 && !f3 && f4) {
2058
                fieldStmt.setString(1, identifier.getValue());
2059
                // count
2060
                countStmt.setString(1, identifier.getValue());
2061
            } else if (!f1 && !f2 && !f3 && !f4) {
2062
                //do nothing
2063 5895 berkley
            }
2064 6836 cjones
2065 10239 tao
            logMetacat.info("list objects fieldStmt: " + fieldStmt.toString());
2066 7461 leinfelder
2067 10239 tao
            logMetacat.info("list objects countStmt: " + countStmt.toString());
2068 7461 leinfelder
2069 7452 leinfelder
            // get the total object count no matter what
2070
            int total = 0;
2071 9307 tao
            totalResult = countStmt.executeQuery();
2072 7452 leinfelder
            if (totalResult.next()) {
2073
            	total = totalResult.getInt(1);
2074 5895 berkley
            }
2075 7438 leinfelder
2076 7461 leinfelder
            logMetacat.debug("list objects total: " + total);
2077
2078 7452 leinfelder
        	// set the totals
2079
        	ol.setStart(start);
2080
            ol.setCount(count);
2081
2082
            // retrieve the actual records if requested
2083
            if (count != 0) {
2084
2085 9307 tao
                rs = fieldStmt.executeQuery();
2086 7410 leinfelder
	            while (rs.next()) {
2087 7438 leinfelder
2088 7410 leinfelder
	                String guid = rs.getString(1);
2089 7461 leinfelder
	                logMetacat.debug("query found object with guid " + guid);
2090 7410 leinfelder
	                // Timestamp dateUploaded = rs.getTimestamp(2);
2091
	                // String rightsHolder = rs.getString(3);
2092
	                String checksum = rs.getString(4);
2093
	                String checksumAlgorithm = rs.getString(5);
2094
	                // String originMemberNode = rs.getString(6);
2095
	                // String authoritiveMemberNode = rs.getString(7);
2096
	                Timestamp dateModified = rs.getTimestamp(8);
2097
	                // String submitter = rs.getString(9);
2098
	                String fmtidStr = rs.getString(10);
2099
	                String sz = rs.getString(11);
2100
	                BigInteger size = new BigInteger("0");
2101
2102
	                if (sz != null && !sz.trim().equals("")) {
2103
	                    size = new BigInteger(rs.getString(11));
2104
	                }
2105
2106
	                ObjectInfo oi = new ObjectInfo();
2107
2108
	                Identifier id = new Identifier();
2109
	                id.setValue(guid);
2110
	                oi.setIdentifier(id);
2111
2112
	                if (dateModified != null) {
2113
	                    oi.setDateSysMetadataModified(dateModified);
2114
	                }
2115
2116
	                Checksum cs = new Checksum();
2117
	                cs.setValue(checksum);
2118
	                try {
2119
	                    // cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
2120
	                    cs.setAlgorithm(checksumAlgorithm);
2121
	                } catch (Exception e) {
2122
	                    logMetacat.error("could not parse checksum algorithm", e);
2123
	                    continue;
2124
	                }
2125
	                oi.setChecksum(cs);
2126
2127
	                // set the format type
2128
	                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
2129
	                fmtid.setValue(fmtidStr);
2130
	                oi.setFormatId(fmtid);
2131
2132
	                oi.setSize(size);
2133 9307 tao
2134 7438 leinfelder
	                ol.addObjectInfo(oi);
2135
2136 7410 leinfelder
	            }
2137 7452 leinfelder
2138 7461 leinfelder
	            logMetacat.debug("list objects count: " + ol.sizeObjectInfoList());
2139 7452 leinfelder
	            // set the actual count retrieved
2140
	            ol.setCount(ol.sizeObjectInfoList());
2141 9308 tao
2142 7410 leinfelder
2143
	        }
2144 9308 tao
            ol.setTotal(total);
2145 9307 tao
        } finally {
2146 5943 berkley
            // Return database connection to the pool
2147 9307 tao
            try {
2148
                if(totalResult !=null ){
2149
                    totalResult.close();
2150
                }
2151
                if(countStmt!=null ) {
2152
                    countStmt.close();
2153
                }
2154
                if(rs != null) {
2155
                    rs.close();
2156
                }
2157
                if(fieldStmt != null) {
2158
                    fieldStmt.close();
2159
                }
2160
2161
            } catch (SQLException sql) {
2162
2163
            }
2164 5943 berkley
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2165 9307 tao
2166 5943 berkley
        }
2167 9307 tao
        if(ol != null) {
2168
            logMetacat.debug("list objects start(before returning): " + ol.getStart());
2169
            logMetacat.debug("list objects count: " + ol.getCount());
2170
            logMetacat.debug("list objects total: " + ol.getTotal());
2171
        }
2172 5895 berkley
        return ol;
2173
    }
2174
2175
    /**
2176 6099 leinfelder
     * create a mapping in the identifier table
2177 5377 berkley
     * @param guid
2178
     * @param localId
2179
     */
2180 6099 leinfelder
    public void createMapping(String guid, String localId)
2181 5453 berkley
    {
2182 5334 berkley
2183
        int serialNumber = -1;
2184 5333 berkley
        DBConnection dbConn = null;
2185
        try {
2186
2187
            // Parse the localId into scope and rev parts
2188
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
2189
            String docid = acc.getDocid();
2190 5344 berkley
            int rev = 1;
2191 6099 leinfelder
            if (acc.getRev() != null) {
2192 5344 berkley
              rev = (new Integer(acc.getRev()).intValue());
2193
            }
2194 5333 berkley
2195
            // Get a database connection from the pool
2196 6099 leinfelder
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
2197 5333 berkley
            serialNumber = dbConn.getCheckOutSerialNumber();
2198
2199
            // Execute the insert statement
2200 6099 leinfelder
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
2201 5333 berkley
            PreparedStatement stmt = dbConn.prepareStatement(query);
2202
            stmt.setString(1, guid);
2203
            stmt.setString(2, docid);
2204
            stmt.setInt(3, rev);
2205 6099 leinfelder
            logMetacat.debug("mapping query: " + stmt.toString());
2206 5333 berkley
            int rows = stmt.executeUpdate();
2207
2208
            stmt.close();
2209
        } catch (SQLException e) {
2210 5344 berkley
            e.printStackTrace();
2211 6099 leinfelder
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: "
2212 5333 berkley
                    + e.getMessage());
2213
        } catch (NumberFormatException e) {
2214 5344 berkley
            e.printStackTrace();
2215 6099 leinfelder
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: "
2216 5333 berkley
                    + e.getMessage());
2217
        } catch (AccessionNumberException e) {
2218 5344 berkley
            e.printStackTrace();
2219 6099 leinfelder
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: "
2220 5333 berkley
                    + e.getMessage());
2221
        } finally {
2222
            // Return database connection to the pool
2223
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2224
        }
2225
    }
2226 6099 leinfelder
2227
    /**
2228 7017 leinfelder
     * remove a mapping in the identifier table
2229
     * @param guid
2230
     * @param localId
2231
     */
2232
    public void removeMapping(String guid, String localId)
2233
    {
2234
2235
        int serialNumber = -1;
2236
        DBConnection dbConn = null;
2237
        try {
2238
2239
            // Parse the localId into scope and rev parts
2240
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
2241
            String docid = acc.getDocid();
2242
            int rev = 1;
2243
            if (acc.getRev() != null) {
2244
              rev = (new Integer(acc.getRev()).intValue());
2245
            }
2246
2247
            // Get a database connection from the pool
2248
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.removeMapping");
2249
            serialNumber = dbConn.getCheckOutSerialNumber();
2250
2251
            // Execute the insert statement
2252
            String query = "DELETE FROM " + TYPE_IDENTIFIER + " WHERE guid = ? AND docid = ? AND rev = ?";
2253
            PreparedStatement stmt = dbConn.prepareStatement(query);
2254
            stmt.setString(1, guid);
2255
            stmt.setString(2, docid);
2256
            stmt.setInt(3, rev);
2257
            logMetacat.debug("remove mapping query: " + stmt.toString());
2258
            int rows = stmt.executeUpdate();
2259
2260
            stmt.close();
2261
        } catch (SQLException e) {
2262
            e.printStackTrace();
2263
            logMetacat.error("removeMapping: SQL error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: "
2264
                    + e.getMessage());
2265
        } catch (NumberFormatException e) {
2266
            e.printStackTrace();
2267
            logMetacat.error("removeMapping: NumberFormat error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: "
2268
                    + e.getMessage());
2269
        } catch (AccessionNumberException e) {
2270
            e.printStackTrace();
2271
            logMetacat.error("removeMapping: AccessionNumber error while removing a mapping to the " + TYPE_IDENTIFIER + " identifier: "
2272
                    + e.getMessage());
2273
        } finally {
2274
            // Return database connection to the pool
2275
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2276
        }
2277
    }
2278
2279
    /**
2280 6099 leinfelder
     * create the systemmetadata record
2281
     * @param guid
2282 7188 leinfelder
     * @param dbConn
2283
     * @throws SQLException
2284 6099 leinfelder
     */
2285 7188 leinfelder
    private void insertSystemMetadata(String guid, DBConnection dbConn) throws SQLException
2286 6099 leinfelder
    {
2287
2288 7188 leinfelder
        // Execute the insert statement
2289
        String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
2290
        PreparedStatement stmt = dbConn.prepareStatement(query);
2291
        stmt.setString(1, guid);
2292
        logMetacat.debug("system metadata query: " + stmt.toString());
2293
        int rows = stmt.executeUpdate();
2294 6099 leinfelder
2295 7188 leinfelder
        stmt.close();
2296
2297 6099 leinfelder
    }
2298 6277 leinfelder
2299 8852 tao
    public boolean deleteSystemMetadata(String guid)
2300 6277 leinfelder
    {
2301 8852 tao
        boolean success = false;
2302 6277 leinfelder
        int serialNumber = -1;
2303
        DBConnection dbConn = null;
2304 6648 leinfelder
        String query = null;
2305
        PreparedStatement stmt = null;
2306
        int rows = 0;
2307 6277 leinfelder
        try {
2308
2309 8852 tao
        	 // Get a database connection from the pool
2310 6648 leinfelder
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.deleteSystemMetadata");
2311 6277 leinfelder
            serialNumber = dbConn.getCheckOutSerialNumber();
2312 8852 tao
            dbConn.setAutoCommit(false);
2313
2314 7392 leinfelder
            // remove the smReplicationPolicy
2315
            query = "delete from smReplicationPolicy " +
2316 6648 leinfelder
            "where guid = ?";
2317
            stmt = dbConn.prepareStatement(query);
2318
            stmt.setString(1, guid);
2319 7392 leinfelder
            logMetacat.debug("delete smReplicationPolicy: " + stmt.toString());
2320 6648 leinfelder
            rows = stmt.executeUpdate();
2321
            stmt.close();
2322
2323 7392 leinfelder
            // remove the smReplicationStatus
2324
            query = "delete from smReplicationStatus " +
2325 6648 leinfelder
            "where guid = ?";
2326
            stmt = dbConn.prepareStatement(query);
2327
            stmt.setString(1, guid);
2328 7392 leinfelder
            logMetacat.debug("delete smReplicationStatus: " + stmt.toString());
2329 6648 leinfelder
            rows = stmt.executeUpdate();
2330
            stmt.close();
2331
2332 9230 tao
            // remove the smmediatypeproperties
2333 10005 tao
            query = "delete from smMediaTypeProperties " +
2334 9230 tao
                    "where guid = ?";
2335
            stmt = dbConn.prepareStatement(query);
2336
            stmt.setString(1, guid);
2337 10005 tao
            logMetacat.debug("delete smMediaTypeProperties: " + stmt.toString());
2338 9230 tao
            rows = stmt.executeUpdate();
2339
            stmt.close();
2340
2341 10005 tao
            // remove the xml_access
2342
            query = "delete from xml_access " +
2343
                    "where guid = ?";
2344
            stmt = dbConn.prepareStatement(query);
2345
            stmt.setString(1, guid);
2346
            logMetacat.debug("delete xml_access: " + stmt.toString());
2347
            rows = stmt.executeUpdate();
2348
            stmt.close();
2349
2350 8852 tao
            // remove main system metadata entry
2351
            query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
2352
            stmt = dbConn.prepareStatement(query);
2353
            stmt.setString(1, guid);
2354
            logMetacat.debug("delete system metadata: " + stmt.toString());
2355
            rows = stmt.executeUpdate();
2356
            stmt.close();
2357
2358
            dbConn.commit();
2359
            dbConn.setAutoCommit(true);
2360
            success = true;
2361 6744 leinfelder
            // TODO: remove the access?
2362 6648 leinfelder
            // Metacat keeps "deleted" documents so we should not remove access rules.
2363
2364 6277 leinfelder
        } catch (Exception e) {
2365
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
2366 6648 leinfelder
            try {
2367
				dbConn.rollback();
2368
			} catch (SQLException sqle) {
2369
	            logMetacat.error("Error while rolling back delete for record: " + guid, sqle );
2370
			}
2371 6277 leinfelder
        } finally {
2372
            // Return database connection to the pool
2373
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2374
        }
2375 8852 tao
        return success;
2376 6277 leinfelder
    }
2377 6862 leinfelder
2378
    public void updateAuthoritativeMemberNodeId(String existingMemberNodeId, String newMemberNodeId)
2379
    {
2380
        DBConnection dbConn = null;
2381
        int serialNumber = -1;
2382
2383
        try {
2384
            // Get a database connection from the pool
2385
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.updateAuthoritativeMemberNodeId");
2386
            serialNumber = dbConn.getCheckOutSerialNumber();
2387
2388
            // Execute the insert statement
2389
            String query = "update " + TYPE_SYSTEM_METADATA +
2390
                " set authoritive_member_node = ? " +
2391
                " where authoritive_member_node = ?";
2392
            PreparedStatement stmt = dbConn.prepareStatement(query);
2393
2394
            //data values
2395
            stmt.setString(1, newMemberNodeId);
2396
            stmt.setString(2, existingMemberNodeId);
2397
2398
            logMetacat.debug("stmt: " + stmt.toString());
2399
            //execute
2400
            int rows = stmt.executeUpdate();
2401
2402
            stmt.close();
2403
        } catch (SQLException e) {
2404
            e.printStackTrace();
2405
            logMetacat.error("updateSystemMetadataFields: SQL error while updating system metadata: "
2406
                    + e.getMessage());
2407
        } catch (NumberFormatException e) {
2408
            e.printStackTrace();
2409
            logMetacat.error("updateSystemMetadataFields: NumberFormat error while updating system metadata: "
2410
                    + e.getMessage());
2411
        } finally {
2412
            // Return database connection to the pool
2413
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
2414
        }
2415
    }
2416 10123 tao
2417
    /**
2418
     * Determine if the object file exist for the given localId.
2419
     * @param localId
2420
     * @param isScienceMetadata
2421
     * @return
2422
     * @throws PropertyNotFoundException
2423
     */
2424
    public boolean objectFileExists(String localId, boolean isScienceMetadata) throws PropertyNotFoundException {
2425
        boolean exist =false;
2426
        if (localId != null) {
2427
            String documentPath = getObjectFilePath(localId, isScienceMetadata);
2428
            if(documentPath != null) {
2429
                File file = new File(documentPath);
2430
                exist = file.exists();
2431
            }
2432
        }
2433
        logMetacat.debug("IdentifierManager.ObjectFileExist - Does the object file for the local id "+localId+" which is science metadata "+isScienceMetadata+" exist in the Metacast file system? The answer is "+exist);
2434
        return exist;
2435
    }
2436
2437
    /**
2438
     *Get the the file path for the given object local id
2439
     * @param localId
2440
     * @param isScienceMetadata
2441
     * @return
2442
     * @throws PropertyNotFoundException
2443
     */
2444
    public String getObjectFilePath(String localId, boolean isScienceMetadata) throws PropertyNotFoundException {
2445
        String documentPath = null;
2446
        if (localId != null) {
2447
            String documentDir = null;
2448
            // get the correct location on disk
2449
            if (isScienceMetadata) {
2450
                documentDir = PropertyService.getProperty("application.documentfilepath");
2451
            } else {
2452
                documentDir = PropertyService.getProperty("application.datafilepath");
2453
            }
2454
            documentPath = documentDir + FileUtil.getFS() + localId;
2455
        }
2456
        logMetacat.debug("IdentifierManager.getObjectFilePath - the file path for the object with localId "+localId+" which is scienceMetacat "+isScienceMetadata+", is "+documentPath+". If the value is null, this means we can't find it.");
2457
        return documentPath;
2458
    }
2459 10185 tao
2460
    /**
2461
     * IF the given localId exists on the xml_revisions table
2462
     * @param localId
2463
     * @return
2464
     * @throws SQLException
2465
     */
2466
    public boolean existsInXmlLRevisionTable(String docid, int rev) throws SQLException{
2467
        boolean exist =false;
2468
        DBConnection conn = null;
2469
        int serialNumber = -1;
2470
        PreparedStatement pstmt = null;
2471
        ResultSet rs = null;
2472
        logMetacat.info("IdentifierManager.existsInXmlLRevisionTable - the docid is "+docid +" and rev is "+rev);
2473
        try {
2474
            //check out DBConnection
2475
            conn = DBConnectionPool.getDBConnection("IdentifierManager.existsInXmlLRevisionTable");
2476
            serialNumber = conn.getCheckOutSerialNumber();
2477
            // Check if the document exists in xml_revisions table.
2478
            //this only archives a document from xml_documents to xml_revisions (also archive the xml_nodes table as well)
2479
            logMetacat.debug("IdentifierManager.existsInXmlLRevisionTable - check if the document "+docid+"."+rev+ " exists in the xml_revision table");
2480
            pstmt = conn.prepareStatement("SELECT rev, docid FROM xml_revisions WHERE docid = ? AND rev = ?");
2481
            pstmt.setString(1, docid);
2482
            pstmt.setInt(2, rev);
2483
            logMetacat.debug("IdentifierManager.existsInXmlLRevisionTable - executing SQL: " + pstmt.toString());
2484
            pstmt.execute();
2485
            rs = pstmt.getResultSet();
2486
            if(rs.next()){
2487
                exist = true;
2488
            }
2489
            conn.increaseUsageCount(1);
2490
        } catch (Exception e) {
2491
            throw new SQLException(e.getMessage());
2492
        } finally {
2493
            // Return database connection to the pool
2494
            DBConnectionPool.returnDBConnection(conn, serialNumber);
2495
            if(rs != null) {
2496
                rs.close();
2497
            }
2498
            if(pstmt != null) {
2499
                pstmt.close();
2500
            }
2501
        }
2502
        logMetacat.info("IdentifierManager.existsInXmlLRevisionTable - Does the docid "+docid+"."+rev+ " exist in the xml_revision table? - "+exist);
2503
        return exist;
2504
    }
2505 5282 jones
}