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