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.camel.util; 018 019 import java.io.IOException; 020 import java.net.URL; 021 import java.util.Enumeration; 022 import java.util.Locale; 023 import java.util.Map; 024 import java.util.Properties; 025 import java.util.Set; 026 import java.util.SortedMap; 027 import java.util.StringTokenizer; 028 import java.util.TreeMap; 029 030 import org.apache.camel.CamelContext; 031 import org.apache.camel.Component; 032 import org.apache.camel.Endpoint; 033 import org.apache.camel.Exchange; 034 import org.apache.camel.NoSuchBeanException; 035 import org.apache.camel.NoSuchEndpointException; 036 037 import static org.apache.camel.util.ObjectHelper.isEmpty; 038 import static org.apache.camel.util.ObjectHelper.isNotEmpty; 039 import static org.apache.camel.util.ObjectHelper.notNull; 040 041 /** 042 * A number of helper methods 043 * 044 * @version 045 */ 046 public final class CamelContextHelper { 047 public static final String COMPONENT_DESCRIPTOR = "META-INF/services/org/apache/camel/component.properties"; 048 049 /** 050 * Utility classes should not have a public constructor. 051 */ 052 private CamelContextHelper() { 053 } 054 055 /** 056 * Returns the mandatory endpoint for the given URI or the 057 * {@link org.apache.camel.NoSuchEndpointException} is thrown 058 */ 059 public static Endpoint getMandatoryEndpoint(CamelContext camelContext, String uri) 060 throws NoSuchEndpointException { 061 Endpoint endpoint = camelContext.getEndpoint(uri); 062 if (endpoint == null) { 063 throw new NoSuchEndpointException(uri); 064 } else { 065 return endpoint; 066 } 067 } 068 069 /** 070 * Returns the mandatory endpoint for the given URI and type or the 071 * {@link org.apache.camel.NoSuchEndpointException} is thrown 072 */ 073 public static <T extends Endpoint> T getMandatoryEndpoint(CamelContext camelContext, String uri, Class<T> type) { 074 Endpoint endpoint = getMandatoryEndpoint(camelContext, uri); 075 return ObjectHelper.cast(type, endpoint); 076 } 077 078 /** 079 * Converts the given value to the requested type 080 */ 081 public static <T> T convertTo(CamelContext context, Class<T> type, Object value) { 082 notNull(context, "camelContext"); 083 return context.getTypeConverter().convertTo(type, value); 084 } 085 086 /** 087 * Converts the given value to the specified type throwing an {@link IllegalArgumentException} 088 * if the value could not be converted to a non null value 089 */ 090 public static <T> T mandatoryConvertTo(CamelContext context, Class<T> type, Object value) { 091 T answer = convertTo(context, type, value); 092 if (answer == null) { 093 throw new IllegalArgumentException("Value " + value + " converted to " + type.getName() + " cannot be null"); 094 } 095 return answer; 096 } 097 098 /** 099 * Creates a new instance of the given type using the {@link org.apache.camel.spi.Injector} on the given 100 * {@link CamelContext} 101 */ 102 public static <T> T newInstance(CamelContext context, Class<T> beanType) { 103 return context.getInjector().newInstance(beanType); 104 } 105 106 /** 107 * Look up the given named bean in the {@link org.apache.camel.spi.Registry} on the 108 * {@link CamelContext} 109 */ 110 public static Object lookup(CamelContext context, String name) { 111 return context.getRegistry().lookup(name); 112 } 113 114 /** 115 * Look up the given named bean of the given type in the {@link org.apache.camel.spi.Registry} on the 116 * {@link CamelContext} 117 */ 118 public static <T> T lookup(CamelContext context, String name, Class<T> beanType) { 119 return context.getRegistry().lookup(name, beanType); 120 } 121 122 /** 123 * Look up the given named bean in the {@link org.apache.camel.spi.Registry} on the 124 * {@link CamelContext} or throws {@link NoSuchBeanException} if not found. 125 */ 126 public static Object mandatoryLookup(CamelContext context, String name) { 127 Object answer = lookup(context, name); 128 if (answer == null) { 129 throw new NoSuchBeanException(name); 130 } 131 return answer; 132 } 133 134 /** 135 * Look up the given named bean of the given type in the {@link org.apache.camel.spi.Registry} on the 136 * {@link CamelContext} or throws NoSuchBeanException if not found. 137 */ 138 public static <T> T mandatoryLookup(CamelContext context, String name, Class<T> beanType) { 139 T answer = lookup(context, name, beanType); 140 if (answer == null) { 141 throw new NoSuchBeanException(name, beanType.getName()); 142 } 143 return answer; 144 } 145 146 /** 147 * Evaluates the @EndpointInject annotation using the given context 148 */ 149 public static Endpoint getEndpointInjection(CamelContext camelContext, String uri, String ref, String injectionPointName, boolean mandatory) { 150 if (ObjectHelper.isNotEmpty(uri) && ObjectHelper.isNotEmpty(ref)) { 151 throw new IllegalArgumentException("Both uri and name is provided, only either one is allowed: uri=" + uri + ", ref=" + ref); 152 } 153 154 Endpoint endpoint; 155 if (isNotEmpty(uri)) { 156 endpoint = camelContext.getEndpoint(uri); 157 } else { 158 // if a ref is given then it should be possible to lookup 159 // otherwise we do not catch situations where there is a typo etc 160 if (isNotEmpty(ref)) { 161 endpoint = mandatoryLookup(camelContext, ref, Endpoint.class); 162 } else { 163 if (isEmpty(ref)) { 164 ref = injectionPointName; 165 } 166 if (mandatory) { 167 endpoint = mandatoryLookup(camelContext, ref, Endpoint.class); 168 } else { 169 endpoint = lookup(camelContext, ref, Endpoint.class); 170 } 171 } 172 } 173 return endpoint; 174 } 175 176 /** 177 * Gets the maximum cache pool size. 178 * <p/> 179 * Will use the property set on CamelContext with the key {@link Exchange#MAXIMUM_CACHE_POOL_SIZE}. 180 * If no property has been set, then it will fallback to return a size of 1000. 181 * 182 * @param camelContext the camel context 183 * @return the maximum cache size 184 * @throws IllegalArgumentException is thrown if the property is illegal 185 */ 186 public static int getMaximumCachePoolSize(CamelContext camelContext) throws IllegalArgumentException { 187 if (camelContext != null) { 188 String s = camelContext.getProperties().get(Exchange.MAXIMUM_CACHE_POOL_SIZE); 189 if (s != null) { 190 try { 191 // we cannot use Camel type converters as they may not be ready this early 192 Integer size = Integer.valueOf(s); 193 if (size == null || size <= 0) { 194 throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_CACHE_POOL_SIZE + " must be a positive number, was: " + s); 195 } 196 return size; 197 } catch (NumberFormatException e) { 198 throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_CACHE_POOL_SIZE + " must be a positive number, was: " + s, e); 199 } 200 } 201 } 202 203 // 1000 is the default fallback 204 return 1000; 205 } 206 207 /** 208 * Gets the maximum endpoint cache size. 209 * <p/> 210 * Will use the property set on CamelContext with the key {@link Exchange#MAXIMUM_ENDPOINT_CACHE_SIZE}. 211 * If no property has been set, then it will fallback to return a size of 1000. 212 * 213 * @param camelContext the camel context 214 * @return the maximum cache size 215 * @throws IllegalArgumentException is thrown if the property is illegal 216 */ 217 public static int getMaximumEndpointCacheSize(CamelContext camelContext) throws IllegalArgumentException { 218 if (camelContext != null) { 219 String s = camelContext.getProperties().get(Exchange.MAXIMUM_ENDPOINT_CACHE_SIZE); 220 if (s != null) { 221 // we cannot use Camel type converters as they may not be ready this early 222 try { 223 Integer size = Integer.valueOf(s); 224 if (size == null || size <= 0) { 225 throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_ENDPOINT_CACHE_SIZE + " must be a positive number, was: " + s); 226 } 227 return size; 228 } catch (NumberFormatException e) { 229 throw new IllegalArgumentException("Property " + Exchange.MAXIMUM_ENDPOINT_CACHE_SIZE + " must be a positive number, was: " + s, e); 230 } 231 } 232 } 233 234 // 1000 is the default fallback 235 return 1000; 236 } 237 238 /** 239 * Parses the given text and handling property placeholders as well 240 * 241 * @param camelContext the camel context 242 * @param text the text 243 * @return the parsed text, or <tt>null</tt> if the text was <tt>null</tt> 244 * @throws Exception is thrown if illegal argument 245 */ 246 public static String parseText(CamelContext camelContext, String text) throws Exception { 247 // ensure we support property placeholders 248 return camelContext.resolvePropertyPlaceholders(text); 249 } 250 251 /** 252 * Parses the given text and converts it to an Integer and handling property placeholders as well 253 * 254 * @param camelContext the camel context 255 * @param text the text 256 * @return the integer vale, or <tt>null</tt> if the text was <tt>null</tt> 257 * @throws Exception is thrown if illegal argument or type conversion not possible 258 */ 259 public static Integer parseInteger(CamelContext camelContext, String text) throws Exception { 260 // ensure we support property placeholders 261 String s = camelContext.resolvePropertyPlaceholders(text); 262 if (s != null) { 263 try { 264 return camelContext.getTypeConverter().mandatoryConvertTo(Integer.class, s); 265 } catch (NumberFormatException e) { 266 if (s.equals(text)) { 267 throw new IllegalArgumentException("Error parsing [" + s + "] as an Integer.", e); 268 } else { 269 throw new IllegalArgumentException("Error parsing [" + s + "] from property " + text + " as an Integer.", e); 270 } 271 } 272 } 273 return null; 274 } 275 276 /** 277 * Parses the given text and converts it to an Long and handling property placeholders as well 278 * 279 * @param camelContext the camel context 280 * @param text the text 281 * @return the long vale, or <tt>null</tt> if the text was <tt>null</tt> 282 * @throws Exception is thrown if illegal argument or type conversion not possible 283 */ 284 public static Long parseLong(CamelContext camelContext, String text) throws Exception { 285 // ensure we support property placeholders 286 String s = camelContext.resolvePropertyPlaceholders(text); 287 if (s != null) { 288 try { 289 return camelContext.getTypeConverter().mandatoryConvertTo(Long.class, s); 290 } catch (NumberFormatException e) { 291 if (s.equals(text)) { 292 throw new IllegalArgumentException("Error parsing [" + s + "] as a Long.", e); 293 } else { 294 throw new IllegalArgumentException("Error parsing [" + s + "] from property " + text + " as a Long.", e); 295 } 296 } 297 } 298 return null; 299 } 300 301 /** 302 * Parses the given text and converts it to a Double and handling property placeholders as well 303 * 304 * @param camelContext the camel context 305 * @param text the text 306 * @return the double vale, or <tt>null</tt> if the text was <tt>null</tt> 307 * @throws Exception is thrown if illegal argument or type conversion not possible 308 */ 309 public static Double parseDouble(CamelContext camelContext, String text) throws Exception { 310 // ensure we support property placeholders 311 String s = camelContext.resolvePropertyPlaceholders(text); 312 if (s != null) { 313 try { 314 return camelContext.getTypeConverter().mandatoryConvertTo(Double.class, s); 315 } catch (NumberFormatException e) { 316 if (s.equals(text)) { 317 throw new IllegalArgumentException("Error parsing [" + s + "] as an Integer.", e); 318 } else { 319 throw new IllegalArgumentException("Error parsing [" + s + "] from property " + text + " as an Integer.", e); 320 } 321 } 322 } 323 return null; 324 } 325 326 /** 327 * Parses the given text and converts it to an Boolean and handling property placeholders as well 328 * 329 * @param camelContext the camel context 330 * @param text the text 331 * @return the boolean vale, or <tt>null</tt> if the text was <tt>null</tt> 332 * @throws Exception is thrown if illegal argument or type conversion not possible 333 */ 334 public static Boolean parseBoolean(CamelContext camelContext, String text) throws Exception { 335 // ensure we support property placeholders 336 String s = camelContext.resolvePropertyPlaceholders(text); 337 if (s != null) { 338 s = s.trim().toLowerCase(Locale.ENGLISH); 339 if (s.equals("true") || s.equals("false")) { 340 return "true".equals(s) ? Boolean.TRUE : Boolean.FALSE; 341 } else { 342 if (s.equals(text)) { 343 throw new IllegalArgumentException("Error parsing [" + s + "] as a Boolean."); 344 } else { 345 throw new IllegalArgumentException("Error parsing [" + s + "] from property " + text + " as a Boolean."); 346 } 347 } 348 } 349 return null; 350 } 351 352 /** 353 * Finds all possible Components on the classpath and Registry 354 */ 355 public static SortedMap<String, Properties> findComponents(CamelContext camelContext) throws LoadPropertiesException { 356 SortedMap<String,Properties> map = new TreeMap<String, Properties>(); 357 Enumeration<URL> iter = camelContext.getClassResolver().loadResourcesAsURL(COMPONENT_DESCRIPTOR); 358 while (iter.hasMoreElements()) { 359 URL url = iter.nextElement(); 360 try { 361 Properties properties = new Properties(); 362 properties.load(url.openStream()); 363 String names = properties.getProperty("components"); 364 if (names != null) { 365 StringTokenizer tok = new StringTokenizer(names); 366 while (tok.hasMoreTokens()) { 367 String name = tok.nextToken(); 368 map.put(name, properties); 369 } 370 } 371 } catch (IOException e) { 372 throw new LoadPropertiesException(url, e); 373 } 374 } 375 376 // lets see what other components are in the registry 377 Map<String,Component> beanMap = camelContext.getRegistry().lookupByType(Component.class); 378 Set<Map.Entry<String,Component>> entries = beanMap.entrySet(); 379 for (Map.Entry<String, Component> entry : entries) { 380 String name = entry.getKey(); 381 if (!map.containsKey(name)) { 382 Properties properties = new Properties(); 383 Component component = entry.getValue(); 384 if (component != null) { 385 properties.put("component", component); 386 properties.put("class", component.getClass().getName()); 387 map.put(name, properties); 388 } 389 } 390 } 391 return map; 392 } 393 }