@SuppressWarnings("unchecked") private <T> T getService(Class<T> serviceType, String filter, long timeout) throws TestContainerException { assert m_framework != null : "Framework should be up"; assert serviceType != null : "serviceType not be null"; final Long start = System.currentTimeMillis(); LOG.info("Aquiring Service " + serviceType.getName() + " " + (filter != null ? filter : "")); do { try { ServiceReference[] reference = m_framework.getBundleContext().getServiceReferences(serviceType.getName(), filter); if (reference != null && reference.length > 0) { return ((T) m_framework.getBundleContext().getService(reference[0])); } Thread.sleep(200); } catch (Exception e) { LOG.error("Some problem during looking up service from framework: " + m_framework, e); } // wait a bit } while ((System.currentTimeMillis()) < start + timeout); printAvailableAlternatives(serviceType); throw new TestContainerException( "Not found a matching Service " + serviceType.getName() + " for Filter:" + (filter != null ? filter : "")); }
/** * Called when this bundle is started so the Framework can perform the bundle-specific activities * necessary to start this bundle. This method can be used to register services or to allocate any * resources that this bundle needs. * * <p>This method must complete and return to its caller in a timely manner. * * @param context The execution context of the bundle being started. * @throws Exception If this method throws an exception, this bundle is marked as stopped and the * Framework will remove this bundle's listeners, unregister all services registered by this * bundle, and release all services used by this bundle. */ @Override public void start(BundleContext context) throws Exception { this.context = context; initMembers(); this.activatorLogger.info( "Starting APSActivator for bundle '" + context.getBundle().getSymbolicName() + "' with activatorMode: " + this.activatorMode); Bundle bundle = context.getBundle(); List<Class> classEntries = new LinkedList<>(); if (!this.activatorMode) { classEntries.addAll(this.managedInstances.keySet()); } collectClassEntries(bundle, classEntries, "/"); for (Class entryClass : classEntries) { OSGiServiceProvider serviceProvider = (OSGiServiceProvider) entryClass.getAnnotation(OSGiServiceProvider.class); if (serviceProvider != null && serviceProvider.threadStart()) { new StartThread(entryClass, context).start(); } else { handleServiceInstances(entryClass, context); handleFieldInjections(entryClass, context); handleServiceRegistrations(entryClass, context); handleMethods(entryClass, context); } } }
/** * Handles annotated methods. * * @param managedClass Used to lookup or create an instance of this class containing the method to * call. * @param context The bundle context. */ protected void handleMethods(Class managedClass, BundleContext context) { for (Method method : managedClass.getDeclaredMethods()) { handleStartupMethods(method, managedClass, context); handleShutdownMethods(method, managedClass, context); handleListenerMethods(method, managedClass, context); } }
public <S> ServiceRegistration<S> registerService( Class<S> clazz, S service, Dictionary<String, ?> properties) { @SuppressWarnings("unchecked") ServiceRegistration<S> registration = (ServiceRegistration<S>) registerService(clazz.getName(), service, properties); return registration; }
/** Check for permission to get a service. */ private <A> void checkAdaptPermission(Class<A> adapterType) { SecurityManager sm = System.getSecurityManager(); if (sm == null) { return; } sm.checkPermission(new AdaptPermission(adapterType.getName(), this, AdaptPermission.ADAPT)); }
/** * This method loads a class from the bundle. The class is searched for in the same manner as it * would if it was being loaded from a bundle (i.e. all hosts, fragments, import, required bundles * and local resources are searched. * * @param name the name of the desired Class. * @return the resulting Class * @exception java.lang.ClassNotFoundException if the class definition was not found. */ public final Class loadClass(String name) throws ClassNotFoundException { BundleClassLoader bcl = createClassLoader(); // The instanceof check here is just to be safe. The javadoc contract stated in // BundleClassLoader // mandate that BundleClassLoaders be an instance of ClassLoader. if (name.length() > 0 && name.charAt(0) == '[' && bcl instanceof ClassLoader) return Class.forName(name, false, (ClassLoader) bcl); return bcl.loadClass(name); }
private static ClassLoader getClassLoader(final Class clazz) { if (System.getSecurityManager() == null) return clazz.getClassLoader(); return (ClassLoader) AccessController.doPrivileged( new PrivilegedAction() { public Object run() { return clazz.getClassLoader(); } }); }
private static Class<?> mapComponentType(Class<?> componentType) { if (componentType.isPrimitive() || componentType.isArray() || Object.class.equals(componentType) || Number.class.isAssignableFrom(componentType) || Boolean.class.isAssignableFrom(componentType) || Character.class.isAssignableFrom(componentType) || String.class.isAssignableFrom(componentType) || DTO.class.isAssignableFrom(componentType)) { return componentType; } if (Map.class.isAssignableFrom(componentType)) { return Map.class; } if (List.class.isAssignableFrom(componentType)) { return List.class; } if (Set.class.isAssignableFrom(componentType)) { return Set.class; } return String.class; }
/** * This is used to start delayed service publishing. Each tracker of a required service will be * calling this method on first service becoming available. When all required services are * available the delayed service will be published. * * @param service The received service. * @param serviceReference The reference to the received service. * @throws Exception */ @Override public void onServiceAvailable(Object service, ServiceReference serviceReference) throws Exception { this.activatorLogger.info("Received service: " + service.getClass().getName()); List<Class> uniqueClasses = new LinkedList<>(); for (Tuple4<APSServiceTracker, Class, Boolean, List<ServiceRegistration>> requiredService : this.requiredServices) { if (!uniqueClasses.contains(requiredService.t2)) { uniqueClasses.add(requiredService.t2); } } for (Class managedClass : uniqueClasses) { boolean allRequiredAvailable = true; for (Tuple4<APSServiceTracker, Class, Boolean, List<ServiceRegistration>> requiredService : this.requiredServices) { if (requiredService.t2.equals(managedClass) && !requiredService.t1.hasTrackedService()) { allRequiredAvailable = false; this.activatorLogger.info( "Not all required services are available yet for: " + managedClass.getName()); break; } } if (allRequiredAvailable) { this.activatorLogger.info( "All required services are now available for: " + managedClass.getName()); for (Tuple4<APSServiceTracker, Class, Boolean, List<ServiceRegistration>> requiredService : this.requiredServices) { if (requiredService.t2.equals(managedClass) && requiredService.t3 == false) { this.activatorLogger.info("Registering services for: " + managedClass.getName()); registerServices(requiredService.t2, this.context, requiredService.t4); this.services.addAll(requiredService.t4); requiredService.t3 = true; } } } } }
/** * Tracks and injects APSServiceTracker directly or as wrapped service instance using the tracker * to call the service depending on the field type. * * @param field The field to inject. * @param managedClass Used to lookup or create an instance of this class to inject into. * @param context The bundle context. */ protected void handleServiceInjections(Field field, Class managedClass, BundleContext context) { OSGiService service = field.getAnnotation(OSGiService.class); if (service != null) { String trackerKey = field.getType().getName() + service.additionalSearchCriteria(); APSServiceTracker tracker = this.trackers.get(trackerKey); if (tracker == null) { tracker = new APSServiceTracker<>( context, field.getType(), service.additionalSearchCriteria(), service.timeout()); this.trackers.put(trackerKey, tracker); } tracker.start(); List<Object> managedInstances = getManagedInstances(managedClass); for (Object managedInstance : managedInstances) { if (field.getType().equals(APSServiceTracker.class)) { injectObject(managedInstance, tracker, field); } else { injectObject(managedInstance, tracker.getWrappedService(), field); } } if (service.required() && this.supportsRequired) { Tuple4<APSServiceTracker, Class, Boolean, List<ServiceRegistration>> requiredService = new Tuple4<>( tracker, managedClass, false, (List<ServiceRegistration>) new LinkedList<ServiceRegistration>()); this.requiredServices.add(requiredService); } this.activatorLogger.info( "Injected tracked service '" + field.getType().getName() + (service.additionalSearchCriteria().length() > 0 ? " " + service.additionalSearchCriteria() : "") + "' " + "into '" + managedClass.getName() + "." + field.getName() + "' for bundle: " + context.getBundle().getSymbolicName() + " for " + managedInstances.size() + " instance(s)!"); } }
/** * Returns a managed instance of a class. * * @param managedClass The managed class to get instance for. * @param size The number of instances. */ protected List<Object> getManagedInstances(Class managedClass, int size) { List<Object> managedInstances = this.managedInstances.get(managedClass); if (managedInstances == null) { managedInstances = new LinkedList<>(); } if (managedInstances.isEmpty()) { if (size == -1) throw new IllegalStateException("Expected instances are not available!"); try { for (int i = 0; i < size; i++) { Object managedInstance = managedClass.newInstance(); managedInstances.add(managedInstance); this.managedInstances.put(managedClass, managedInstances); this.activatorLogger.info( "Instantiated '" + managedClass.getName() + "': " + managedInstance); } } catch (InstantiationException | IllegalAccessException e) { throw new APSActivatorException("Failed to instantiate activator managed class!", e); } } return managedInstances; }
/** * Handles publishing of bundle services. If a published service has any dependencies to other * services that are marked as required then the publishing is delayed until all required services * are available. In this case the service will be unpublished if any of the required services * times out. * * @param managedClass The managed service class to instantiate and register as a service. * @param context The bundles context. * @throws Exception */ protected void handleServiceRegistrations(final Class managedClass, final BundleContext context) throws Exception { OSGiServiceProvider serviceProvider = (OSGiServiceProvider) managedClass.getAnnotation(OSGiServiceProvider.class); if (serviceProvider != null) { if (this.requiredServices.isEmpty()) { registerServices(managedClass, context, this.services); } else { for (Tuple4<APSServiceTracker, Class, Boolean, List<ServiceRegistration>> requiredService : this.requiredServices) { this.activatorLogger.info( "Registering for delayed start of '" + managedClass.getName() + "' " + "due to service '" + requiredService.t1.getServiceClass().getName() + "'!"); requiredService.t1.onActiveServiceAvailable(this); requiredService.t1.setOnTimeout(this); } } } }
public <S> Collection<ServiceReference<S>> getServiceReferences(Class<S> clazz, String filter) throws InvalidSyntaxException { @SuppressWarnings("unchecked") ServiceReference<S>[] refs = (ServiceReference<S>[]) getServiceReferences(clazz.getName(), filter); if (refs == null) { @SuppressWarnings("unchecked") Collection<ServiceReference<S>> empty = Collections.EMPTY_LIST; return empty; } List<ServiceReference<S>> result = new ArrayList<ServiceReference<S>>(refs.length); for (ServiceReference<S> b : refs) { result.add(b); } return result; }
private <T> void printAvailableAlternatives(Class<T> serviceType) { try { ServiceReference[] reference = m_framework.getBundleContext().getAllServiceReferences(serviceType.getName(), null); if (reference != null) { LOG.warn("Test Endpoints: " + reference.length); for (ServiceReference ref : reference) { LOG.warn("Endpoint: " + ref); } } } catch (Exception e) { LOG.error("Some problem during looking up alternative service. ", e); } }
/** * Handles injections of APSLogger, BundleContext, or other class types with default constructor. * * @param field The field to inject into. * @param managedClass Used to lookup or create an instance of this class to inject into. * @param context The bundle context. */ protected void handleInstanceInjections(Field field, Class managedClass, BundleContext context) { Managed managed = field.getAnnotation(Managed.class); if (managed != null) { String namedInstanceKey = managed.name() + field.getType().getName(); Object namedInstance = this.namedInstances.get(namedInstanceKey); if (namedInstance == null) { if (field.getType().equals(APSLogger.class)) { namedInstance = new APSLogger(System.out); if (managed.loggingFor().length() > 0) { ((APSLogger) namedInstance).setLoggingFor(managed.loggingFor()); } ((APSLogger) namedInstance).start(context); } else if (field.getType().equals(BundleContext.class)) { namedInstance = context; } else { namedInstance = getManagedInstance(field.getType()); } this.namedInstances.put(namedInstanceKey, namedInstance); } else { this.activatorLogger.info( "Got named instance for key '" + namedInstanceKey + "': " + namedInstance.getClass().getName()); } List<Object> managedInstances = getManagedInstances(managedClass); for (Object managedInstance : managedInstances) { injectObject(managedInstance, namedInstance, field); } this.activatorLogger.info( "Injected '" + namedInstance.getClass().getName() + "' instance for name '" + managed.name() + "' " + "into '" + managedClass.getName() + "." + field.getName() + "' for bundle: " + context.getBundle().getSymbolicName() + "!"); } }
/** * This is the first thing done to instantiate all service instances needed, so that they all can * be injected later. * * @param managedClass The manages class to create instances of. * @param context The bundles context. * @throws Exception */ protected void handleServiceInstances(Class managedClass, BundleContext context) throws Exception { OSGiServiceProvider serviceProvider = (OSGiServiceProvider) managedClass.getAnnotation(OSGiServiceProvider.class); if (serviceProvider != null) { int noInstances = 1; if (serviceProvider.instances().length > 0) { noInstances = serviceProvider.instances().length; } else if (!serviceProvider.instanceFactoryClass().equals(InstanceFactory.class)) { InstanceFactory instanceFactory = (InstanceFactory) getManagedInstance(serviceProvider.instanceFactoryClass()); if (instanceFactory == null) { instanceFactory = serviceProvider.instanceFactoryClass().newInstance(); } noInstances = instanceFactory.getPropertiesPerInstance().size(); } // This will just instantiate and cache the number of instances. Right now we don't care // about the instances themselves. getManagedInstances(managedClass, noInstances); } }
@Override public Class<?> loadClass(String name) throws ClassNotFoundException { try { equinoxContainer.checkAdminPermission(this, AdminPermission.CLASS); } catch (SecurityException e) { throw new ClassNotFoundException(name, e); } checkValid(); if (isFragment()) { throw new ClassNotFoundException( "Can not load a class from a fragment bundle: " + this); // $NON-NLS-1$ } try { ModuleClassLoader classLoader = getModuleClassLoader(true); if (classLoader != null) { if (name.length() > 0 && name.charAt(0) == '[') return Class.forName(name, false, classLoader); return classLoader.loadClass(name); } } catch (ClassNotFoundException e) { // This is an equinox-ism. Not sure it is worth it to offer an option to disable ... // On failure attempt to activate lazy activating bundles. if (State.LAZY_STARTING.equals(module.getState())) { try { module.start(StartOptions.LAZY_TRIGGER); } catch (BundleException e1) { equinoxContainer .getLogServices() .log(EquinoxContainer.NAME, FrameworkLogEntry.WARNING, e.getMessage(), e); } } throw e; } throw new ClassNotFoundException( "No class loader available for the bundle: " + this); // $NON-NLS-1$ }
protected void registerService(Class<?> clazz, Object service) { serviceRegistrations.add( getSystemBundleContext().registerService(clazz.getName(), service, null)); }
/** * Returns the operation set corresponding to the specified class or null if this operation set is * not supported by the provider implementation. * * @param opsetClass the <tt>Class</tt> of the operation set that we're looking for. * @return returns an OperationSet of the specified <tt>Class</tt> if the undelying implementation * supports it or null otherwise. */ public OperationSet getOperationSet(Class opsetClass) { return (OperationSet) getSupportedOperationSets().get(opsetClass.getName()); }
public Class<?> loadClass(String name) throws ClassNotFoundException { return Class.forName(name); }
public <S> ServiceReference<S> getServiceReference(Class<S> clazz) { @SuppressWarnings("unchecked") ServiceReference<S> reference = (ServiceReference<S>) getServiceReference(clazz.getName()); return reference; }
/** * Handles methods annotated with @APSBundleStartup. * * @param method The annotated method to call. * @param managedClass Used to lookup or create an instance of this class containing the method to * call. * @param context The bundle context. */ protected void handleStartupMethods( final Method method, final Class managedClass, final BundleContext context) { BundleStart bundleStart = method.getAnnotation(BundleStart.class); if (bundleStart != null) { if (method.getParameterTypes().length > 0) { throw new APSActivatorException( "An @BundleStart method must take no parameters! [" + managedClass.getName() + "." + method.getName() + "(?)]"); } if (bundleStart.thread()) { new Thread( new Runnable() { @Override public void run() { try { Object managedInstance = null; if (!Modifier.isStatic(method.getModifiers())) { managedInstance = getManagedInstance(managedClass); } method.invoke(managedInstance, null); APSActivator.this.activatorLogger.info( "Called bundle start method '" + managedClass.getName() + "." + method.getName() + "()' for bundle: " + context.getBundle().getSymbolicName() + "!"); } catch (IllegalAccessException iae) { APSActivator.this.activatorLogger.error( "Failed to call start method! [" + managedClass.getName() + "." + method.getName() + "()]", iae); } catch (InvocationTargetException ite) { APSActivator.this.activatorLogger.error( "Failed to call start method! [" + managedClass.getName() + "." + method.getName() + "()]", ite.getCause()); } catch (Exception e) { APSActivator.this.activatorLogger.error( "Failed to call start method! [" + managedClass.getName() + "." + method.getName() + "()]", e); } } }) .start(); } else { try { Object managedInstance = null; if (!Modifier.isStatic(method.getModifiers())) { managedInstance = getManagedInstance(managedClass); } method.invoke(managedInstance, null); this.activatorLogger.info( "Called bundle start method '" + managedClass.getName() + "." + method.getName() + "()' for bundle: " + context.getBundle().getSymbolicName() + "!"); } catch (IllegalAccessException iae) { throw new APSActivatorException( "Failed to call start method! [" + managedClass.getName() + "." + method.getName() + "()]", iae); } catch (InvocationTargetException ite) { throw new APSActivatorException( "Failed to call start method! [" + managedClass.getName() + "." + method.getName() + "()]", ite.getCause()); } } } }
/** * This handles all field injections by delegating to handlers of specific types of field * injections. * * @param managedClass The managed class to inject into. * @param context The bundles context. */ protected void handleFieldInjections(Class managedClass, BundleContext context) { for (Field field : managedClass.getDeclaredFields()) { handleServiceInjections(field, managedClass, context); handleInstanceInjections(field, managedClass, context); } }
/** * Registers/publishes services annotated with @OSGiServiceProvider. * * @param managedClass The managed class to instantiate and register as an OSGi service. * @param context The bundle context. * @param serviceRegs The list to save all service registrations to for later unregistration. * @throws Exception */ protected void registerServices( Class managedClass, BundleContext context, List<ServiceRegistration> serviceRegs) throws Exception { OSGiServiceProvider serviceProvider = (OSGiServiceProvider) managedClass.getAnnotation(OSGiServiceProvider.class); if (serviceProvider != null) { List<Tuple3<Properties, Object, List<String>>> serviceInstData = new LinkedList<>(); if (serviceProvider.properties().length > 0) { Tuple3<Properties, Object, List<String>> sd = new Tuple3<>(); sd.t1 = osgiPropertiesToProperties(serviceProvider.properties()); serviceInstData.add(sd); } else if (serviceProvider.instances().length > 0) { for (OSGiServiceInstance serviceInst : serviceProvider.instances()) { Tuple3<Properties, Object, List<String>> sd = new Tuple3<>(); sd.t1 = osgiPropertiesToProperties(serviceInst.properties()); serviceInstData.add(sd); } } else if (!serviceProvider.instanceFactoryClass().equals(InstanceFactory.class)) { InstanceFactory instanceFactory = (InstanceFactory) getManagedInstance(serviceProvider.instanceFactoryClass()); if (instanceFactory == null) { instanceFactory = serviceProvider.instanceFactoryClass().newInstance(); } for (Properties props : instanceFactory.getPropertiesPerInstance()) { Tuple3<Properties, Object, List<String>> sd = new Tuple3<>(); sd.t1 = props; serviceInstData.add(sd); } } else { Tuple3<Properties, Object, List<String>> sd = new Tuple3<>(); sd.t1 = new Properties(); serviceInstData.add(sd); } // The number of managedInstances and serviceInstData will always be the same. They both // originate // from the same information. List<Object> managedInstances = getManagedInstances(managedClass); for (int i = 0; i < serviceInstData.size(); i++) { List<String> serviceAPIs = new LinkedList<>(); if (serviceProvider.serviceAPIs().length > 0) { for (Class svcAPI : serviceProvider.serviceAPIs()) { serviceAPIs.add(svcAPI.getName()); } } else if (serviceProvider.instances().length > 0) { OSGiServiceInstance svsInstAnn = serviceProvider.instances()[i]; for (Class svcAPI : svsInstAnn.serviceAPIs()) { serviceAPIs.add(svcAPI.getName()); } } else if (!serviceProvider.instanceFactoryClass().equals(InstanceFactory.class)) { String svcAPIList = serviceInstData.get(i).t1.getProperty(InstanceFactory.SERVICE_API_CLASSES_PROPERTY); if (svcAPIList != null) { for (String svcAPI : svcAPIList.split(":")) { serviceAPIs.add(svcAPI); } } else { Class[] interfaces = managedClass.getInterfaces(); if (interfaces != null && interfaces.length > 0) { serviceAPIs.add(interfaces[0].getName()); } } } else { Class[] interfaces = managedClass.getInterfaces(); if (interfaces != null && interfaces.length > 0) { serviceAPIs.add(interfaces[0].getName()); } } Tuple3<Properties, Object, List<String>> sd = serviceInstData.get(i); sd.t3 = serviceAPIs; sd.t2 = managedInstances.get(i); } for (Tuple3<Properties, Object, List<String>> sd : serviceInstData) { sd.t1.put(Constants.SERVICE_PID, managedClass.getName()); if (!sd.t3.isEmpty()) { injectInstanceProps(sd.t2, sd.t1); for (String svcAPI : sd.t3) { ServiceRegistration serviceReg = context.registerService(svcAPI, sd.t2, sd.t1); serviceRegs.add(serviceReg); this.activatorLogger.info( "Registered '" + managedClass.getName() + "' as a service provider of '" + svcAPI + "' for bundle: " + context.getBundle().getSymbolicName() + "!"); } } else { throw new IllegalArgumentException( "The @OSGiServiceProvider annotated service of class '" + managedClass.getName() + "' does not implement a service interface!"); } } } }