Project: blueprint-namespaces
/**
 *  Licensed to the Apache Software Foundation (ASF) under one or more 
 *  contributor license agreements.  See the NOTICE file distributed with 
 *  this work for additional information regarding copyright ownership. 
 *  The ASF licenses this file to You under the Apache License, Version 2.0 
 *  (the "License"); you may not use this file except in compliance with 
 *  the License.  You may obtain a copy of the License at 
 * 
 *     http://www.apache.org/licenses/LICENSE-2.0 
 * 
 *  Unless required by applicable law or agreed to in writing, software 
 *  distributed under the License is distributed on an "AS IS" BASIS, 
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 *  See the License for the specific language governing permissions and 
 *  limitations under the License. 
 */
package org.apache.aries.blueprint.annotation.impl; 
 
import java.io.File; 
import java.io.IOException; 
import java.lang.reflect.Field; 
import java.lang.reflect.Method; 
import java.math.BigInteger; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.util.Arrays; 
import java.util.HashMap; 
import java.util.HashSet; 
import java.util.LinkedHashSet; 
import java.util.List; 
import java.util.Map; 
import java.util.Set; 
 
import javax.xml.bind.JAXBContext; 
import javax.xml.bind.JAXBException; 
import javax.xml.bind.Marshaller; 
 
import org.apache.aries.blueprint.annotation.Arg; 
import org.apache.aries.blueprint.annotation.Bean; 
import org.apache.aries.blueprint.annotation.Bind; 
import org.apache.aries.blueprint.annotation.Blueprint; 
import org.apache.aries.blueprint.annotation.Destroy; 
import org.apache.aries.blueprint.annotation.Init; 
import org.apache.aries.blueprint.annotation.Inject; 
import org.apache.aries.blueprint.annotation.Reference; 
import org.apache.aries.blueprint.annotation.ReferenceList; 
import org.apache.aries.blueprint.annotation.ReferenceListener; 
import org.apache.aries.blueprint.annotation.Register; 
import org.apache.aries.blueprint.annotation.RegistrationListener; 
import org.apache.aries.blueprint.annotation.Service; 
import org.apache.aries.blueprint.annotation.ServiceProperty; 
import org.apache.aries.blueprint.annotation.Unbind; 
import org.apache.aries.blueprint.annotation.Unregister; 
import org.apache.aries.blueprint.annotation.service.BlueprintAnnotationScanner; 
import org.apache.aries.blueprint.jaxb.Targument; 
import org.apache.aries.blueprint.jaxb.Tbean; 
import org.apache.aries.blueprint.jaxb.Tblueprint; 
import org.apache.aries.blueprint.jaxb.Tdescription; 
import org.apache.aries.blueprint.jaxb.Tinterfaces; 
import org.apache.aries.blueprint.jaxb.Tproperty; 
import org.apache.aries.blueprint.jaxb.Treference; 
import org.apache.aries.blueprint.jaxb.TreferenceList; 
import org.apache.aries.blueprint.jaxb.TreferenceListener; 
import org.apache.aries.blueprint.jaxb.TregistrationListener; 
import org.apache.aries.blueprint.jaxb.Tservice; 
import org.apache.aries.blueprint.jaxb.TservicePropertyEntry; 
import org.apache.aries.blueprint.jaxb.TtypeConverters; 
import org.apache.aries.blueprint.jaxb.Tvalue; 
import org.apache.xbean.finder.BundleAnnotationFinder; 
import org.osgi.framework.Bundle; 
import org.osgi.framework.BundleContext; 
import org.osgi.framework.ServiceReference; 
import org.osgi.service.blueprint.container.Converter; 
import org.osgi.service.packageadmin.PackageAdmin; 
 
