/*******************************************************************************
* Copyright (c) 2008-2009 Cambridge Semantics Incorporated.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*******************************************************************************/
package org.openanzo.analysis;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.jms.JMSException;
import javax.jms.TextMessage;
import org.openanzo.exceptions.AnzoException;
import org.openanzo.exceptions.ExceptionConstants;
import org.openanzo.exceptions.LogUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Request recorder
*
* @author Ben Szekely ( <a href="mailto:ben@cambridgesemantics.com">ben@cambridgesemantics.com </a>)
*
*/
public class RequestRecorder {
protected static final Logger log = LoggerFactory.getLogger(RequestRecorder.class);
/** JMS correlation ID */
public static final String JMS_CORRELATION_ID = "jmsCorrelationId";
/** JMS reply to destination */
public static final String REPLY_TO = "replyTo";
/** JMS Destination */
public static final String DESTINATION = "destination";
/** JMS Request user */
public static final String REQUEST_USER = "requestUser";
/** JMS Request RunAs user */
public static final String REQUEST_RUN_AS_USER = "requestRunAsUser";
private String location = null;
private Set<String> excludedQueues = null;
/**
* Request Recorder
*
* @param location
* location of output
* @param excludedQueues
* set of queue names to exclude from recording
*/
public RequestRecorder(String location, Set<String> excludedQueues) {
log.debug(LogUtils.LIFECYCLE_MARKER, "Setting Combus Endpoint Recorder: {}", location);
this.location = location;
this.excludedQueues = excludedQueues;
}
private boolean handleMessage(TextMessage message) {
try {
return excludedQueues == null || !excludedQueues.contains(message.getJMSDestination().toString());
} catch (JMSException jmsex) {
return true;
}
}
/**
* Record a request
*
* @param request
* request to record
* @param user
* user making request
* @param runAsUser
* runas user making request
* @throws AnzoException
*/
public void recordRequest(TextMessage request, String user, String runAsUser) throws AnzoException {
try {
if (handleMessage(request)) {
Map<String, String> props = getCommonProperties(request);
getRequestProperties(request, props, user, runAsUser);
recordEntry("@request", props, request.getText());
}
} catch (Exception e) {
throw new AnzoException(ExceptionConstants.COMBUS.RECORDER_ERROR, e, "Error recording request");
}
}
/**
* Record response
*
* @param response
* response to request
* @throws AnzoException
*/
public void recordResponse(TextMessage response) throws AnzoException {
try {
if (handleMessage(response)) {
Map<String, String> props = getCommonProperties(response);
getResponseProperties(props);
recordEntry("@response", props, response.getText());
}
} catch (Exception e) {
throw new AnzoException(ExceptionConstants.COMBUS.RECORDER_ERROR, e, "Error recording response");
}
}
/**
* Record response
*
* @param jmsCorrelationId
* correlation id of request
* @param operation
* operation name
* @throws AnzoException
*/
public void recordResponse(String jmsCorrelationId, String operation) throws AnzoException {
try {
Map<String, String> props = getCommonProperties(jmsCorrelationId, operation);
getResponseProperties(props);
recordEntry("@response", props, "NO RESPONSE TEXT");
} catch (Exception e) {
throw new AnzoException(ExceptionConstants.COMBUS.RECORDER_ERROR, e, "Error recording response");
}
}
@SuppressWarnings("unchecked")
private Map<String, String> getCommonProperties(TextMessage msg) throws Exception {
HashMap<String, String> props = new HashMap<String, String>();
Enumeration<String> names = msg.getPropertyNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
String value = msg.getStringProperty(name);
props.put(name, value);
}
if (msg.getJMSCorrelationID() != null) {
props.put(JMS_CORRELATION_ID, msg.getJMSCorrelationID());
}
return props;
}
private Map<String, String> getCommonProperties(String jmsCorrelationId, String operation) throws Exception {
HashMap<String, String> props = new HashMap<String, String>();
props.put(JMS_CORRELATION_ID, jmsCorrelationId);
props.put("operation", operation);
return props;
}
private void getRequestProperties(TextMessage msg, Map<String, String> properties, String user, String runAsUser) throws Exception {
if (msg.getJMSDestination() != null) {
properties.put(DESTINATION, msg.getJMSDestination().toString());
}
if (msg.getJMSReplyTo() != null) {
properties.put(REPLY_TO, msg.getJMSReplyTo().toString());
}
properties.put(REQUEST_USER, user);
if (runAsUser != null) {
properties.put(REQUEST_RUN_AS_USER, runAsUser);
}
}
private void getResponseProperties(Map<String, String> properties) throws Exception {
for (String name : RequestAnalysis.getAnalysisPropertyNames()) {
properties.put(name, RequestAnalysis.getAnalysisProperty(name).toString());
}
}
private synchronized void recordEntry(String header, Map<String, String> properties, String body) throws Exception {
StringBuilder builder = new StringBuilder();
builder.append(header).append("\r\n");
builder.append("@properties").append("\r\n");
TreeMap<String, String> sortedProperties = new TreeMap<String, String>(properties);
for (Map.Entry<String, String> entry : sortedProperties.entrySet()) {
builder.append(entry.getKey()).append("=").append(entry.getValue()).append("\r\n");
}
if (body != null) {
builder.append("@body").append("\r\n");
builder.append(body).append("\r\n");
}
Writer writer = new OutputStreamWriter(new FileOutputStream(location, true), "UTF-8");
writer.write(builder.toString());
writer.flush();
writer.close();
}
/**
* Close the recorder
*/
public void close() {
}
}