/* * #%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.util.Queue; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.message.Exchange; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; import org.apache.cxf.phase.AbstractPhaseInterceptor; import org.apache.cxf.phase.Phase; import org.apache.cxf.service.model.BindingOperationInfo; import org.apache.cxf.ws.addressing.AddressingProperties; import org.apache.cxf.ws.addressing.ContextUtils; import org.talend.esb.sam.common.event.Event; import org.talend.esb.sam.common.spi.EventHandler; /** * Maps the CXF Message to an Event and sends Event to Queue. */ public class EventProducerInterceptor extends AbstractPhaseInterceptor<Message> { private static final Logger LOG = Logger.getLogger(EventProducerInterceptor.class.getName()); private final MessageToEventMapper mapper; private final Queue<Event> queue; private EventHandler handler; private static final String SAM_OPERATION = "{http://www.talend.org/esb/sam/MonitoringService/v1}putEvents"; /** * Instantiates a new event producer interceptor. * * @param mapper the mapper * @param queue the queue */ public EventProducerInterceptor(MessageToEventMapper mapper, Queue<Event> queue) { super(Phase.PRE_INVOKE); if (mapper == null) { throw new RuntimeException("Mapper must be set on EventFeature"); } if (queue == null) { throw new RuntimeException("Queue must be set on EventFeature"); } this.mapper = mapper; this.queue = queue; } /** * Sets the handler. * * @param handler the new handler */ public void setHandler(EventHandler handler) { this.handler = handler; } /* (non-Javadoc) * @see org.apache.cxf.interceptor.Interceptor#handleMessage(org.apache.cxf.message.Message) */ @Override public void handleMessage(Message message) throws Fault { //ignore the messages from SAM Server service itself BindingOperationInfo boi = message.getExchange().getBindingOperationInfo(); if (null != boi){ String operationName = boi.getName().toString(); if (SAM_OPERATION.equals(operationName)) { return; } } if (isRestWadlRequest(message)) { // skip handling REST service WADL requests - temporary fix since will be fixed in CXF soon return; } if (isOnewayResponse(message)) { // skip oneway response events return; } //check MessageID checkMessageID(message); Event event = mapper.mapToEvent(message); if (null != handler) { handler.handleEvent(event); } if (LOG.isLoggable(Level.FINE)) { String id = (event.getMessageInfo() != null) ? event.getMessageInfo().getMessageId() : null; LOG.fine("Store event [message_id=" + id + "] in cache."); } if (null != event) { queue.add(event); } } /** * check if MessageID exists in the message, if not, only generate new MessageID for outbound message. * @param message */ private void checkMessageID(Message message) { if (!MessageUtils.isOutbound(message)) return; AddressingProperties maps = ContextUtils.retrieveMAPs(message, false, MessageUtils.isOutbound(message)); if (maps == null) { maps = new AddressingProperties(); } if (maps.getMessageID() == null) { String messageID = ContextUtils.generateUUID(); boolean isRequestor = ContextUtils.isRequestor(message); maps.setMessageID(ContextUtils.getAttributedURI(messageID)); ContextUtils.storeMAPs(maps, message, ContextUtils.isOutbound(message), isRequestor); } } private boolean isRestWadlRequest(Message message) { if (MessageToEventMapper.isRestMessage(message)) { String queryString = (String) message.get(Message.QUERY_STRING); boolean isRestWadlRequest = isRestWadlRequest(queryString); if (isRestWadlRequest) { return true; } // unfortunately response for WADL request do not contain request QUERY_STRING if (MessageUtils.isOutbound(message)) { Exchange ex = message.getExchange(); if (null != ex) { Message requestMessage = ex.getInMessage(); if (null != requestMessage) { queryString = (String) requestMessage.get(Message.QUERY_STRING); return isRestWadlRequest(queryString); } } } } return false; } private boolean isRestWadlRequest(String requestQueryString) { if (null != requestQueryString) { String[] queryParams = requestQueryString.split("&"); for (String param : queryParams) { if ("_wadl".equals(param) || param.startsWith("_wadl=")) { return true; } } } return false; } private boolean isOnewayResponse(Message message) { boolean isRequestor = MessageUtils.isRequestor(message); boolean isFault = MessageUtils.isFault(message); boolean isOutbound = MessageUtils.isOutbound(message); boolean isOnewayOutResp = message.getExchange().isOneWay() && isOutbound && !isRequestor && !isFault && !MessageToEventMapper.isRestMessage(message); boolean isOnewayInResp = message.getExchange().isOneWay() && !isOutbound && isRequestor && !isFault && !MessageToEventMapper.isRestMessage(message); return isOnewayOutResp || isOnewayInResp; } }