1. Project Clover database Sat Feb 2 2019 06:45:20 CET
  2. Package org.xwiki.component.annotation

File ComponentDescriptorFactory.java

 

Coverage histogram

../../../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

14
40
5
1
187
91
14
0.35
8
5
2.8

Classes

Class Line # Actions
ComponentDescriptorFactory 44 40 0% 14 0
1.0100%
 

Contributing tests

This file is covered by 35 tests. .

Source view

1    /*
2    * See the NOTICE file distributed with this work for additional
3    * information regarding copyright ownership.
4    *
5    * This is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU Lesser General Public License as
7    * published by the Free Software Foundation; either version 2.1 of
8    * the License, or (at your option) any later version.
9    *
10    * This software is distributed in the hope that it will be useful,
11    * but WITHOUT ANY WARRANTY; without even the implied warranty of
12    * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13    * Lesser General Public License for more details.
14    *
15    * You should have received a copy of the GNU Lesser General Public
16    * License along with this software; if not, write to the Free
17    * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18    * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19    */
20    package org.xwiki.component.annotation;
21   
22    import java.lang.reflect.Field;
23    import java.lang.reflect.Type;
24    import java.util.ArrayList;
25    import java.util.List;
26    import java.util.ServiceLoader;
27   
28    import javax.inject.Named;
29    import javax.inject.Singleton;
30   
31    import org.xwiki.component.descriptor.ComponentDependency;
32    import org.xwiki.component.descriptor.ComponentDescriptor;
33    import org.xwiki.component.descriptor.ComponentInstantiationStrategy;
34    import org.xwiki.component.descriptor.DefaultComponentDescriptor;
35    import org.xwiki.component.util.ReflectionUtils;
36   
37    /**
38    * Constructs a Component Descriptor out of a class definition that contains Annotations.
39    *
40    * @version $Id: eab43bcd88b99d0b6eeed7fae730bd071f5028a0 $
41    * @since 1.8.1
42    * @see ComponentAnnotationLoader
43    */
 
