View Javadoc

1   /*
2    * #%L
3    * Bitrepository Reference Pillar
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.service.contributor.handler;
23  
24  import java.io.File;
25  import java.io.FileInputStream;
26  import java.io.FileOutputStream;
27  import java.io.IOException;
28  import java.io.OutputStream;
29  import java.net.URL;
30  import java.util.Date;
31  
32  import javax.xml.bind.JAXBException;
33  
34  import org.apache.activemq.util.ByteArrayInputStream;
35  import org.bitrepository.bitrepositorydata.GetAuditTrailsResults;
36  import org.bitrepository.bitrepositoryelements.ResponseCode;
37  import org.bitrepository.bitrepositoryelements.ResponseInfo;
38  import org.bitrepository.bitrepositoryelements.ResultingAuditTrails;
39  import org.bitrepository.bitrepositorymessages.GetAuditTrailsFinalResponse;
40  import org.bitrepository.bitrepositorymessages.GetAuditTrailsProgressResponse;
41  import org.bitrepository.bitrepositorymessages.GetAuditTrailsRequest;
42  import org.bitrepository.bitrepositorymessages.MessageResponse;
43  import org.bitrepository.common.JaxbHelper;
44  import org.bitrepository.common.utils.CalendarUtils;
45  import org.bitrepository.protocol.FileExchange;
46  import org.bitrepository.protocol.ProtocolComponentFactory;
47  import org.bitrepository.protocol.ProtocolVersionLoader;
48  import org.bitrepository.service.audit.AuditTrailDatabaseResults;
49  import org.bitrepository.service.audit.AuditTrailManager;
50  import org.bitrepository.service.contributor.ContributorContext;
51  import org.bitrepository.service.exception.InvalidMessageException;
52  import org.bitrepository.service.exception.RequestHandlerException;
53  import org.slf4j.Logger;
54  import org.slf4j.LoggerFactory;
55  import org.xml.sax.SAXException;
56  
57  /**
58   * Class for handling the GetAuditTrails operation.
59   */
60  public class GetAuditTrailsRequestHandler extends AbstractRequestHandler<GetAuditTrailsRequest> {
61      /** The log.*/
62      private Logger log = LoggerFactory.getLogger(getClass());
63      /** The audit trail manager.*/
64      private final AuditTrailManager auditManager;
65      
66      /**
67       * Constructor.
68       * @param context The context of the message handler.
69       */
70      public GetAuditTrailsRequestHandler(ContributorContext context, AuditTrailManager auditManager) {
71          super(context);
72          this.auditManager = auditManager;
73      }
74  
75      @Override
76      public Class<GetAuditTrailsRequest> getRequestClass() {
77          return GetAuditTrailsRequest.class;
78      }
79  
80      @Override
81      public void processRequest(GetAuditTrailsRequest message) throws RequestHandlerException {
82          validateCollectionID(message);
83          validateMessage(message);
84          sendProgressMessage(message);
85          AuditTrailDatabaseResults resAudits = collectAudits(message);
86          handleUpload(message, resAudits);
87          sendFinalResponse(message, resAudits);
88      }
89  
90      @Override
91      public MessageResponse generateFailedResponse(GetAuditTrailsRequest request) {
92          return createFinalResponse(request);
93      }
94  
95      /**
96       * Method for validating the content of the message.
97       * @param message The message requesting the operation, which should be validated.
98       * @return Whether it was valid.
99       */
100     protected void validateMessage(GetAuditTrailsRequest message) throws RequestHandlerException {
101         if(!message.getContributor().equals(getContext().getSettings().getComponentID())) {
102             ResponseInfo ri = new ResponseInfo();
103             ri.setResponseCode(ResponseCode.REQUEST_NOT_UNDERSTOOD_FAILURE);
104             ri.setResponseText("Invalid contributor id.");
105             throw new InvalidMessageException(ri, message.getCollectionID());
106         }
107     }
108     
109     /**
110      * The method for sending a progress response telling, that the operation is about to be performed.
111      * @param request The request for the GetStatus operation.
112      */
113     protected void sendProgressMessage(GetAuditTrailsRequest request) {
114         GetAuditTrailsProgressResponse response = createProgressResponse(request);
115         
116         // set missing variables in the request: ResponseInfo
117         ResponseInfo prInfo = new ResponseInfo();
118         prInfo.setResponseCode(ResponseCode.OPERATION_ACCEPTED_PROGRESS);
119         prInfo.setResponseText("Starting to extract the requested audit trails.");
120         response.setResponseInfo(prInfo);
121 
122         getContext().getResponseDispatcher().dispatchResponse(response, request);
123     }
124     
125     /**
126      * Collect the requested audit trails.
127      * @param message The message requesting the collecting of audit trails.
128      * @return The requested audit trails.
129      */
130     protected AuditTrailDatabaseResults collectAudits(GetAuditTrailsRequest message) {
131         Long minSeq = null;
132         if(message.getMinSequenceNumber() != null) {
133             log.trace("Minimum sequence value: {}", message.getMinSequenceNumber().longValue());
134             minSeq = message.getMinSequenceNumber().longValue();
135         }
136         Long maxSeq = null;
137         if(message.getMaxSequenceNumber() != null) {
138             log.trace("Maximum sequence value: {}", message.getMaxSequenceNumber().longValue());
139             maxSeq = message.getMaxSequenceNumber().longValue();
140         }
141         Date minDate = null;
142         if(message.getMinTimestamp() != null) {
143             log.trace("Minimum date value: {}", message.getMinTimestamp());
144             minDate = CalendarUtils.convertFromXMLGregorianCalendar(message.getMinTimestamp());
145         }
146         Date maxDate = null;
147         if(message.getMaxTimestamp() != null) {
148             log.trace("Maximum date value: {}", message.getMaxTimestamp());
149             maxDate = CalendarUtils.convertFromXMLGregorianCalendar(message.getMaxTimestamp());
150         }
151         Long maxNumberOfResults = null;
152         if(message.getMaxNumberOfResults() != null) {
153             log.trace("Maximum number of results: {}", message.getMaxNumberOfResults());
154             maxNumberOfResults = message.getMaxNumberOfResults().longValue();
155         }
156         
157         return auditManager.getAudits(message.getCollectionID(), message.getFileID(), minSeq, maxSeq, minDate, 
158                 maxDate, maxNumberOfResults);
159     }
160     
161     /**
162      * Handles the potential upload of the audit trails to a given URL.
163      * @param message The request for the audit trails, which includes the URL for where the audit trails should be 
164      * uploaded
165      * @param extractedAuditTrails The extracted audit trails.
166      * @throws InvalidMessageException If the creation, serialization, validation or upload of the file fails.
167      */
168     protected void handleUpload(GetAuditTrailsRequest message, AuditTrailDatabaseResults extractedAuditTrails) throws InvalidMessageException {
169         if(message.getResultAddress() == null || message.getResultAddress().isEmpty()) {
170             log.trace("The audit trails are not uploaded.");
171             return;
172         }
173         
174         log.debug("Creating audit trail file and uploading it.");
175         try {
176             File fileToUpload = createAuditTrailFile(message, extractedAuditTrails);
177             URL uploadUrl = new URL(message.getResultAddress());
178             
179             log.debug("Uploading file: " + fileToUpload.getName() + " to " + uploadUrl.toExternalForm());
180             FileExchange fe = ProtocolComponentFactory.getInstance().getFileExchange(getContext().getSettings());
181             fe.uploadToServer(new FileInputStream(fileToUpload), uploadUrl);
182         } catch (Exception e) {
183             ResponseInfo ir = new ResponseInfo();
184             ir.setResponseCode(ResponseCode.FILE_TRANSFER_FAILURE);
185             ir.setResponseText("Could not handle the creation and upload of the results due to: " + e.getMessage());
186             throw new InvalidMessageException(ir, message.getCollectionID(), e);
187         }
188     }
189     
190     /**
191      * Creates a file containing all the audit trails.
192      * @param request The request for the data.
193      * @param extractedAuditTrails The extracted audit trails.
194      * @return The file containing the extracted audit trails.
195      * @throws IOException If something goes wrong when creating the file or finding the XSD.
196      * @throws JAXBException If the resulting structure cannot be serialized.
197      * @throws SAXException If the results does not validate against the XSD.
198      */
199     protected File createAuditTrailFile(GetAuditTrailsRequest request, AuditTrailDatabaseResults extractedAuditTrails) 
200             throws IOException, JAXBException, SAXException {
201         File checksumResultFile = File.createTempFile(request.getCorrelationID(), new Date().getTime() + ".at");
202         
203         GetAuditTrailsResults results = new GetAuditTrailsResults();
204         results.setVersion(ProtocolVersionLoader.loadProtocolVersion().getVersion());
205         results.setMinVersion(ProtocolVersionLoader.loadProtocolVersion().getMinVersion());
206         results.setCollectionID(request.getCollectionID());
207         results.getAuditTrailEvents().add(extractedAuditTrails.getAuditTrailEvents());
208 
209         OutputStream is = null;
210         try {
211             is = new FileOutputStream(checksumResultFile);
212             JaxbHelper jaxb = new JaxbHelper(XSD_CLASSPATH, XSD_BR_DATA);
213             String xmlMessage = jaxb.serializeToXml(results);
214             jaxb.validate(new ByteArrayInputStream(xmlMessage.getBytes()));
215             is.write(xmlMessage.getBytes());
216             is.flush();
217         } finally {
218             if(is != null) {
219                 is.close();
220             }
221         }
222         
223         return checksumResultFile;
224     }
225 
226     /**
227      * Method for sending a positive final response.
228      * @param request The request to respond to.
229      * @param auditExtract The retrieved audit trails.
230      */
231     protected void sendFinalResponse(GetAuditTrailsRequest request, AuditTrailDatabaseResults auditExtract) {
232         GetAuditTrailsFinalResponse response = createFinalResponse(request);
233         ResultingAuditTrails resAuditTrails = new ResultingAuditTrails();
234         if(request.getResultAddress() == null) {
235             resAuditTrails.setAuditTrailEvents(auditExtract.getAuditTrailEvents());
236         } else {
237             resAuditTrails.setResultAddress(request.getResultAddress());
238         }
239         
240         response.setResultingAuditTrails(resAuditTrails);
241         response.setPartialResult(auditExtract.moreResults());
242         
243         ResponseInfo responseInfo = new ResponseInfo();
244         responseInfo.setResponseCode(ResponseCode.OPERATION_COMPLETED);
245         response.setResponseInfo(responseInfo);
246 
247         getContext().getResponseDispatcher().dispatchResponse(response, request);
248     }
249     
250     /**
251      * Creates a GetStatusProgressResponse based on a GetStatusRequest. Missing the 
252      * following fields (besides the ones in dispatchResponse):
253      * <br/> - ResponseInfo
254      * 
255      * @param message The message to base the response upon.
256      * @return The GetStatusProgressResponse based on the request.
257      */
258     private GetAuditTrailsProgressResponse createProgressResponse(GetAuditTrailsRequest message) {
259         GetAuditTrailsProgressResponse res = new GetAuditTrailsProgressResponse();
260         res.setContributor(getContext().getSettings().getComponentID());
261         res.setResultAddress(message.getResultAddress());
262         
263         return res;
264     }
265     
266     /**
267      * Creates a GetStatusFinalResponse based on a GetStatusRequest. Missing the 
268      * following fields (besides the ones in dispatchResponse):
269      * <br/> - ResponseInfo
270      * <br/> - ResultingAuditTrails
271      * 
272      * @return The GetStatusFinalResponse based on the request.
273      */
274     protected GetAuditTrailsFinalResponse createFinalResponse(GetAuditTrailsRequest request) {
275         GetAuditTrailsFinalResponse res = new GetAuditTrailsFinalResponse();
276         res.setContributor(getContext().getSettings().getComponentID());
277         
278         return res;
279     }
280 }