
org.talend.esb.sam.agent.eventproducer.MessageToEventMapper Maven / Gradle / Ivy
/*
* #%L
* Service Activity Monitoring :: Agent
* %%
* Copyright (C) 2011 - 2012 Talend Inc.
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
package org.talend.esb.sam.agent.eventproducer;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.logging.Logger;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import org.apache.cxf.binding.soap.SoapBinding;
import org.apache.cxf.binding.soap.model.SoapBindingInfo;
import org.apache.cxf.configuration.security.AuthorizationPolicy;
import org.apache.cxf.io.CachedOutputStream;
import org.apache.cxf.message.Message;
import org.apache.cxf.message.MessageUtils;
import org.apache.cxf.security.SecurityContext;
import org.apache.cxf.service.model.BindingOperationInfo;
import org.apache.cxf.service.model.ServiceInfo;
import org.apache.cxf.ws.addressing.AddressingProperties;
import org.apache.cxf.ws.addressing.ContextUtils;
//import org.apache.cxf.ws.addressing.impl.AddressingPropertiesImpl;
import org.apache.cxf.service.model.ServiceModelUtil;
import org.talend.esb.sam.agent.message.CorrelationIdHelper;
import org.talend.esb.sam.agent.message.CustomInfo;
import org.talend.esb.sam.agent.message.FlowIdHelper;
import org.talend.esb.sam.agent.util.Converter;
import org.talend.esb.sam.common.event.Event;
import org.talend.esb.sam.common.event.EventTypeEnum;
import org.talend.esb.sam.common.event.MessageInfo;
import org.talend.esb.sam.common.event.Originator;
/**
* The Class MessageToEventMapper.
*/
public class MessageToEventMapper {
private static final Logger LOG = Logger.getLogger(MessageToEventMapper.class.getName());
private static final String CUT_START_TAG = " ";
private int maxContentLength = -1;
/**
* Map to event.
*
* @param message
* the message
* @return the event
*/
public Event mapToEvent(Message message) {
Event event = new Event();
MessageInfo messageInfo = new MessageInfo();
Originator originator = new Originator();
boolean isRestMessage = isRestMessage(message);
event.setMessageInfo(messageInfo);
event.setOriginator(originator);
String content = getPayload(message);
event.setContent(content);
handleContentLength(event);
event.setEventType(null);
Date date = new Date();
event.setTimestamp(date);
// if (isRestMessage) {
// String queryString = (String) message.get(Message.QUERY_STRING);
// if (queryString == null && message.getExchange().getInMessage() != null) {
// queryString = (String) message.getExchange().getInMessage().get(Message.QUERY_STRING);
// }
// if (queryString != null && queryString.contains("_wadl")) {
// return null;
// }
// }
messageInfo.setFlowId(FlowIdHelper.getFlowId(message));
if (!isRestMessage) {
messageInfo.setMessageId(getMessageId(message));
ServiceInfo serviceInfo = message.getExchange().getBinding().getBindingInfo().getService();
if (null != serviceInfo) {
String portTypeName = serviceInfo.getInterface().getName().toString();
messageInfo.setPortType(portTypeName);
messageInfo.setOperationName(getOperationName(message));
}
SoapBinding soapBinding = (SoapBinding) message.getExchange().getBinding();
if (soapBinding.getBindingInfo() instanceof SoapBindingInfo) {
SoapBindingInfo soapBindingInfo = (SoapBindingInfo) soapBinding.getBindingInfo();
messageInfo.setTransportType(soapBindingInfo.getTransportURI());
}
} else {
messageInfo.setTransportType("http://cxf.apache.org/transports/http");
messageInfo.setPortType(message.getExchange().getEndpoint().getEndpointInfo().getName()
.toString());
String opName = getRestOperationName(message);
messageInfo.setOperationName(opName);
}
if (messageInfo.getTransportType() == null) {
messageInfo.setTransportType("Unknown transport type");
}
String addr = message.getExchange().getEndpoint().getEndpointInfo().getAddress();
if (null != addr) {
event.getCustomInfo().put("address", addr);
}
String correlationId = CorrelationIdHelper.getCorrelationId(message);
if (null != correlationId) {
event.getCustomInfo().put("CorrelationID", correlationId);
}
try {
InetAddress inetAddress = InetAddress.getLocalHost();
originator.setIp(inetAddress.getHostAddress());
originator.setHostname(inetAddress.getHostName());
} catch (UnknownHostException e) {
originator.setHostname("Unknown hostname");
originator.setIp("Unknown ip address");
}
originator.setProcessId(Converter.getPID());
if (isRestMessage) {
//String queryString = (String) message.get(Message.QUERY_STRING);
//if (null == queryString && null != message.getExchange().getInMessage()) {
// queryString = (String) message.getExchange().getInMessage().get(Message.QUERY_STRING);
//}
//if (null != queryString) {
// event.getCustomInfo().put("Query String", queryString);
//}
String accept = (String) message.get(Message.ACCEPT_CONTENT_TYPE);
if (null != accept) {
event.getCustomInfo().put("Accept Type", accept);
}
//String httpMethod = (String) message.get(Message.HTTP_REQUEST_METHOD);
//if (null != httpMethod) {
// event.getCustomInfo().put("HTTP Method", httpMethod);
//}
String contentType = (String) message.get(Message.CONTENT_TYPE);
if (null != contentType) {
event.getCustomInfo().put("Content Type", contentType);
}
Integer responseCode = (Integer) message.get(Message.RESPONSE_CODE);
if (null != responseCode) {
event.getCustomInfo().put("Response Code", responseCode.toString());
}
}
SecurityContext sc = message.get(SecurityContext.class);
if (sc != null && sc.getUserPrincipal() != null) {
originator.setPrincipal(sc.getUserPrincipal().getName());
}
if (originator.getPrincipal() == null) {
AuthorizationPolicy authPolicy = message.get(AuthorizationPolicy.class);
if (authPolicy != null) {
originator.setPrincipal(authPolicy.getUserName());
}
}
EventTypeEnum eventType = getEventType(message);
event.setEventType(eventType);
CustomInfo customInfo = CustomInfo.getOrCreateCustomInfo(message);
// System.out.println("custom props: " + customInfo);
event.getCustomInfo().putAll(customInfo);
return event;
}
private String getRestOperationName(Message message) {
boolean isRequestor = MessageUtils.isRequestor(message);
boolean isOutbound = MessageUtils.isOutbound(message);
Message effectiveMessage = message;
if (isRequestor) {
if (!isOutbound) {
effectiveMessage = message.getExchange().getOutMessage();
}
} else {
if (isOutbound) {
effectiveMessage = message.getExchange().getInMessage();
}
}
return buildRestOperationName(effectiveMessage);
}
private static String buildRestOperationName(Message message) {
if (message.containsKey(Message.HTTP_REQUEST_METHOD)) {
String httpMethod = message.get(Message.HTTP_REQUEST_METHOD).toString();
String path = "";
if (message.containsKey(Message.REQUEST_URI)) {
String requestUri = message.get(Message.REQUEST_URI).toString();
int baseUriLength = (message.containsKey(Message.BASE_PATH))
? message.get(Message.BASE_PATH).toString().length() : 0;
path = requestUri.substring(baseUriLength);
if (path.isEmpty()) {
path = "/";
}
}
return new StringBuffer().append(httpMethod).append('[').append(path).append(']').toString();
}
return "";
}
/**
* Get MessageId string.
* if enforceMessageIDTransfer=true or WS-Addressing enabled explicitly (i.e with feature),
* then MessageId is not null and conform with the definition in the WS-Addressing Spec;
* if enforceMessageIDTransfer=false and WS-Addressing doesn't enable,
* then MessageId is null.
* @param message the message
* @return the message id
*/
private String getMessageId(Message message) {
String messageId = null;
AddressingProperties addrProp = ContextUtils.retrieveMAPs(message, false,
MessageUtils.isOutbound(message));
if (addrProp != null && addrProp.getMessageID() != null) {
messageId = addrProp.getMessageID().getValue();
}
return messageId;
}
/**
* Gets the event type from message.
*
* @param message the message
* @return the event type
*/
private EventTypeEnum getEventType(Message message) {
boolean isRequestor = MessageUtils.isRequestor(message);
boolean isFault = MessageUtils.isFault(message);
boolean isOutbound = MessageUtils.isOutbound(message);
//Needed because if it is rest request and method does not exists had better to return Fault
if(!isFault && isRestMessage(message)) {
isFault = (message.getExchange().get("org.apache.cxf.resource.operation.name") == null);
if (!isFault) {
Integer responseCode = (Integer) message.get(Message.RESPONSE_CODE);
if (null != responseCode) {
isFault = (responseCode >= 400);
}
}
}
if (isOutbound) {
if (isFault) {
return EventTypeEnum.FAULT_OUT;
} else {
return isRequestor ? EventTypeEnum.REQ_OUT : EventTypeEnum.RESP_OUT;
}
} else {
if (isFault) {
return EventTypeEnum.FAULT_IN;
} else {
return isRequestor ? EventTypeEnum.RESP_IN : EventTypeEnum.REQ_IN;
}
}
}
private String getOperationName(Message message) {
String operationName = null;
BindingOperationInfo boi = null;
boi = message.getExchange().getBindingOperationInfo();
if (null == boi) {
// get BindingOperationInfo from message content
boi = getOperationFromContent(message);
}
// if BindingOperationInfo is still null, try to get it from Request
// message content
if (null == boi) {
Message inMsg = message.getExchange().getInMessage();
if (null != inMsg) {
Message reqMsg = inMsg.getExchange().getInMessage();
if (null != reqMsg) {
boi = getOperationFromContent(reqMsg);
}
}
}
if (null != boi) {
operationName = boi.getName().toString();
}
return operationName;
}
private BindingOperationInfo getOperationFromContent(Message message) {
BindingOperationInfo boi = null;
XMLStreamReader xmlReader = message.getContent(XMLStreamReader.class);
if (null != xmlReader) {
QName qName = xmlReader.getName();
boi = ServiceModelUtil.getOperation(message.getExchange(), qName);
}
return boi;
}
/**
* Gets the message payload.
*
* @param message the message
* @return the payload
*/
protected String getPayload(Message message) {
try {
String encoding = (String) message.get(Message.ENCODING);
if (encoding == null) {
encoding = "UTF-8";
}
CachedOutputStream cos = message.getContent(CachedOutputStream.class);
if (cos == null) {
LOG.warning("Could not find CachedOutputStream in message."
+ " Continuing without message content");
return "";
}
return new String(cos.getBytes(), encoding);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Gets the max message content length.
*
* @return the max content length
*/
public int getMaxContentLength() {
return maxContentLength;
}
/**
* Sets the max message content length.
*
* @param maxContentLength
* the new max content length
*/
public void setMaxContentLength(int maxContentLength) {
this.maxContentLength = maxContentLength;
}
/**
* Handle content length.
*
* @param event
* the event
*/
private void handleContentLength(Event event) {
if (event.getContent() == null) {
return;
}
if (maxContentLength == -1 || event.getContent().length() <= maxContentLength) {
return;
}
if (maxContentLength < CUT_START_TAG.length() + CUT_END_TAG.length()) {
event.setContent("");
event.setContentCut(true);
return;
}
int contentLength = maxContentLength - CUT_START_TAG.length() - CUT_END_TAG.length();
event.setContent(CUT_START_TAG + event.getContent().substring(0, contentLength) + CUT_END_TAG);
event.setContentCut(true);
}
/**
* check if a Message is a Rest Message
*
* @param message
* @return
*/
static boolean isRestMessage(Message message) {
//String resName = (String) message.getExchange().get("org.apache.cxf.resource.operation.name");
return !(message.getExchange().getBinding() instanceof SoapBinding);
}
}