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