public class BlueprintAnnotationScannerImpl implements 
        BlueprintAnnotationScanner { 
    private final BundleContext context; 
 
    public BlueprintAnnotationScannerImpl(BundleContext bc) { 
        this.context = bc; 
    } 
 
    private BundleContext getBlueprintExtenderContext() { 
        Bundle[] bundles = this.context.getBundles(); 
        for (Bundle b : bundles) { 
            if (b.getSymbolicName().equals("org.apache.aries.blueprint.core")) { 
                return b.getBundleContext(); 
            } 
        } 
 
        return null
    } 
 
    private BundleAnnotationFinder createBundleAnnotationFinder(Bundle bundle) { 
        ServiceReference sr = this.context.getServiceReference(PackageAdmin.class.getName()); 
        PackageAdmin pa = (PackageAdmin) this.context.getService(sr); 
        BundleAnnotationFinder baf = null
        try { 
            baf = new BundleAnnotationFinder(pa, bundle); 
        } catch (Exception e) { 
            // TODO Auto-generated catch block 
            e.printStackTrace(); 
        } 
 
        this.context.ungetService(sr); 
         
        return baf; 
    } 
     
    public URL createBlueprintModel(Bundle bundle) { 
 
        Tblueprint tblueprint = generateBlueprintModel(bundle); 
 
        if (tblueprint != null) { 
            // create the generated blueprint xml file in bundle storage 
            // area 
            BundleContext ctx = getBlueprintExtenderContext(); 
 
            if (ctx == null) { 
                // blueprint extender doesn't exist, let' still generate the 
                // bundle, using the bundle's bundle context 
                ctx = bundle.getBundleContext(); 
            } 
 
            File dir = ctx.getDataFile(bundle.getSymbolicName() + "/" 
                    + bundle.getVersion() + "/"); 
            if (!dir.exists()) { 
                dir.mkdirs(); 
            } 
            String blueprintPath = cachePath(bundle, 
                    "annotation-generated-blueprint.xml"); 
            File file = ctx.getDataFile(blueprintPath); 
            if (!file.exists()) { 
                try { 
                    file.createNewFile(); 
                } catch (IOException e) { 
                    // TODO Auto-generated catch block 
                    e.printStackTrace(); 
                } 
            } 
            try { 
                marshallOBRModel(tblueprint, file); 
            } catch (JAXBException e) { 
                // TODO Auto-generated catch block 
                e.printStackTrace(); 
            } 
            try { 
                return file.toURL(); 
            } catch (MalformedURLException e) { 
                // TODO Auto-generated catch block 
                e.printStackTrace(); 
            } 
        } 
 
        return null
 
    } 
 
    private void marshallOBRModel(Tblueprint tblueprint, File blueprintFile) 
            throws JAXBException { 
        JAXBContext context = JAXBContext.newInstance(Tblueprint.class); 
        Marshaller marshaller = context.createMarshaller(); 
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); 
        marshaller.marshal(tblueprint, blueprintFile); 
 
    } 
 
    private Tblueprint generateBlueprintModel(Bundle bundle) { 
        BundleAnnotationFinder baf = createBundleAnnotationFinder(bundle); 
 
        // we don't trust baf when it comes to returning classes just once (ARIES-654) 
        Set<Class> blueprintClasses = new LinkedHashSet<Class>(baf.findAnnotatedClasses(Blueprint.class)); 
        Set<Class> beanClasses = new HashSet<Class>(baf.findAnnotatedClasses(Bean.class)); 
        Set<Class> refListenerClasses = new HashSet<Class>(baf.findAnnotatedClasses(ReferenceListener.class)); 
        Set<Class> regListenerClasses = new HashSet<Class>(baf.findAnnotatedClasses(RegistrationListener.class)); 
        Map<String, TreferenceListener> reflMap = new HashMap<String, TreferenceListener>(); 
        Map<String, TregistrationListener> reglMap = new HashMap<String, TregistrationListener>(); 
         
        Tblueprint tblueprint = new Tblueprint(); 
         
         
        if (!blueprintClasses.isEmpty()) { 
            // use the first annotated blueprint annotation 
            Blueprint blueprint = (Blueprint)blueprintClasses.iterator().next().getAnnotation(Blueprint.class); 
            tblueprint.setDefaultActivation(blueprint.defaultActivation()); 
            tblueprint.setDefaultAvailability(blueprint.defaultAvailability()); 
            tblueprint.setDefaultTimeout(convertToBigInteger(blueprint.defaultTimeout())); 
        } 
 
        List<Object> components = tblueprint.getServiceOrReferenceListOrBean(); 
         
        // try to process classes that have @ReferenceListener or @RegistrationLister first 
        // as we want the refl and regl maps populated before processing @Bean annotation. 
        for (Class refListener : refListenerClasses) { 
            Bean bean = (Bean) refListener.getAnnotation(Bean.class); 
                        
            // register the treference with its id 
            TreferenceListener tref = generateTrefListener(refListener); 
             
            if (bean.id().length() > 0) { 
                reflMap.put(bean.id(), tref); 
            } else { 
                throw new BlueprintAnnotationException("Unable to find the id for the @ReferenceListener annotated class " + refListener.getName()); 
            } 
        } 
         
         
        for (Class regListener : regListenerClasses) { 
            Bean bean = (Bean) regListener.getAnnotation(Bean.class); 
             
            // register the tregistrationListener with its id 
            TregistrationListener tref = generateTregListener(regListener); 
             
            if (bean.id().length() > 0) { 
                reglMap.put(bean.id(), tref); 
            } else { 
                throw new BlueprintAnnotationException("Unable to find the id for the @RegistrationListener annotated class " + regListener.getName()); 
            }    
        } 
         
        for (Class clazz : beanClasses) { 
            // @Bean annotation detected 
            Bean bean = (Bean)clazz.getAnnotation(Bean.class); 
            Tbean tbean = new Tbean(); 
             
            // process depends-on property 
            String[] dependsOn = bean.dependsOn(); 
            if (!containsValid(dependsOn)) { 
                tbean.setDependsOn(null); 
            } else { 
                List<String> dons = Arrays.asList(dependsOn); 
                tbean.setDependsOn(dons); 
            } 
             
            // process id property 
            String id = bean.id(); 
            if (id.length() > 0) { 
                tbean.setId(id); 
            } else { 
                // should we auto generate an id, based on the class name? 
                tbean.setId(clazz.getSimpleName()); 
            } 
 
            // process the clazz property 
            tbean.setClazz(clazz.getName()); 
             
            // process activation 
            String activation = bean.activation(); 
            if (activation.length() > 0) { 
                if (activation.equalsIgnoreCase("eager") || activation.equalsIgnoreCase("lazy")) { 
                    tbean.setActivation(bean.activation()); 
                } else { 
                    throw new BlueprintAnnotationException("Invalid bean activation value " + activation + " for " + clazz.getName()); 
                } 
            } 
             
            // process description 
            if (bean.description().length() > 0) { 
                Tdescription desp = new Tdescription(); 
                desp.getContent().add(bean.description()); 
                tbean.setDescription(desp); 
            } 
             
            // process scope 
            String scope = bean.scope(); 
            if (scope.length() > 0) { 
                if (scope.equalsIgnoreCase("singleton") || scope.equalsIgnoreCase("prototype")) { 
                    tbean.setScope(scope); 
                } else { 
                    throw new BlueprintAnnotationException("Invalid bean scope value " + scope + " for " + clazz.getName()); 
                } 
            } 
             
            // process factory ref 
            String factoryRef = bean.factoryRef(); 
            if (factoryRef.length() > 0) { 
                tbean.setFactoryRef(factoryRef); 
            } 
             
            // process factory method 
            String factoryMethod = bean.factoryMethod(); 
            if (factoryMethod.length() > 0) { 
                tbean.setFactoryMethod(factoryMethod); 
            } 
             
 
            List<Object> props = tbean.getArgumentOrPropertyOrAny(); 
 
            // process args  
            Arg[] args = bean.args(); 
             
            if (args.length > 0) { 
                for (int i = 0; i < args.length; i++) { 
                    Targument targ = createTargument(args[i]); 
                    if (targ != null) { 
                        props.add(targ); 
                    } 
                } 
            } 
             
            Field[] fields = clazz.getDeclaredFields(); 
            for (int i = 0; i < fields.length; i++) { 
                if (fields[i].isAnnotationPresent(Inject.class)) {  
                    if (fields[i].isAnnotationPresent(Reference.class)) { 
                        // the field is also annotated with @Reference 
                        Reference ref = fields[i].getAnnotation(Reference.class); 
                        Treference tref = generateTref(ref, reflMap); 
                        components.add(tref); 
                    } else if (fields[i].isAnnotationPresent(ReferenceList.class)) { 
                        // the field is also annotated with @ReferenceList 
                        ReferenceList ref = fields[i].getAnnotation(ReferenceList.class); 
                        TreferenceList tref = generateTrefList(ref, reflMap); 
                        components.add(tref); 
                         
                    } else { 
                        Tproperty tp = createTproperty(fields[i].getName(), fields[i].getAnnotation(Inject.class)); 
                        props.add(tp); 
                    } 
                } 
            } 
                     
            // check if the bean also declares init, destroy or inject annotation on methods 
            Method[] methods = clazz.getDeclaredMethods(); 
            for (int i = 0; i < methods.length; i++) { 
                if (methods[i].isAnnotationPresent(Init.class)) { 
                    tbean.setInitMethod(methods[i].getName()); 
                } else if (methods[i].isAnnotationPresent(Destroy.class)) { 
                    tbean.setDestroyMethod(methods[i].getName()); 
                } else if (methods[i].isAnnotationPresent(Inject.class)) { 
                    String propertyName = convertFromMethodName(methods[i].getName()); 
                    Tproperty tp = createTproperty(propertyName, methods[i].getAnnotation(Inject.class)); 
                    props.add(tp);   
                } else if (methods[i].isAnnotationPresent(Arg.class)) { 
                    Targument targ = createTargument(methods[i].getAnnotation(Arg.class)); 
                    props.add(targ);      
                } 
            } 
             
            // check if the bean also declares service 
            if (clazz.getAnnotation(Service.class) != null) { 
                Tservice tservice = generateTservice(clazz, id, reglMap); 
                components.add(tservice); 
            } 
             
            // check if the clazz implement Converter, if so, it is Converter 
            boolean isConverter = isConverter(clazz); 
            if (isConverter) { 
                TtypeConverters converters = tblueprint.getTypeConverters();  
                List<Object> objects = converters.getBeanOrReferenceOrRef(); 
                objects.add(tbean); 
            } else { 
                components.add(tbean); 
            } 
        } 
 
        return tblueprint; 
    } 
 
    private TreferenceListener generateTrefListener(Class refListener) { 
        ReferenceListener rl = (ReferenceListener) refListener.getAnnotation(ReferenceListener.class); 
         
        String ref = rl.ref(); 
        String bind = null
        String unbind = null
         
        // also check bind/unbind method 
        Method[] methods = refListener.getDeclaredMethods(); 
        for (int i = 0; i < methods.length; i++) { 
            if (methods[i].isAnnotationPresent(Bind.class)) { 
                if (bind == null) { 
                    bind = methods[i].getName(); 
                } else if (!bind.equals(methods[i].getName())) { 
                    throw new BlueprintAnnotationException("@Bind annottaed method for reference listener " + refListener.getName() + " are not consistent");        
                } 
                continue
            } 
            if (methods[i].isAnnotationPresent(Unbind.class)) { 
                if (unbind == null) { 
                  unbind = methods[i].getName(); 
                } else if (!unbind.equals(methods[i].getName())) { 
                    throw new BlueprintAnnotationException("@Unbind annotated method for reference listener " + refListener.getName() + " are not consistent");        
                } 
                continue
            } 
        } 
         
        TreferenceListener trl = new TreferenceListener(); 
        if (bind != null) { 
            trl.setBindMethod(bind); 
        } 
        if (unbind != null) { 
            trl.setUnbindMethod(unbind); 
        } 
         
        if (ref != null) { 
            trl.setRefAttribute(ref); 
        } 
         
        return trl; 
    } 
     
    private TregistrationListener generateTregListener(Class regListener) { 
        RegistrationListener rl = (RegistrationListener) regListener.getAnnotation(RegistrationListener.class); 
         
        String register = null
        String unregister = null
         
        // also check bind/unbind method 
        Method[] methods = regListener.getDeclaredMethods(); 
        for (int i = 0; i < methods.length; i++) { 
            if (methods[i].isAnnotationPresent(Register.class)) { 
                if (register == null) { 
                    register = methods[i].getName(); 
                } else if (!register.equals(methods[i].getName())) { 
                    throw new BlueprintAnnotationException("@Register annottaed method for registration listener " + regListener.getName() + " are not consistent");        
                } 
                continue
            } 
            if (methods[i].isAnnotationPresent(Unregister.class)) { 
                if (unregister == null) { 
                  unregister = methods[i].getName(); 
                } else if (!unregister.equals(methods[i].getName())) { 
                    throw new BlueprintAnnotationException("@Unregister annotated method for registration listener " + regListener.getName() + " are not consistent");        
                } 
                continue
            } 
        } 
         
        TregistrationListener trl = new TregistrationListener(); 
        if (register != null) { 
            trl.setRegistrationMethod(register); 
        } 
        if (unregister != null) { 
            trl.setUnregistrationMethod(unregister); 
        } 
         
        return trl; 
    } 
 
    private Targument createTargument(Arg arg) { 
        String value = arg.value(); 
        String ref = arg.ref(); 
        Targument targ = null
        if (value.length() > 0) { 
            targ = new Targument(); 
            targ.setValueAttribute(value); 
        } 
         
        if (ref.length() > 0) { 
            if (targ == null) { 
                targ = new Targument(); 
            } 
             
            targ.setRefAttribute(ref); 
        } 
         
        // TODO process description, index of Arg annotation 
        return targ; 
    } 
 
    private String convertFromMethodName(String name) { 
        if (name.length() > 3) { 
            name = name.substring(3); 
        } else { 
            throw new BlueprintAnnotationException("The annotated method name " + name + " is invalid"); 
        } 
        String firstChar = name.substring(01).toLowerCase(); 
         
        if (name.length() == 1) { 
            return firstChar; 
        } else { 
            return firstChar + name.substring(1); 
        } 
    } 
 
    /**
     * @param nm    method or field name 
     * @param inj   inject annotation 
     * @return 
     */
 
    private Tproperty createTproperty(String nm, Inject inj) { 
        String value = inj.value(); 
        String ref = inj.ref(); 
        String name = inj.name(); 
        String desp = inj.description(); 
                          
        Tproperty tp = new Tproperty(); 
        if (value.length() > 0) { 
            Tvalue tvalue = new Tvalue(); 
            tvalue.setContent(value); 
            tp.setValue(tvalue); 
        } 
         
        if (ref.length() > 0) { 
            tp.setRefAttribute(ref); 
        } 
         
        if (name.length() > 0) { 
            tp.setName(name); 
        } else { 
            tp.setName(nm); 
        } 
         
        if (desp.length() > 0) { 
            Tdescription tdesp = new Tdescription(); 
            tdesp.getContent().add(desp); 
            tp.setDescription(tdesp); 
             
        } 
         
        return tp; 
    } 
 
    private boolean isConverter(Class clazz) { 
        Class[] classes = clazz.getInterfaces(); 
        for (int i = 0; i < classes.length; i++) { 
            if (classes[i].getName().equals(Converter.class.getName())) { 
                return true
            } 
         
        } 
        return false
 
    } 
    
    private BigInteger convertToBigInteger(int timeout) { 
        return BigInteger.valueOf(timeout * 1000); 
    } 
 
    private boolean containsValid(String[] dependsOn) { 
        for (int i = 0; i < dependsOn.length; i++) { 
            if (dependsOn[i].length() != 0) { 
                return true
            } 
        } 
        return false
    } 
 
    // copy from blueprint extender 
    private String cachePath(Bundle bundle, String filePath) { 
        return bundle.getSymbolicName() + "/" + bundle.getVersion() + "/" 
                + filePath; 
    } 
     
    private Treference generateTref(Reference ref, Map<String, TreferenceListener> reflMap) { 
 
        String id = ref.id(); 
        String availability = ref.availability(); 
        String compName = ref.componentName(); 
        String desp = ref.description(); 
        String filter = ref.filter(); 
        Class<?> serviceInterface = ref.serviceInterface(); 
        ReferenceListener[] refListeners = ref.referenceListeners(); 
        int timeout = ref.timeout(); 
        Treference tref = new Treference(); 
         
        // can not think of configuring depends on for reference 
        tref.setDependsOn(null); 
         
        if (id.length() > 0) { 
            tref.setId(id); 
        } 
         
        if (availability.length() > 0) { 
            tref.setAvailability(availability); 
        } 
        if (compName.length() > 0) { 
            tref.setComponentName(compName); 
        } 
        if (desp.length() > 0) { 
            Tdescription value = new Tdescription(); 
            value.getContent().add(desp); 
            tref.setDescription(value); 
        } 
        if (filter.length() > 0) { 
            tref.setFilter(filter); 
        } 
        if (serviceInterface != Object.class) { 
            tref.setInterface(serviceInterface.getName()); 
        } 
         
        if (timeout > 0) { 
            tref.setTimeout(convertToBigInteger(timeout)); 
        } 
        for (ReferenceListener rl : refListeners) { 
            String rf = rl.ref(); 
            TreferenceListener trl = reflMap.get(rf); 
            if (trl != null) { 
                trl.setRefAttribute(rf); 
                tref.getReferenceListener().add(trl); 
            } else { 
                throw new BlueprintAnnotationException("Unable to find the ReferenceListener ref " + rf); 
            } 
        } 
         
        return tref; 
    } 
     
    private TreferenceList generateTrefList(ReferenceList ref, Map<String, TreferenceListener> reflMap) { 
        String id = ref.id(); 
        String availability = ref.availability(); 
        String compName = ref.componentName(); 
        String desp = ref.description(); 
        String filter = ref.filter(); 
        Class<?> serviceInterface = ref.serviceInterface(); 
        ReferenceListener[] refListeners = ref.referenceListeners(); 
        TreferenceList tref = new TreferenceList(); 
         
        // can not think of configuring depends on for referencelist 
        tref.setDependsOn(null); 
         
        if (id.length() > 0) { 
            tref.setId(id); 
        } 
         
        if (availability.length() > 0) { 
            tref.setAvailability(availability); 
        } 
        if (compName.length() > 0) { 
            tref.setComponentName(compName); 
        } 
        if (desp.length() > 0) { 
            Tdescription value = new Tdescription(); 
            value.getContent().add(desp); 
            tref.setDescription(value); 
        } 
        if (filter.length() > 0) { 
            tref.setFilter(filter); 
        } 
        if (serviceInterface  != Object.class) { 
            tref.setInterface(serviceInterface.getName()); 
        }  
         
        for (ReferenceListener rl : refListeners) { 
            String rf = rl.ref(); 
            TreferenceListener trl = reflMap.get(rf); 
            if (trl != null) { 
                trl.setRefAttribute(rf); 
                tref.getReferenceListener().add(trl); 
            } else { 
                throw new BlueprintAnnotationException("Unable to find the ReferenceListener ref " + rf); 
            } 
        } 
         
        return tref; 
    } 
     
    private Tservice generateTservice(Class clazz, String id, Map<String, TregistrationListener> reglMap) { 
        Service service = (Service) clazz.getAnnotation(Service.class); 
        Class<?>[] interfaces = service.interfaces(); 
        int ranking = service.ranking(); 
        String autoExport = service.autoExport(); 
        ServiceProperty[] serviceProperties = service.serviceProperties(); 
        RegistrationListener[] regListeners = service.registerationListeners(); 
         
        Tservice tservice = new Tservice(); 
         
        // can not think of configuring depends on for service 
        tservice.setDependsOn(null); 
         
        // use the bean id as the ref value since we are exposing service for the bean 
        tservice.setRefAttribute(id); 
         
        if (autoExport.length() > 0) { 
            tservice.setAutoExport(autoExport); 
        } 
        if (ranking > 0) { 
            tservice.setRanking(ranking); 
        } 
        for (Class<?> interf : interfaces) { 
            Tinterfaces tInterfaces = new Tinterfaces(); 
            if (interf != null) { 
                tInterfaces.getValue().add(interf.getName()); 
            } 
            tservice.setInterfaces(tInterfaces); 
        } 
         
        // process service property.  only key value as string are supported for now 
        for (ServiceProperty sp : serviceProperties) { 
            if (sp != null) { 
                String key = sp.key(); 
                String value = sp.value(); 
                if (key.length() > 0 && value.length() > 0) { 
                    TservicePropertyEntry tsp = new TservicePropertyEntry(); 
                    tsp.setKey(key); 
                    tsp.setValueAttribute(value); 
                    tservice.getServiceProperties().getEntry().add(tsp); 
                } 
                 
            } 
        } 
         
        for (RegistrationListener regListener : regListeners) { 
            String ref = regListener.ref(); 
            if (ref.length() > 0) { 
                TregistrationListener tregListener = reglMap.get(ref); 
                tregListener.setRefAttribute(ref); 
                tservice.getRegistrationListener().add(tregListener); 
                 
            } else { 
                throw new BlueprintAnnotationException("No ref id for service registration listener " + " for " + clazz.getName()); 
            } 
        } 
         
        return tservice; 
    } 
}