/* * Copyright 2012 Research Studios Austria Forschungsges.m.b.H. * * 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. */ package won.node.camel.processor.general; import org.apache.camel.Exchange; import org.apache.camel.Expression; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.support.AopUtils; import org.springframework.beans.factory.InitializingBean; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import won.node.camel.processor.annotation.DefaultFacetMessageProcessor; import won.node.camel.processor.annotation.FacetMessageProcessor; import won.protocol.message.WonMessage; import won.protocol.message.WonMessageDirection; import won.protocol.message.WonMessageType; import won.protocol.message.processor.camel.WonCamelConstants; import won.protocol.message.processor.exception.MissingMessagePropertyException; import won.protocol.message.processor.exception.WonMessageProcessingException; import won.protocol.vocabulary.WONMSG; import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * User: syim * Date: 11.03.2015 */ public class FacetTypeSlipComputer implements InitializingBean, ApplicationContextAware, Expression { Logger logger = LoggerFactory.getLogger(this.getClass()); HashMap<String, Object> facetMessageProcessorsMap; private ApplicationContext applicationContext; public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } @Override public void afterPropertiesSet() throws Exception { facetMessageProcessorsMap = (HashMap)applicationContext.getBeansWithAnnotation(FacetMessageProcessor .class); } @Override public <T> T evaluate(final Exchange exchange, final Class<T> type) { WonMessage message = (WonMessage) exchange.getIn().getHeader(WonCamelConstants.MESSAGE_HEADER); assert message != null : "wonMessage header must not be null"; String slip =""; // exchange.getIn().setHeader(); URI messageType = (URI) exchange.getIn().getHeader(WonCamelConstants.MESSAGE_TYPE_HEADER); assert messageType != null : "messageType header must not be null"; URI direction = (URI) exchange.getIn().getHeader(WonCamelConstants.DIRECTION_HEADER); assert direction != null : "direction header must not be null"; URI facetType = (URI) exchange.getIn().getHeader(WonCamelConstants.FACET_TYPE_HEADER); //for ordinary messages, the process method is called //for responses, the on[Failure|Success]Response is called. String method = "process"; if (WonMessageDirection.FROM_EXTERNAL.isIdentifiedBy(direction)){ //check if we're handling a response. If so, do special routing //the response comes from the remote node, but the handler we need is the //one that sent the original message, so we have to switch direction //and we have to set the type to the type of the original message that //we are now handling the response to if (WonMessageType.SUCCESS_RESPONSE.isIdentifiedBy(messageType)){ method = "onSuccessResponse"; direction = URI.create(WonMessageDirection.FROM_OWNER.getResource().toString()); WonMessageType origType = message.getIsResponseToMessageType(); if (origType == null) { throw new MissingMessagePropertyException(URI.create(WONMSG.IS_RESPONSE_TO_MESSAGE_TYPE.getURI().toString())); } messageType = origType.getURI(); } else if (WonMessageType.FAILURE_RESPONSE.isIdentifiedBy(messageType)){ WonMessageType isResponseToType = message.getIsResponseToMessageType(); if (WonMessageType.FAILURE_RESPONSE == isResponseToType || WonMessageType.SUCCESS_RESPONSE == isResponseToType) { //exception from the exception: if we're handling a FailureResponse // to a response - in that case, don't compute a slip value - no bean // will specially process this. return null; } method = "onFailureResponse"; direction = URI.create(WonMessageDirection.FROM_OWNER.getResource().toString()); WonMessageType origType = message.getIsResponseToMessageType(); if (origType == null) { throw new MissingMessagePropertyException( URI.create(WONMSG.IS_RESPONSE_TO_MESSAGE_TYPE.getURI().toString())); } messageType = origType.getURI(); } } try { slip = "bean:"+computeFacetSlip(messageType, facetType, direction) + "?method=" + method; } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } return type.cast(slip); } private String computeFacetSlip(URI messageType, URI facetType, URI direction) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { Iterator iter = facetMessageProcessorsMap.entrySet().iterator(); while(iter.hasNext()){ Map.Entry pair = (Map.Entry)iter.next(); Object facet = pair.getValue(); if (facetType != null) { Annotation annotation = AopUtils.getTargetClass(facet).getAnnotation(FacetMessageProcessor.class); if(matches(annotation, messageType, direction, facetType)){ return pair.getKey().toString(); } } else { Annotation annotation = AopUtils.getTargetClass(facet).getAnnotation(DefaultFacetMessageProcessor .class); if(matches(annotation, messageType, direction, facetType)){ return pair.getKey().toString(); } } } throw new WonMessageProcessingException(String.format("unexpected combination of messageType %s, " + "facetType %s and direction %s encountered", messageType, facetType, direction)); } private boolean matches(Annotation annotation, URI messageType, URI direction, URI facetType) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { if (annotation == null || messageType==null||direction==null) return false; if (messageType != null){ if (!annotationFeatureMatches(annotation, messageType.toString(), "messageType")){ return false; } } if (direction != null){ if (!annotationFeatureMatches(annotation, direction.toString(), "direction")){ return false; } } if (facetType != null){ if (!annotationFeatureMatches(annotation, facetType.toString(), "facetType")){ return false; } } return true; } private boolean annotationFeatureMatches(Annotation annotation, String expected, String featureName) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { return expected.equals(annotation.annotationType().getDeclaredMethod(featureName).invoke(annotation)); } }