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 */
017package org.apache.camel.support;
018
019import org.apache.camel.Exchange;
020import org.apache.camel.model.remote.ServiceCallDefinition;
021import org.apache.camel.util.ObjectHelper;
022import org.slf4j.Logger;
023import org.slf4j.LoggerFactory;
024
025/**
026 * Support class for custom implementations of {@link ServiceCallDefinition ServiceCall EIP} components.
027 * <p/>
028 * Below are some examples how to call a service and what Camel endpoint URI is constructed based on the input:
029 * <pre>
030     serviceCall("myService") -> http://hostname:port
031     serviceCall("myService/foo") -> http://hostname:port/foo
032     serviceCall("http:myService/foo") -> http:hostname:port/foo
033     serviceCall("myService", "http:myService.host:myService.port/foo") -> http:hostname:port/foo
034     serviceCall("myService", "netty4:tcp:myService?connectTimeout=1000") -> netty:tcp:hostname:port?connectTimeout=1000
035 * </pre>
036 */
037public abstract class ServiceCallExpressionSupport extends ExpressionAdapter {
038
039    private static final Logger LOG = LoggerFactory.getLogger(ServiceCallExpressionSupport.class);
040
041    private final String name;
042    private final String scheme;
043    private final String contextPath;
044    private final String uri;
045
046    public ServiceCallExpressionSupport(String name, String scheme, String contextPath, String uri) {
047        this.name = name;
048        this.scheme = scheme;
049        this.contextPath = contextPath;
050        this.uri = uri;
051    }
052
053    public abstract String getIp(Exchange exchange) throws Exception;
054
055    public abstract int getPort(Exchange exchange) throws Exception;
056
057    @Override
058    public Object evaluate(Exchange exchange) {
059        try {
060            String ip = getIp(exchange);
061            int port = getPort(exchange);
062            return buildCamelEndpointUri(ip, port, name, uri, contextPath, scheme);
063        } catch (Exception e) {
064            throw ObjectHelper.wrapRuntimeCamelException(e);
065        }
066    }
067
068    protected static String buildCamelEndpointUri(String ip, int port, String name, String uri, String contextPath, String scheme) {
069        // build basic uri if none provided
070        String answer = uri;
071        if (answer == null) {
072            if (scheme == null) {
073                // use http/https by default if no scheme has been configured
074                if (port == 443) {
075                    scheme = "https";
076                } else {
077                    scheme = "http";
078                }
079            }
080            answer = scheme + "://" + ip + ":" + port;
081            if (contextPath != null) {
082                answer += "" + contextPath;
083            }
084        } else {
085            // we have existing uri, then replace the serviceName with ip:port
086            if (answer.contains(name + ".host")) {
087                answer = answer.replaceFirst(name + "\\.host", ip);
088            }
089            if (answer.contains(name + ".port")) {
090                answer = answer.replaceFirst(name + "\\.port", "" + port);
091            }
092            if (answer.contains(name)) {
093                answer = answer.replaceFirst(name, ip + ":" + port);
094            }
095        }
096
097        LOG.debug("Camel endpoint uri: {} for calling service: {} on server {}:{}", answer, name, ip, port);
098        return answer;
099    }
100
101}