001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.servicemix.components.cache;
018
019 import java.util.Map;
020
021 import javax.jbi.JBIException;
022 import javax.jbi.messaging.Fault;
023 import javax.jbi.messaging.InOut;
024 import javax.jbi.messaging.MessageExchange;
025 import javax.jbi.messaging.MessagingException;
026 import javax.jbi.messaging.NormalizedMessage;
027
028 import org.apache.servicemix.components.util.TransformComponentSupport;
029 import org.apache.servicemix.expression.Expression;
030 import org.apache.servicemix.expression.PropertyExpression;
031 import org.apache.servicemix.jbi.NoOutMessageAvailableException;
032
033 /**
034 * Implements a caching layer on top of a service invocation to avoid calling an expensive remote service too often.
035 * The cache can be a simple Map based cache or a full <a href="http://www.jcp.org/en/jsr/detail?id=107">JCache</a> instance.
036 *
037 * @version $Revision: 2153 $
038 */
039 public class CacheComponent extends TransformComponentSupport {
040
041 public static final PropertyExpression KEY_PROPERTY_EXPRESSION = new PropertyExpression("org.apache.servicemix.key");
042
043 private Map cache;
044 private Expression keyExpression = KEY_PROPERTY_EXPRESSION;
045
046 public Map getCache() {
047 return cache;
048 }
049
050 public void setCache(Map cache) {
051 this.cache = cache;
052 }
053
054 public Expression getKeyExpression() {
055 return keyExpression;
056 }
057
058 public void setKeyExpression(Expression keyExpression) {
059 this.keyExpression = keyExpression;
060 }
061
062
063 // Implementation methods
064 //-------------------------------------------------------------------------
065 protected void init() throws JBIException {
066 super.init();
067 if (cache == null) {
068 throw new JBIException("You must specify a cache property");
069 }
070 }
071
072 protected boolean transform(MessageExchange exchange, NormalizedMessage in, NormalizedMessage out) throws MessagingException {
073 Object key = keyExpression.evaluate(exchange, in);
074 if (key != null) {
075 NormalizedMessage message = (NormalizedMessage) cache.get(key);
076 if (message != null) {
077 getMessageTransformer().transform(exchange, message, out);
078 return true;
079 }
080 }
081
082 InOut inOut = getExchangeFactory().createInOutExchange();
083 NormalizedMessage request = inOut.createMessage();
084 getMessageTransformer().transform(exchange, in, request);
085 inOut.setInMessage(request);
086 getDeliveryChannel().sendSync(inOut);
087
088 NormalizedMessage response = inOut.getOutMessage();
089 Fault fault = inOut.getFault();
090 Exception error = inOut.getError();
091 if (fault != null) {
092 fail(exchange, fault);
093 }
094 else if (error != null) {
095 fail(exchange, error);
096 }
097 else if (response != null) {
098 getMessageTransformer().transform(exchange, response, out);
099
100 if (key != null) {
101 cache.put(key, response);
102 }
103 }
104 else {
105 throw new NoOutMessageAvailableException(exchange);
106 }
107 return true;
108 }
109
110 }