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.blueprint; 018 019import java.lang.reflect.Modifier; 020import java.util.List; 021import java.util.Set; 022 023import org.apache.camel.RoutesBuilder; 024import org.apache.camel.spi.PackageScanClassResolver; 025import org.osgi.service.blueprint.container.BlueprintContainer; 026import org.osgi.service.blueprint.reflect.BeanMetadata; 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029 030/** 031 * A helper class which will find all {@link org.apache.camel.builder.RouteBuilder} instances on the classpath 032 * 033 * @version 034 */ 035public class PackageScanRouteBuilderFinder { 036 private static final Logger LOG = LoggerFactory.getLogger(PackageScanRouteBuilderFinder.class); 037 private final BlueprintCamelContext camelContext; 038 private final String[] packages; 039 private final PackageScanClassResolver resolver; 040 private final BlueprintContainer blueprintContainer; 041 042 public PackageScanRouteBuilderFinder(BlueprintCamelContext camelContext, String[] packages, ClassLoader classLoader, 043 PackageScanClassResolver resolver) { 044 this.camelContext = camelContext; 045 this.blueprintContainer = camelContext.getBlueprintContainer(); 046 this.packages = packages; 047 this.resolver = resolver; 048 // add our provided loader as well 049 resolver.addClassLoader(classLoader); 050 } 051 052 /** 053 * Appends all the {@link org.apache.camel.builder.RouteBuilder} instances that can be found on the classpath 054 */ 055 public void appendBuilders(List<RoutesBuilder> list) throws IllegalAccessException, InstantiationException { 056 Set<Class<?>> classes = resolver.findImplementations(RoutesBuilder.class, packages); 057 for (Class<?> aClass : classes) { 058 LOG.trace("Found RouteBuilder class: {}", aClass); 059 060 // certain beans should be ignored 061 if (shouldIgnoreBean(aClass)) { 062 LOG.debug("Ignoring RouteBuilder class: {}", aClass); 063 continue; 064 } 065 066 if (!isValidClass(aClass)) { 067 LOG.debug("Ignoring invalid RouteBuilder class: {}", aClass); 068 continue; 069 } 070 071 // type is valid so create and instantiate the builder 072 RoutesBuilder builder = instantiateBuilder(aClass); 073 LOG.debug("Adding instantiated RouteBuilder: {}", builder); 074 list.add(builder); 075 } 076 } 077 078 /** 079 * Allows for ignoring beans that are explicitly configured in the Spring XML files 080 */ 081 protected boolean shouldIgnoreBean(Class<?> type) { 082 for (Object metadataObject : blueprintContainer.getMetadata(BeanMetadata.class)) { 083 BeanMetadata metadata = (BeanMetadata) metadataObject; 084 if (BeanMetadata.SCOPE_SINGLETON.equals(metadata.getScope())) { 085 Object bean = blueprintContainer.getComponentInstance(metadata.getId()); 086 if (type.isInstance(bean)) { 087 return true; 088 } 089 } 090 } 091 return false; 092 } 093 094 /** 095 * Returns <tt>true</tt>if the class is a public, non-abstract class 096 */ 097 protected boolean isValidClass(Class<?> type) { 098 // should skip non public classes 099 if (!Modifier.isPublic(type.getModifiers())) { 100 return false; 101 } 102 103 if (!Modifier.isAbstract(type.getModifiers()) && !type.isInterface()) { 104 return true; 105 } 106 return false; 107 } 108 109 protected RoutesBuilder instantiateBuilder(Class<?> type) throws IllegalAccessException, InstantiationException { 110 return (RoutesBuilder) camelContext.getInjector().newInstance(type); 111 } 112}