Project

General

Profile

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