| /** |
| * Licensed 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.cdi.container.internal.container; |
| |
| import java.io.InputStream; |
| import java.lang.annotation.Annotation; |
| import java.lang.reflect.Type; |
| import java.net.URL; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Map.Entry; |
| import java.util.Optional; |
| import java.util.Set; |
| import java.util.concurrent.CopyOnWriteArrayList; |
| import java.util.concurrent.atomic.AtomicBoolean; |
| |
| import javax.enterprise.context.ApplicationScoped; |
| import javax.enterprise.context.Dependent; |
| import javax.enterprise.event.Observes; |
| import javax.enterprise.event.ObservesAsync; |
| import javax.enterprise.inject.Disposes; |
| import javax.enterprise.inject.Produces; |
| import javax.enterprise.inject.spi.Annotated; |
| import javax.enterprise.inject.spi.AnnotatedMember; |
| import javax.enterprise.inject.spi.AnnotatedMethod; |
| import javax.enterprise.inject.spi.AnnotatedParameter; |
| import javax.enterprise.inject.spi.AnnotatedType; |
| import javax.inject.Inject; |
| import javax.inject.Named; |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.xpath.XPath; |
| import javax.xml.xpath.XPathConstants; |
| import javax.xml.xpath.XPathExpression; |
| import javax.xml.xpath.XPathExpressionException; |
| import javax.xml.xpath.XPathFactory; |
| |
| import org.apache.aries.cdi.container.internal.annotated.AnnotatedTypeImpl; |
| import org.apache.aries.cdi.container.internal.model.BeansModel; |
| import org.apache.aries.cdi.container.internal.model.ComponentPropertiesModel; |
| import org.apache.aries.cdi.container.internal.model.ExtendedActivationTemplateDTO; |
| import org.apache.aries.cdi.container.internal.model.ExtendedComponentTemplateDTO; |
| import org.apache.aries.cdi.container.internal.model.ExtendedConfigurationTemplateDTO; |
| import org.apache.aries.cdi.container.internal.model.OSGiBean; |
| import org.apache.aries.cdi.container.internal.model.ReferenceModel; |
| import org.apache.aries.cdi.container.internal.model.ReferenceModel.Builder; |
| import org.apache.aries.cdi.container.internal.util.Annotates; |
| import org.apache.aries.cdi.container.internal.util.Reflection; |
| import org.osgi.service.cdi.ComponentType; |
| import org.osgi.service.cdi.ConfigurationPolicy; |
| import org.osgi.service.cdi.MaximumCardinality; |
| import org.osgi.service.cdi.ServiceScope; |
| import org.osgi.service.cdi.annotations.ComponentProperties; |
| import org.osgi.service.cdi.annotations.ComponentScoped; |
| import org.osgi.service.cdi.annotations.FactoryComponent; |
| import org.osgi.service.cdi.annotations.PID; |
| import org.osgi.service.cdi.annotations.Reference; |
| import org.osgi.service.cdi.annotations.SingleComponent; |
| import org.osgi.service.cdi.reference.BindBeanServiceObjects; |
| import org.osgi.service.cdi.reference.BindService; |
| import org.osgi.service.cdi.reference.BindServiceReference; |
| import org.osgi.service.cdi.runtime.dto.template.ComponentTemplateDTO; |
| import org.w3c.dom.Attr; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.w3c.dom.NodeList; |
| |
| import aQute.lib.exceptions.Exceptions; |
| |
| public class Discovery { |
| |
| private static final List<Type> BIND_TYPES = Arrays.asList(BindService.class, BindBeanServiceObjects.class, BindServiceReference.class); |
| |
| static final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); |
| static final XPathFactory xpf = XPathFactory.newInstance(); |
| static final XPathExpression trimExpression; |
| static final XPathExpression excludeExpression; |
| |
| static { |
| try { |
| dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); |
| dbf.setXIncludeAware(false); |
| dbf.setExpandEntityReferences(false); |
| XPath xPath = xpf.newXPath(); |
| trimExpression = xPath.compile("boolean(/beans/trim)"); |
| excludeExpression = xPath.compile("/beans/scan/exclude"); |
| } catch (Throwable t) { |
| throw Exceptions.duck(t); |
| } |
| } |
| |
| public Discovery(ContainerState containerState) { |
| _containerState = containerState; |
| _beansModel = _containerState.beansModel(); |
| _containerTemplate = _containerState.containerDTO().template.components.get(0); |
| |
| AtomicBoolean trim = new AtomicBoolean(); |
| |
| _excludes = new ArrayList<>(); |
| |
| _beansModel.getBeansXml().stream().map(this::readXMLResource).forEach(doc -> { |
| if (!trim.get()) trim.set(checkTrim(doc)); |
| _excludes.addAll(getExcludes(doc)); |
| }); |
| |
| _trim = trim.get(); |
| } |
| |
| public void discover() { |
| _beansModel.getOSGiBeans().stream().forEach(osgiBean -> { |
| osgiBean.found(true); |
| |
| AnnotatedType<?> annotatedType = new AnnotatedTypeImpl<>(osgiBean.getBeanClass()); |
| |
| if (trimIt(annotatedType) || exclude(annotatedType)) { |
| return; |
| } |
| |
| try { |
| String beanName = Annotates.beanName(annotatedType); |
| Class<? extends Annotation> beanScope = Annotates.beanScope(annotatedType); |
| Map<String, Object> componentProperties = Annotates.componentProperties(annotatedType); |
| ServiceScope serviceScope = Annotates.serviceScope(annotatedType); |
| List<String> serviceTypes = Annotates.serviceClassNames(annotatedType); |
| |
| if (annotatedType.isAnnotationPresent(SingleComponent.class)) { |
| doFactoryOrSingleComponent(osgiBean, osgiBean.getBeanClass(), annotatedType, beanName, serviceTypes, serviceScope, componentProperties, ComponentType.SINGLE); |
| } |
| else if (annotatedType.isAnnotationPresent(FactoryComponent.class)) { |
| doFactoryOrSingleComponent(osgiBean, osgiBean.getBeanClass(), annotatedType, beanName, serviceTypes, serviceScope, componentProperties, ComponentType.FACTORY); |
| } |
| else if (annotatedType.isAnnotationPresent(ComponentScoped.class)) { |
| _componentScoped.add(osgiBean); |
| } |
| else { |
| discoverActivations(osgiBean, osgiBean.getBeanClass(), annotatedType, null, beanScope, serviceTypes, serviceScope, componentProperties); |
| } |
| } |
| catch (Exception e) { |
| _containerState.error(e); |
| |
| return; |
| } |
| |
| annotatedType.getConstructors().stream().filter(this::isInject).flatMap(annotatedConstructor -> annotatedConstructor.getParameters().stream()).forEach( |
| annotatedParameter -> |
| processAnnotated(annotatedParameter, annotatedParameter.getBaseType(), Annotates.qualifiers(annotatedParameter), osgiBean) |
| ); |
| |
| annotatedType.getFields().stream().filter(this::isInject).forEach( |
| annotatedField -> |
| processAnnotated(annotatedField, annotatedField.getBaseType(), Annotates.qualifiers(annotatedField), osgiBean) |
| ); |
| |
| annotatedType.getFields().stream().filter(this::isProduces).forEach( |
| annotatedField -> { |
| Class<? extends Annotation> beanScope = Annotates.beanScope(annotatedField); |
| Map<String, Object> componentProperties = Annotates.componentProperties(annotatedField); |
| ServiceScope serviceScope = Annotates.serviceScope(annotatedField); |
| List<String> serviceTypes = Annotates.serviceClassNames(annotatedField); |
| |
| discoverActivations(osgiBean, osgiBean.getBeanClass(), annotatedField, annotatedField, beanScope, serviceTypes, serviceScope, componentProperties); |
| } |
| ); |
| |
| annotatedType.getMethods().stream().forEach(annotatedMethod -> { |
| if (isInjectOrProduces(annotatedMethod)) { |
| annotatedMethod.getParameters().stream().forEach( |
| annotatedParameter -> processAnnotated(annotatedParameter, annotatedParameter.getBaseType(), Annotates.qualifiers(annotatedParameter), osgiBean) |
| ); |
| |
| if (isProduces(annotatedMethod)) { |
| Class<? extends Annotation> beanScope = Annotates.beanScope(annotatedMethod); |
| Map<String, Object> componentProperties = Annotates.componentProperties(annotatedMethod); |
| ServiceScope serviceScope = Annotates.serviceScope(annotatedMethod); |
| List<String> serviceTypes = Annotates.serviceClassNames(annotatedMethod); |
| |
| discoverActivations(osgiBean, osgiBean.getBeanClass(), annotatedMethod, annotatedMethod, beanScope, serviceTypes, serviceScope, componentProperties); |
| } |
| } |
| else if (isDisposeOrObserves(annotatedMethod)) { |
| annotatedMethod.getParameters().subList(1, annotatedMethod.getParameters().size()).stream().forEach( |
| annotatedParameter -> processAnnotated(annotatedParameter, annotatedParameter.getBaseType(), Annotates.qualifiers(annotatedParameter), osgiBean) |
| ); |
| } |
| }); |
| }); |
| |
| postProcessComponentScopedBeans(); |
| } |
| |
| boolean exclude(AnnotatedType<?> annotatedType) { |
| // See https://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#exclude_filters |
| return _excludes.stream().anyMatch(ex -> ex.exclude(annotatedType)); |
| } |
| |
| boolean trimIt(AnnotatedType<?> annotatedType) { |
| // See https://docs.jboss.org/cdi/spec/2.0/cdi-spec.html#trimmed_bean_archive |
| if (!_trim) return false; |
| |
| if (Annotates.hasBeanDefiningAnnotations(annotatedType)) return false; |
| |
| // or any scope annotation |
| if (Annotates.beanScope(annotatedType, null) != null) return false; |
| |
| return true; |
| } |
| |
| <X> boolean isInject(AnnotatedMember<X> annotatedMember) { |
| return (annotatedMember.isAnnotationPresent(Inject.class) && !annotatedMember.isStatic()); |
| } |
| |
| <X> boolean isInjectOrProduces(AnnotatedMember<X> annotatedMember) { |
| return (annotatedMember.isAnnotationPresent(Inject.class) && !annotatedMember.isStatic()) || |
| annotatedMember.isAnnotationPresent(Produces.class); |
| } |
| |
| <X> boolean isProduces(AnnotatedMember<X> annotatedMember) { |
| return annotatedMember.isAnnotationPresent(Produces.class); |
| } |
| |
| <X> boolean isDisposeOrObserves(AnnotatedMethod<X> annotatedMethod) { |
| return !annotatedMethod.getParameters().isEmpty() && (annotatedMethod.getParameters().get(0).isAnnotationPresent(Disposes.class) || |
| annotatedMethod.getParameters().get(0).isAnnotationPresent(Observes.class) || |
| annotatedMethod.getParameters().get(0).isAnnotationPresent(ObservesAsync.class)); |
| } |
| |
| <X> void processAnnotated(Annotated annotated, Type injectionPointType, Set<Annotation> qualifiers, OSGiBean osgiBean) { |
| if (BIND_TYPES.contains(Reflection.getRawType(annotated.getBaseType()))) { |
| Builder builder = new ReferenceModel.Builder(annotated); |
| |
| try { |
| ReferenceModel referenceModel = builder.type(injectionPointType).build(); |
| |
| osgiBean.addReference(referenceModel.toDTO()); |
| } |
| catch (Exception e) { |
| _containerState.error(e); |
| } |
| } |
| else { |
| Reference reference = annotated.getAnnotation(Reference.class); |
| ComponentProperties componentProperties = annotated.getAnnotation(ComponentProperties.class); |
| |
| if (reference != null) { |
| doReference(osgiBean, annotated, injectionPointType, reference, componentProperties); |
| } |
| else if (componentProperties != null) { |
| doComponentProperties(osgiBean, injectionPointType, qualifiers); |
| } |
| } |
| } |
| |
| void postProcessComponentScopedBeans() { |
| _containerState.containerDTO().template.components.stream().filter( |
| template -> template.type != ComponentType.CONTAINER |
| ).map( |
| template -> (ExtendedComponentTemplateDTO)template |
| ).forEach( |
| template -> { |
| |
| _componentScoped.forEach( |
| osgiBean -> { |
| if (osgiBean.getComponent() == null) { |
| osgiBean.setComponent(_containerState, template); |
| } |
| |
| String className = osgiBean.getBeanClass().getName(); |
| if (!template.beans.contains(className)) { |
| template.beans.add(className); |
| } |
| } |
| ); |
| } |
| ); |
| } |
| |
| void doComponentProperties(OSGiBean osgiBean, Type injectionPointType, Set<Annotation> qualifiers) { |
| try { |
| ComponentPropertiesModel configurationModel = new ComponentPropertiesModel.Builder( |
| injectionPointType |
| ).declaringClass( |
| osgiBean.getBeanClass() |
| ).qualifiers( |
| qualifiers |
| ).build(); |
| |
| osgiBean.addConfiguration(_containerState, configurationModel.toDTO()); |
| } |
| catch (Exception e) { |
| _containerState.error(e); |
| } |
| } |
| |
| void discoverActivations(OSGiBean osgiBean, Class<?> declaringClass, Annotated annotated, AnnotatedMember<?> producer, Class<? extends Annotation> scope, List<String> serviceTypeNames, ServiceScope serviceScope, Map<String, Object> componentProperties) { |
| String className = declaringClass.getName(); |
| |
| if (!_containerTemplate.beans.contains(className)) { |
| _containerTemplate.beans.add(className); |
| } |
| |
| if (!serviceTypeNames.isEmpty()) { |
| if (!scope.equals(ApplicationScoped.class) && |
| !scope.equals(Dependent.class)) { |
| |
| _containerState.error( |
| new IllegalStateException( |
| String.format( |
| "@Service can only be used on @ApplicationScoped, @Dependent, @SingleComponent, and @FactoryComponent: %s", |
| osgiBean.getBeanClass()))); |
| |
| return; |
| } |
| |
| ExtendedActivationTemplateDTO activationTemplate = new ExtendedActivationTemplateDTO(); |
| activationTemplate.cdiScope = scope; |
| activationTemplate.declaringClass = declaringClass; |
| activationTemplate.producer = producer; |
| activationTemplate.properties = componentProperties; |
| activationTemplate.scope = serviceScope; |
| activationTemplate.serviceClasses = serviceTypeNames; |
| |
| _containerTemplate.activations.add(activationTemplate); |
| } |
| |
| osgiBean.setComponent(_containerState, _containerTemplate); |
| } |
| |
| void doFactoryOrSingleComponent( |
| OSGiBean osgiBean, Class<?> declaringClass, Annotated annotated, String beanName, |
| List<String> serviceTypes, ServiceScope serviceScope, |
| Map<String, Object> componentProperties, ComponentType componentType) { |
| |
| Set<Annotation> qualifiers = Annotates.qualifiers(annotated); |
| qualifiers.removeIf(Named.class::isInstance); |
| |
| ExtendedComponentTemplateDTO componentTemplate = new ExtendedComponentTemplateDTO(); |
| componentTemplate.activations = new CopyOnWriteArrayList<>(); |
| |
| ExtendedActivationTemplateDTO activationTemplate = new ExtendedActivationTemplateDTO(); |
| activationTemplate.declaringClass = declaringClass; |
| activationTemplate.properties = Collections.emptyMap(); |
| activationTemplate.scope = serviceScope; |
| activationTemplate.serviceClasses = serviceTypes; |
| |
| componentTemplate.activations.add(activationTemplate); |
| |
| componentTemplate.beanClass = declaringClass; |
| componentTemplate.qualifiers = qualifiers; |
| componentTemplate.beans = new CopyOnWriteArrayList<>(); |
| componentTemplate.configurations = new CopyOnWriteArrayList<>(); |
| componentTemplate.name = beanName; |
| componentTemplate.properties = componentProperties; |
| componentTemplate.references = new CopyOnWriteArrayList<>(); |
| componentTemplate.type = componentType; |
| |
| annotated.getAnnotations(PID.class).stream().forEach( |
| PID -> { |
| String pid = PID.value(); |
| |
| ExtendedConfigurationTemplateDTO configurationTemplate = new ExtendedConfigurationTemplateDTO(); |
| |
| configurationTemplate.declaringClass = declaringClass; |
| configurationTemplate.maximumCardinality = MaximumCardinality.ONE; |
| configurationTemplate.pid = Optional.of(pid).map( |
| s -> (s.equals("$") || s.equals("")) ? componentTemplate.name : s |
| ).orElse(componentTemplate.name); |
| |
| if (componentType == ComponentType.SINGLE) { |
| configurationTemplate.pid = (pid.equals("$") || pid.equals("")) ? componentTemplate.name : pid; |
| } |
| |
| configurationTemplate.policy = PID.policy(); |
| |
| componentTemplate.configurations.add(configurationTemplate); |
| } |
| ); |
| |
| if (componentType == ComponentType.SINGLE) { |
| if (componentTemplate.configurations.isEmpty()) { |
| ExtendedConfigurationTemplateDTO configurationTemplate = new ExtendedConfigurationTemplateDTO(); |
| |
| configurationTemplate.declaringClass = declaringClass; |
| configurationTemplate.maximumCardinality = MaximumCardinality.ONE; |
| configurationTemplate.pid = componentTemplate.name; |
| configurationTemplate.policy = ConfigurationPolicy.OPTIONAL; |
| |
| componentTemplate.configurations.add(configurationTemplate); |
| } |
| } |
| else { |
| ExtendedConfigurationTemplateDTO configurationTemplate = new ExtendedConfigurationTemplateDTO(); |
| |
| configurationTemplate.declaringClass = declaringClass; |
| configurationTemplate.maximumCardinality = MaximumCardinality.MANY; |
| configurationTemplate.pid = Optional.ofNullable( |
| annotated.getAnnotation(FactoryComponent.class) |
| ).map(FactoryComponent::value).map( |
| v -> (v.equals("$") || v.equals("")) ? componentTemplate.name : v |
| ).orElse(componentTemplate.name); |
| configurationTemplate.policy = ConfigurationPolicy.REQUIRED; |
| |
| componentTemplate.configurations.add(configurationTemplate); |
| } |
| |
| componentTemplate.beans.add(declaringClass.getName()); |
| |
| _containerState.containerDTO().template.components.add(componentTemplate); |
| |
| osgiBean.setComponent(_containerState, componentTemplate); |
| } |
| |
| void doReference(OSGiBean osgiBean, Annotated annotated, Type injectionPointType, Reference reference, ComponentProperties componentProperties) { |
| if (componentProperties != null) { |
| _containerState.error( |
| new IllegalArgumentException( |
| String.format( |
| "Cannot use @Reference and @Configuration on the same injection point {}", |
| injectionPointType)) |
| ); |
| |
| return; |
| } |
| |
| Builder builder = null; |
| |
| if (annotated instanceof AnnotatedParameter) { |
| builder = new ReferenceModel.Builder(annotated); |
| } |
| else { |
| builder = new ReferenceModel.Builder(annotated); |
| } |
| |
| try { |
| ReferenceModel referenceModel = builder.type(injectionPointType).build(); |
| |
| osgiBean.addReference(referenceModel.toDTO()); |
| } |
| catch (Exception e) { |
| _containerState.error(e); |
| } |
| } |
| |
| boolean checkTrim(Document document) { |
| try { |
| return Boolean.class.cast(trimExpression.evaluate(document, XPathConstants.BOOLEAN)); |
| } catch (XPathExpressionException e) { |
| throw Exceptions.duck(e); |
| } |
| } |
| |
| List<Exclude> getExcludes(Document document) { |
| try { |
| List<Exclude> excludes = new ArrayList<>(); |
| |
| NodeList excludeNodes = NodeList.class.cast(excludeExpression.evaluate(document, XPathConstants.NODESET)); |
| |
| for (int i = 0; i < excludeNodes.getLength(); i++) { |
| Element excludeElement = (Element)excludeNodes.item(i); |
| |
| excludes.add(new Exclude(excludeElement)); |
| } |
| |
| return excludes; |
| } |
| catch (Exception e) { |
| throw Exceptions.duck(e); |
| } |
| } |
| |
| Document readXMLResource(URL resource) { |
| try { |
| DocumentBuilder db = dbf.newDocumentBuilder(); |
| try (InputStream is = resource.openStream()) { |
| return db.parse(is); |
| } catch (Throwable t) { |
| return db.newDocument(); |
| } |
| } |
| catch (Exception e) { |
| throw Exceptions.duck(e); |
| } |
| } |
| |
| private final BeansModel _beansModel; |
| private final Set<OSGiBean> _componentScoped = new HashSet<>(); |
| private final ComponentTemplateDTO _containerTemplate; |
| private final ContainerState _containerState; |
| private final boolean _trim; |
| private final List<Exclude> _excludes; |
| |
| enum Match { |
| CLASSNAME, PACKAGE_NAME, PACKAGE_PREFIX |
| } |
| |
| class Exclude { |
| |
| private final String name; |
| private final Match match; |
| private final List<String> ifClassAvailableS = new ArrayList<>(); |
| private final List<String> ifClassesNotAvailableS = new ArrayList<>(); |
| private final Map<String, String> ifSystemPropertyS = new HashMap<>(); |
| |
| public Exclude(Element excludeElement) { |
| String glob = excludeElement.getAttribute("name"); |
| |
| if (glob.endsWith(".**")) { |
| match = Match.PACKAGE_PREFIX; |
| name = glob.substring(0, glob.length() - 3); |
| } |
| else if (glob.endsWith(".*")) { |
| match = Match.PACKAGE_NAME; |
| name = glob.substring(0, glob.length() - 2); |
| } |
| else { |
| match = Match.CLASSNAME; |
| name = glob; |
| } |
| |
| NodeList ifClassAvailableNodes = excludeElement.getElementsByTagName("if-class-available"); |
| |
| for (int iCAIdx = 0; iCAIdx < ifClassAvailableNodes.getLength(); iCAIdx++) { |
| Element ifClassAvailableElement = (Element)ifClassAvailableNodes.item(iCAIdx); |
| |
| Attr nameAttribute = ifClassAvailableElement.getAttributeNode("name"); |
| |
| ifClassAvailableS.add(nameAttribute.getValue()); |
| } |
| |
| NodeList ifClassNotAvailableNodes = excludeElement.getElementsByTagName("if-class-not-available"); |
| |
| for (int iCNAIdx = 0; iCNAIdx < ifClassNotAvailableNodes.getLength(); iCNAIdx++) { |
| Element ifClassNotAvailableElement = (Element)ifClassNotAvailableNodes.item(iCNAIdx); |
| |
| Attr nameAttribute = ifClassNotAvailableElement.getAttributeNode("name"); |
| |
| ifClassesNotAvailableS.add(nameAttribute.getValue()); |
| } |
| |
| NodeList ifSystemPropertyNodes = excludeElement.getElementsByTagName("if-system-property"); |
| |
| for (int iCNAIdx = 0; iCNAIdx < ifSystemPropertyNodes.getLength(); iCNAIdx++) { |
| Element ifSystemPropertyElement = (Element)ifSystemPropertyNodes.item(iCNAIdx); |
| |
| String value = ""; |
| |
| if (ifSystemPropertyElement.hasAttribute("value")) { |
| value = ifSystemPropertyElement.getAttributeNode("value").getValue(); |
| } |
| |
| Attr nameAttribute = ifSystemPropertyElement.getAttributeNode("name"); |
| |
| ifSystemPropertyS.put(nameAttribute.getValue(), value); |
| } |
| } |
| |
| public boolean exclude(AnnotatedType<?> annotatedType) { |
| String className = annotatedType.getJavaClass().getName(); |
| String packageName = annotatedType.getJavaClass().getPackage().getName(); |
| |
| boolean matches = false; |
| switch (match) { |
| case CLASSNAME: { |
| matches = className.equals(name); |
| break; |
| } |
| case PACKAGE_NAME: { |
| matches = packageName.equals(name); |
| break; |
| } |
| case PACKAGE_PREFIX: { |
| matches = packageName.startsWith(name); |
| } |
| } |
| |
| if (matches && |
| ifClassAvailableS.stream().allMatch(this::classIsAvailable) && |
| ifClassesNotAvailableS.stream().allMatch(this::classIsNotAvailable) && |
| ifSystemPropertyS.entrySet().stream().allMatch(this::isPropertySet)) { |
| |
| return true; |
| } |
| |
| return false; |
| } |
| |
| boolean classIsNotAvailable(String className) { |
| return !classIsAvailable(className); |
| } |
| |
| boolean classIsAvailable(String className) { |
| try { |
| Class.forName(className, false, _containerState.classLoader()); |
| return true; |
| } |
| catch (ClassNotFoundException cnfe) { |
| return false; |
| } |
| } |
| |
| boolean isPropertySet(Entry<String, String> entry) { |
| if (entry.getValue().isEmpty()) { |
| return _containerState.bundleContext().getProperty(entry.getKey()) != null; |
| } |
| else { |
| return entry.getValue().equals(_containerState.bundleContext().getProperty(entry.getKey())); |
| } |
| } |
| |
| @Override |
| public String toString() { |
| return name + ":" + match; |
| } |
| |
| } |
| |
| } |