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.util.component; 018 019import java.util.Collection; 020import java.util.HashMap; 021import java.util.Map; 022import java.util.Set; 023 024import org.apache.camel.Exchange; 025import org.apache.camel.Processor; 026import org.apache.camel.impl.ScheduledPollConsumer; 027import org.apache.camel.util.ObjectHelper; 028import org.slf4j.Logger; 029import org.slf4j.LoggerFactory; 030 031/** 032 * Abstract base class for API Component Consumers. 033 */ 034public abstract class AbstractApiConsumer<E extends Enum<E> & ApiName, T> 035 extends ScheduledPollConsumer implements PropertyNamesInterceptor, PropertiesInterceptor, ResultInterceptor { 036 037 // logger 038 protected final Logger log = LoggerFactory.getLogger(getClass()); 039 040 // API Endpoint 041 protected final AbstractApiEndpoint<E, T> endpoint; 042 043 // API method to invoke 044 protected final ApiMethod method; 045 046 // split Array or Collection API method results into multiple Exchanges 047 private boolean splitResult = true; 048 049 public AbstractApiConsumer(AbstractApiEndpoint<E, T> endpoint, Processor processor) { 050 super(endpoint, processor); 051 052 this.endpoint = endpoint; 053 this.method = ApiConsumerHelper.findMethod(endpoint, this); 054 } 055 056 @Override 057 public boolean isGreedy() { 058 // make this consumer not greedy to avoid making too many calls 059 return false; 060 } 061 062 @Override 063 protected int poll() throws Exception { 064 // invoke the consumer method 065 final Map<String, Object> args = new HashMap<String, Object>(); 066 args.putAll(endpoint.getEndpointProperties()); 067 068 // let the endpoint and the Consumer intercept properties 069 endpoint.interceptProperties(args); 070 interceptProperties(args); 071 072 try { 073 074 Object result = doInvokeMethod(args); 075 return ApiConsumerHelper.getResultsProcessed(this, result, isSplitResult()); 076 077 } catch (Throwable t) { 078 throw ObjectHelper.wrapRuntimeCamelException(t); 079 } 080 } 081 082 @Override 083 public void interceptPropertyNames(Set<String> propertyNames) { 084 // do nothing by default 085 } 086 087 @Override 088 public void interceptProperties(Map<String, Object> properties) { 089 // do nothing by default 090 } 091 092 /** 093 * Invoke the API method. 094 * This method can be overridden, for example to synchronize API calls for thread-unsafe proxies. 095 * Derived class MUST call super.doInvokeMethod() to invoke the API method. 096 * @param args method arguments from endpoint parameters. 097 * @return method invocation result. 098 */ 099 protected Object doInvokeMethod(Map<String, Object> args) { 100 return ApiMethodHelper.invokeMethod(endpoint.getApiProxy(method, args), method, args); 101 } 102 103 @Override 104 public Object splitResult(Object result) { 105 // process result according to type 106 if (splitResult && result != null && (result instanceof Collection || result.getClass().isArray())) { 107 // create an exchange for every element 108 return getResultAsArray(result); 109 } else { 110 return result; 111 } 112 } 113 114 @Override 115 public void interceptResult(Object result, Exchange resultExchange) { 116 // do nothing by default 117 } 118 119 private static Object getResultAsArray(Object result) { 120 if (result.getClass().isArray()) { 121 // no conversion needed 122 return result; 123 } 124 // must be a Collection 125 Collection<?> collection = (Collection<?>) result; 126 return collection.toArray(new Object[collection.size()]); 127 } 128 129 public final boolean isSplitResult() { 130 return splitResult; 131 } 132 133 public final void setSplitResult(boolean splitResult) { 134 this.splitResult = splitResult; 135 } 136}