/** * Finds the first service configurations by service name.<br> * If similar configurations appear more than once on the classpath, the * first is returned. Useful to override service default implementations. * * @param serviceName the service name, usually a classname * @return the service configuation entry */ @Override public synchronized Map.Entry<String,URL> findFirstServiceConfiguration(String serviceName) { Map<String,URL> services = findServiceConfigurations(serviceName); if (services.isEmpty()) { throw new TentackleRuntimeException("service '" + serviceName + "' not found"); } return services.entrySet().iterator().next(); }
/** * Finds a unique service configurations by service name.<br> * It is checked that the service is defined exactly once. * Useful for factories, singletons and alike. * * @param serviceName the service name, usually a classname * @return the service configuation entry */ @Override public synchronized Map.Entry<String,URL> findUniqueServiceConfiguration(String serviceName) { Map<String,URL> services = findServiceConfigurations(serviceName); if (services.isEmpty()) { throw new TentackleRuntimeException("service '" + serviceName + "' not found"); } if (services.size() > 1) { StringBuilder msg = new StringBuilder(); msg.append("service '").append(serviceName).append("' defined more than once: "); boolean needComma = false; for (Map.Entry<String,URL> entry: services.entrySet()) { if (needComma) { msg.append(", "); } msg.append(entry.getKey()).append(" in ").append(entry.getValue()); needComma = true; } throw new TentackleRuntimeException(msg.toString()); } return services.entrySet().iterator().next(); }
/** * Finds the service providers by service names. * * @param <T> the service type * @param service the service class * @return the classes providing this service * @throws ClassNotFoundException if some provider could not be loaded */ @SuppressWarnings("unchecked") @Override public synchronized <T> Collection<Class<T>> findServiceProviders(Class<T> service) throws ClassNotFoundException { String serviceName = service.getName(); Collection<Class<T>> serviceImplClasses = (Collection) classMap.get(serviceName); if (serviceImplClasses == null) { serviceImplClasses = new ArrayList<>(); for (Map.Entry<String,URL> entry: findServiceConfigurations(serviceName).entrySet()) { String serviceImplName = entry.getKey(); Class<T> provider = (Class<T>) Class.forName(serviceImplName, true, getClassLoader(serviceName)); // check that provides really implements service checkProvider(provider, service, entry.getValue()); serviceImplClasses.add(provider); } classMap.put(serviceName, (Collection) serviceImplClasses); } return serviceImplClasses; }