/* * Copyright (C) 2015 * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.cleverbus.component.externalcall; import java.util.Arrays; import org.cleverbus.api.extcall.ExtCallComponentParams; import org.cleverbus.spi.extcall.ExternalCallService; import org.apache.camel.CamelContext; import org.apache.camel.Component; import org.apache.camel.ComponentConfiguration; import org.apache.camel.Endpoint; import org.apache.camel.EndpointConfiguration; import org.apache.camel.Produce; import org.apache.camel.ProducerTemplate; import org.apache.camel.impl.DefaultComponentConfiguration; import org.apache.camel.util.ObjectHelper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.util.Assert; /** * Apache Camel Component for wrapping external calls with checks for duplicate and outdated calls. * <p/> * The URI format is the following: * {@code extcall:[keyType]:[targetURI]} where keyType can be one of: * <ol><li>{@code message} - to generate a key based on message source system and correlation ID, * effectively providing duplicate call protection, but not obsolete call protection</li> * <li>{@code entity} - to generate a key based on message objectId property, * providing both duplicate call protection and obsolete call protection</li> * <li>{@code custom} - to use a custom key provided in the {@link ExtCallComponentParams#EXTERNAL_CALL_KEY} exchange property</li> * </ol> * In the first two cases (message and entity), * if the {@link ExtCallComponentParams#EXTERNAL_CALL_KEY} exchange property is provided, * it will be appended to the generated key. * <p/> * By default, the {@code targetURI} is used as the operation. * This can be changed by providing an optional {@link ExtCallComponentParams#EXTERNAL_CALL_OPERATION} exchange property. * The targetURI will still be the URI that is called, if the external call is not skipped, * but the duplicate/obsolete protection logic will use the {@link ExtCallComponentParams#EXTERNAL_CALL_OPERATION} value for checking, * if the call should be made or skipped. */ public class ExternalCallComponent implements Component { @Autowired private ExternalCallService service; @Produce private ProducerTemplate producer; private CamelContext context; @Override public Endpoint createEndpoint(String uri) throws Exception { String endpointURI = ObjectHelper.after(uri, ":"); if (endpointURI != null && endpointURI.startsWith("//")) { endpointURI = endpointURI.substring(2); } Assert.hasText(endpointURI, "External Call endpoint URI must not be empty"); String keyTypeString = ObjectHelper.before(endpointURI, ":"); Assert.notNull(keyTypeString, "External Call endpoint URI must be in format [keyType]:[targetURI]"); String targetURI = ObjectHelper.after(endpointURI, ":"); if (targetURI != null && targetURI.startsWith("//")) { targetURI = targetURI.substring(2); } Assert.hasText(keyTypeString, "External Call key type must not be empty"); Assert.hasText(targetURI, "External Call target URI must not be empty"); ExternalCallKeyType keyType = null; for (ExternalCallKeyType aKeyType : ExternalCallKeyType.values()) { if (aKeyType.name().equalsIgnoreCase(keyTypeString)) { keyType = aKeyType; break; } } Assert.notNull(keyType, String.format("External Call key type \"%s\" is invalid. It must be one of: %s", keyTypeString, Arrays.toString(ExternalCallKeyType.values()))); return new ExternalCallEndpoint(uri, this, keyType, targetURI); } @Override public boolean useRawUri() { return false; } @Override public EndpointConfiguration createConfiguration(String uri) throws Exception { return null; } @Override public ComponentConfiguration createComponentConfiguration() { return new DefaultComponentConfiguration(this); } @Override public void setCamelContext(CamelContext camelContext) { context = camelContext; } @Override public CamelContext getCamelContext() { return context; } ProducerTemplate getProducerTemplate() { return producer; } ExternalCallService getService() { return service; } }