View Javadoc

1   /*
2    * #%L
3    * Bitrepository Audit Trail Service
4    * %%
5    * Copyright (C) 2010 - 2012 The State and University Library, The Royal Library and The State Archives, Denmark
6    * %%
7    * This program is free software: you can redistribute it and/or modify
8    * it under the terms of the GNU Lesser General Public License as 
9    * published by the Free Software Foundation, either version 2.1 of the 
10   * License, or (at your option) any later version.
11   * 
12   * This program is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   * GNU General Lesser Public License for more details.
16   * 
17   * You should have received a copy of the GNU General Lesser Public 
18   * License along with this program.  If not, see
19   * <http://www.gnu.org/licenses/lgpl-2.1.html>.
20   * #L%
21   */
22  package org.bitrepository.audittrails.store;
23  
24  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.AUDITTRAIL_CONTRIBUTOR_KEY;
25  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.AUDITTRAIL_FILE_KEY;
26  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.AUDITTRAIL_SEQUENCE_NUMBER;
27  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.AUDITTRAIL_TABLE;
28  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.COLLECTION_ID;
29  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.COLLECTION_KEY;
30  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.COLLECTION_TABLE;
31  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.CONTRIBUTOR_ID;
32  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.CONTRIBUTOR_KEY;
33  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.CONTRIBUTOR_TABLE;
34  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.FILE_COLLECTION_KEY;
35  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.FILE_KEY;
36  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.FILE_TABLE;
37  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.PRESERVATION_COLLECTION_KEY;
38  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.PRESERVATION_CONTRIBUTOR_KEY;
39  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.PRESERVATION_KEY;
40  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.PRESERVATION_SEQ;
41  import static org.bitrepository.audittrails.store.AuditDatabaseConstants.PRESERVATION_TABLE;
42  
43  import java.sql.SQLException;
44  import java.util.Date;
45  
46  import org.bitrepository.bitrepositoryelements.AuditTrailEvent;
47  import org.bitrepository.bitrepositoryelements.AuditTrailEvents;
48  import org.bitrepository.bitrepositoryelements.FileAction;
49  import org.bitrepository.common.ArgumentValidator;
50  import org.bitrepository.service.database.DBConnector;
51  import org.bitrepository.service.database.DatabaseManager;
52  import org.bitrepository.service.database.DatabaseUtils;
53  import org.slf4j.Logger;
54  import org.slf4j.LoggerFactory;
55  
56  /**
57   * Audit trail storages backed by a database for preserving
58   */
59  public class AuditTrailServiceDAO implements AuditTrailStore {
60      /** The log.*/
61      private Logger log = LoggerFactory.getLogger(getClass());
62      /** The connection to the database.*/
63      private DBConnector dbConnector;
64      
65      /** 
66       * Constructor.
67       * @param databaseManager The database manager
68       */
69      public AuditTrailServiceDAO(DatabaseManager databaseManager) {
70          dbConnector = databaseManager.getConnector();
71      }
72      
73      @Override
74      public AuditEventIterator getAuditTrailsByIterator(String fileId, String collectionID, String contributorId, 
75              Long minSeqNumber, Long maxSeqNumber, String actorName, FileAction operation, Date startDate, 
76              Date endDate, String fingerprint, String operationID) {
77          ExtractModel model = new ExtractModel();
78          model.setFileId(fileId);
79          model.setCollectionId(collectionID);
80          model.setContributorId(contributorId);
81          model.setMinSeqNumber(minSeqNumber);
82          model.setMaxSeqNumber(maxSeqNumber);
83          model.setActorName(actorName);
84          model.setOperation(operation);
85          model.setStartDate(startDate);
86          model.setEndDate(endDate);
87          model.setFingerprint(fingerprint);
88          model.setOperationID(operationID);
89  
90          AuditDatabaseExtractor extractor = new AuditDatabaseExtractor(model, dbConnector);
91          return extractor.extractAuditEventsByIterator();
92      }
93      
94      
95      
96      @Override
97      public void addAuditTrails(AuditTrailEvents newAuditTrails, String collectionId) {
98          ArgumentValidator.checkNotNull(newAuditTrails, "AuditTrailEvents newAuditTrails");
99          ArgumentValidator.checkNotNullOrEmpty(collectionId, "String collectionId");
100         
101         AuditDatabaseIngestor ingestor = new AuditDatabaseIngestor(dbConnector);
102         for(AuditTrailEvent event : newAuditTrails.getAuditTrailEvent()) {
103             ingestor.ingestAuditEvents(event, collectionId);
104         }
105     }
106     
107     @Override
108     public int largestSequenceNumber(String contributorId, String collectionId) {
109         ArgumentValidator.checkNotNullOrEmpty(contributorId, "String contributorId");
110         ArgumentValidator.checkNotNullOrEmpty(collectionId, "String collectionId");
111         
112         // Indirectly extracts contributor and collection keys, and joins with the file table where the query can be
113         // limited by collection
114         String sql = "SELECT " + AUDITTRAIL_SEQUENCE_NUMBER + " FROM " + AUDITTRAIL_TABLE 
115                 + " JOIN " + FILE_TABLE 
116                 + " ON " + AUDITTRAIL_TABLE + "." + AUDITTRAIL_FILE_KEY + " = " + FILE_TABLE + "." + FILE_KEY
117                 + " WHERE "  + AUDITTRAIL_TABLE + "." + AUDITTRAIL_CONTRIBUTOR_KEY + " = ("
118                     + " SELECT " + CONTRIBUTOR_KEY + " FROM " + CONTRIBUTOR_TABLE 
119                     + " WHERE " + CONTRIBUTOR_ID + " = ? )"
120                 + " AND " + FILE_TABLE + "." + FILE_COLLECTION_KEY + " = (" 
121                     + " SELECT " + COLLECTION_KEY + " FROM " + COLLECTION_TABLE 
122                     + " WHERE " + COLLECTION_ID + " = ? )"
123                 + " ORDER BY " + AUDITTRAIL_TABLE + "." + AUDITTRAIL_SEQUENCE_NUMBER + " DESC";
124         
125         Long seq = DatabaseUtils.selectFirstLongValue(dbConnector, sql, contributorId, collectionId);
126         if(seq != null) {
127             return seq.intValue();
128         }
129         return 0;
130     }    
131 
132     @Override
133     public long getPreservationSequenceNumber(String contributorId, String collectionId) {
134         ArgumentValidator.checkNotNullOrEmpty(contributorId, "String contributorId");
135         ArgumentValidator.checkNotNullOrEmpty(collectionId, "String collectionId");
136         
137         String sql = "SELECT " + PRESERVATION_SEQ + " FROM " + PRESERVATION_TABLE 
138                 + " WHERE " + PRESERVATION_CONTRIBUTOR_KEY + " = (" 
139                     + " SELECT " + CONTRIBUTOR_KEY + " FROM " + CONTRIBUTOR_TABLE 
140                     + " WHERE " + CONTRIBUTOR_ID + " = ? )"
141                 + "AND " + PRESERVATION_COLLECTION_KEY + " = (" 
142                     + " SELECT " + COLLECTION_KEY + " FROM " + COLLECTION_TABLE 
143                     + " WHERE " + COLLECTION_ID + " = ? )";
144         
145         Long seq = DatabaseUtils.selectLongValue(dbConnector, sql, contributorId, collectionId);
146         if(seq != null) {
147             return seq.intValue();
148         }
149         return 0;
150     }
151 
152     @Override
153     public void setPreservationSequenceNumber(String contributorId, String collectionId, long seqNumber) {
154         ArgumentValidator.checkNotNullOrEmpty(contributorId, "String contributorId");
155         ArgumentValidator.checkNotNegative(seqNumber, "int seqNumber");
156         long preservationKey = retrievePreservationKey(contributorId, collectionId);
157         log.debug("Updating preservation sequence number for contributor: " + contributorId 
158                 + " in collection: " + collectionId + " to seq: " + seqNumber);
159         String sqlUpdate = "UPDATE " + PRESERVATION_TABLE + " SET " + PRESERVATION_SEQ + " = ?"
160                 + " WHERE " + PRESERVATION_KEY + " = ? ";
161         DatabaseUtils.executeStatement(dbConnector, sqlUpdate, seqNumber, preservationKey);
162     }
163     
164     @Override
165     public boolean havePreservationKey(String contributorID, String collectionID) {
166         String sql = "SELECT " + PRESERVATION_KEY + " FROM " + PRESERVATION_TABLE 
167                 + " WHERE " + PRESERVATION_CONTRIBUTOR_KEY + " = (" 
168                     + " SELECT " + CONTRIBUTOR_KEY + " FROM " + CONTRIBUTOR_TABLE 
169                     + " WHERE " + CONTRIBUTOR_ID + " = ? ) "
170                 + "AND " + PRESERVATION_COLLECTION_KEY + " = ("
171                     + " SELECT " + COLLECTION_KEY + " FROM " + COLLECTION_TABLE
172                     + " WHERE " + COLLECTION_ID + " = ? )";
173         
174         Long preservationKey = DatabaseUtils.selectLongValue(dbConnector, sql, contributorID, collectionID);
175         if(preservationKey == null) {
176             return false;    
177         } else {
178             return true;
179         }
180         
181     }
182     
183     /**
184      * Retrieves the key of the preservation table entry for the given collection and contributor.
185      * 
186      * @param contributorId The contributor of the preservation table entry.
187      * @param collectionId The collection of the preservation table entry.
188      * @return The key of the entry in the preservation table.
189      */
190     private Long retrievePreservationKey(String contributorId, String collectionId) {
191         String sqlRetrieve = "SELECT " + PRESERVATION_KEY + " FROM " + PRESERVATION_TABLE 
192                 + " WHERE " + PRESERVATION_CONTRIBUTOR_KEY + " = (" 
193                     + " SELECT " + CONTRIBUTOR_KEY + " FROM " + CONTRIBUTOR_TABLE 
194                     + " WHERE " + CONTRIBUTOR_ID + " = ? ) "
195                 + "AND " + PRESERVATION_COLLECTION_KEY + " = ("
196                     + " SELECT " + COLLECTION_KEY + " FROM " + COLLECTION_TABLE
197                     + " WHERE " + COLLECTION_ID + " = ? )";
198         Long guid = DatabaseUtils.selectLongValue(dbConnector, sqlRetrieve, contributorId, collectionId);
199         
200         if(guid == null) {
201             log.debug("Inserting preservation entry for contributor '" + contributorId + "' and collection '" 
202                     + collectionId + "' into the preservation table.");
203             String sqlInsert = "INSERT INTO " + PRESERVATION_TABLE + " ( " + PRESERVATION_CONTRIBUTOR_KEY + " , " 
204                     + PRESERVATION_COLLECTION_KEY + ") VALUES ( "
205                         + "(SELECT " + CONTRIBUTOR_KEY + " FROM " + CONTRIBUTOR_TABLE + " WHERE " 
206                         + CONTRIBUTOR_ID + " = ?)"
207                     + ", "
208                         + "( SELECT " + COLLECTION_KEY + " FROM " + COLLECTION_TABLE + " WHERE " 
209                         + COLLECTION_ID + " = ? )"
210                     + ")";
211             DatabaseUtils.executeStatement(dbConnector, sqlInsert, contributorId, collectionId);
212             
213             guid = DatabaseUtils.selectLongValue(dbConnector, sqlRetrieve, contributorId, collectionId);
214         }
215         
216         if(guid == null) {
217             throw new IllegalStateException("PreservationKey cannot be obtained for contributor: " + contributorId +
218                     " in collection: " + collectionId);
219         }
220         
221         return guid;
222     }
223 
224     @Override
225     public void close() {
226         try {
227             dbConnector.getConnection().close();
228         } catch (SQLException e) {
229             log.warn("Cannot close the database properly.", e);
230         }
231     }
232 
233 }