44    public class ComponentDescriptorFactory
45    {
46    /**
47    * Load all Component Descriptor Factories implementations using the JDK's Service Loader facility. Note that we
48    * cannot use Components to do this since it would be a chicken and egg issue since this factory class is used to
49    * initialize Components...
50    */
51    private ServiceLoader<ComponentDependencyFactory> componentDependencyFactories = ServiceLoader
52    .load(ComponentDependencyFactory.class);
53   
54    /**
55    * Create component descriptors for the passed component implementation class and component role class. There can be
56    * more than one descriptor if the component class has specified several hints.
57    *
58    * @param componentClass the component implementation class
59    * @param componentRoleClass the component role class
60    * @return the component descriptors with resolved component dependencies
61    * @deprecated since 4.0M1 use {@link #createComponentDescriptors(Class, Type)} instead
62    */
 
63  5 toggle @Deprecated
64    public List<ComponentDescriptor> createComponentDescriptors(Class<?> componentClass,
65    Class<?> componentRoleClass)
66    {
67  5 return createComponentDescriptors(componentClass, (Type) componentRoleClass);
68    }
69   
70    /**
71    * Create component descriptors for the passed component implementation class and component role class. There can be
72    * more than one descriptor if the component class has specified several hints.
73    *
74    * @param componentClass the component implementation class
75    * @param componentRoleType the component role type
76    * @return the component descriptors with resolved component dependencies
77    * @since 4.0M1
78    */
 
79  818125 toggle public List<ComponentDescriptor> createComponentDescriptors(Class<?> componentClass, Type componentRoleType)
80    {
81  818125 List<ComponentDescriptor> descriptors = new ArrayList<ComponentDescriptor>();
82   
83    // If there's a @Named annotation, use it and ignore hints specified in the @Component annotation.
84  818125 String[] hints;
85  818125 Named named = componentClass.getAnnotation(Named.class);
86  818125 if (named != null) {
87  476264 hints = new String[] {named.value()};
88    } else {
89    // If the Component annotation has several hints specified ignore the default hint value and for each
90    // specified hint create a Component Descriptor
91  341861 Component component = componentClass.getAnnotation(Component.class);
92  341861 if (component != null && component.hints().length > 0) {
93  12535 hints = component.hints();
94    } else {
95  329326 if (component != null && component.value().trim().length() > 0) {
96  14 hints = new String[] {component.value().trim()};
97    } else {
98  329312 hints = new String[] {"default"};
99    }
100    }
101    }
102   
103    // Create the descriptors
104  818125 for (String hint : hints) {
105  835777 descriptors.add(createComponentDescriptor(componentClass, hint, componentRoleType));
106    }
107   
108  818125 return descriptors;
109    }
110   
111    /**
112    * Create a component descriptor for the passed component implementation class, hint and component role class.
113    *
114    * @param componentClass the component implementation class
115    * @param hint the hint
116    * @param componentRoleType the component role type
117    * @return the component descriptor with resolved component dependencies
118    */
 
119  835777 toggle private ComponentDescriptor createComponentDescriptor(Class<?> componentClass, String hint,
120    Type componentRoleType)
121    {
122  835777 DefaultComponentDescriptor descriptor = new DefaultComponentDescriptor();
123  835777 descriptor.setRoleType(componentRoleType);
124  835777 descriptor.setImplementation(componentClass);
125  835777 descriptor.setRoleHint(hint);
126  835777 descriptor.setInstantiationStrategy(createComponentInstantiationStrategy(componentClass));
127   
128    // Set the injected fields.
129    // Note: that we need to find all fields since we can have some inherited fields which are annotated in a
130    // superclass. Since Java doesn't offer a method to return all fields we have to traverse all parent classes
131    // looking for declared fields.
132  835777 for (Field field : ReflectionUtils.getAllFields(componentClass)) {
133  4806669 ComponentDependency dependency = createComponentDependency(field);
134  4806669 if (dependency != null) {
135  1814580 descriptor.addComponentDependency(dependency);
136    }
137    }
138   
139  835777 return descriptor;
140    }
141   
142    /**
143    * @param componentClass the component class from which to extract the component instantiation strategy
144    * @return the component instantiation strategy to use
145    */
 
146  835777 toggle private ComponentInstantiationStrategy createComponentInstantiationStrategy(Class<?> componentClass)
147    {
148  835777 ComponentInstantiationStrategy strategy;
149   
150    // Support both InstantiationStrategy and JSR 330's Singleton annotations.
151  835777 Singleton singleton = componentClass.getAnnotation(Singleton.class);
152  835777 if (singleton != null) {
153  733068 strategy = ComponentInstantiationStrategy.SINGLETON;
154    } else {
155  102709 InstantiationStrategy instantiationStrategy = componentClass.getAnnotation(InstantiationStrategy.class);
156  102709 if (instantiationStrategy != null) {
157  95864 strategy = instantiationStrategy.value();
158    } else {
159    // TODO: In order to be JSR330 compliant we need to change this behavior and consider components are
160    // per lookup when no annotation is specified. Before we can do this we need to modify the full xwiki
161    // code base and possibly introduce a configuration option. To be discussed.
162  6845 strategy = ComponentInstantiationStrategy.SINGLETON;
163    }
164    }
165   
166  835777 return strategy;
167    }
168   
169    /**
170    * @param field the field for which to extract a Component Dependency
171    * @return the Component Dependency instance created from the passed field
172    */
 
173  4806669 toggle private ComponentDependency createComponentDependency(Field field)
174    {
175  4806669 ComponentDependency dependency = null;
176   
177    // Try each factory till one returns a non null result
178  4806669 for (ComponentDependencyFactory factory : this.componentDependencyFactories) {
179  4806669 dependency = factory.createComponentDependency(field);
180  4806669 if (dependency != null) {
181  1814580 break;
182    }
183    }
184   
185  4806669 return dependency;
186    }
187    }