blob: 3fe3e4d0282f1a5100db231c48a1ce36cf490057 [file] [log] [blame]
Richard S. Halle449eca2006-09-28 20:00:47 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
Richard S. Hall0c111822006-09-17 19:43:50 +00009 *
Richard S. Halle449eca2006-09-28 20:00:47 +000010 * http://www.apache.org/licenses/LICENSE-2.0
Richard S. Hall0c111822006-09-17 19:43:50 +000011 *
Richard S. Halle449eca2006-09-28 20:00:47 +000012 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
Richard S. Hall0c111822006-09-17 19:43:50 +000018 */
19package org.apache.felix.scr;
20
Felix Meschbergeree3f1db2007-08-22 15:21:27 +000021import java.util.ArrayList;
22import java.util.Dictionary;
23import java.util.Hashtable;
24import java.util.Iterator;
25import java.util.List;
Richard S. Hall0c111822006-09-17 19:43:50 +000026
27import org.osgi.service.component.ComponentException;
Humberto Cervantes Macedaa3664ba2006-04-21 16:34:36 +000028
29/**
Richard S. Hall0c111822006-09-17 19:43:50 +000030 * This class holds the information associated to a component in the descriptor * */
31public class ComponentMetadata {
32 // 112.4.3: A Globally unique component name (required)
33 private String m_name;
34
35 // 112.4.3: Controls whether the component is enabled when the bundle is started. (optional, default is true).
36 private boolean m_enabled = true;
37
38 // 112.4.3: Factory identified. If set to a non empty string, it indicates that the component is a factory component (optional).
39 private String m_factory = null;
40
41 // 112.4.3: Controls whether component configurations must be immediately activated after becoming
Felix Meschberger65cce822007-08-14 11:33:05 +000042 // satisfied or whether activation should be delayed. (optional, default value depends
43 // on whether the component has a service element or not).
44 private Boolean m_immediate = null;
Richard S. Hall0c111822006-09-17 19:43:50 +000045
46 // 112.4.4 Implementation Element (required)
47 private String m_implementationClassName = null;
48
49 // Associated properties (0..*)
50 private Dictionary m_properties = new Hashtable();
51
52 // List of Property metadata - used while building the meta data
53 // while validating the properties contained in the PropertyMetadata
54 // instances are copied to the m_properties Dictionary while this
55 // list will be cleared
56 private List m_propertyMetaData = new ArrayList();
57
58 // Provided services (0..1)
59 private ServiceMetadata m_service = null;
60
61 // List of service references, (required services 0..*)
62 private List m_references = new ArrayList();
63
64 // Flag that is set once the component is verified (its properties cannot be changed)
65 private boolean m_validated = false;
66
67
68 /////////////////////////////////////////// SETTERS //////////////////////////////////////
69
70 /**
71 * Setter for the name
72 *
73 * @param name
74 */
75 public void setName(String name) {
76 if(m_validated) {
77 return;
78 }
79 m_name = name;
80 }
81
82 /**
83 * Setter for the enabled property
84 *
85 * @param enabled
86 */
87 public void setEnabled(boolean enabled) {
88 if(m_validated) {
89 return;
90 }
91 m_enabled = enabled;
92 }
93
94 /**
95 *
96 * @param factoryIdentifier
97 */
98 public void setFactoryIdentifier(String factoryIdentifier) {
99 if(m_validated) {
100 return;
101 }
102 m_factory = factoryIdentifier;
103 }
104
105 /**
106 * Setter for the immediate property
107 *
108 * @param immediate
109 */
110 public void setImmediate(boolean immediate) {
111 if(m_validated) {
112 return;
113 }
Felix Meschberger65cce822007-08-14 11:33:05 +0000114 m_immediate = immediate ? Boolean.TRUE : Boolean.FALSE;
Richard S. Hall0c111822006-09-17 19:43:50 +0000115 }
116
117 /**
118 * Sets the name of the implementation class
119 *
120 * @param implementationClassName a class name
121 */
122 public void setImplementationClassName(String implementationClassName) {
123 if(m_validated) {
124 return;
125 }
126 m_implementationClassName = implementationClassName;
127 }
128
129 /**
130 * Used to add a property to the instance
131 *
132 * @param newProperty a property metadata object
133 */
134 public void addProperty(PropertyMetadata newProperty) {
135 if(m_validated) {
136 return;
137 }
138 if(newProperty == null) {
139 throw new IllegalArgumentException ("Cannot add a null property");
140 }
141 m_propertyMetaData.add(newProperty);
142 }
143
144 /**
145 * Used to set a ServiceMetadata object.
146 *
147 * @param service a ServiceMetadata
148 */
149 public void setService(ServiceMetadata service) {
150 if(m_validated) {
151 return;
152 }
153 m_service = service;
154 }
155
156 /**
157 * Used to add a reference metadata to the component
158 *
159 * @param newReference a new ReferenceMetadata to be added
160 */
161 public void addDependency(ReferenceMetadata newReference) {
162 if(newReference == null) {
163 throw new IllegalArgumentException ("Cannot add a null ReferenceMetadata");
164 }
165 m_references.add(newReference);
166 }
167
168
169 /////////////////////////////////////////// GETTERS //////////////////////////////////////
170
171 /**
172 * Returns the name of the component
173 *
174 * @return A string containing the name of the component
175 */
176 public String getName() {
177 return m_name;
178 }
179
180 /**
181 * Returns the value of the enabled flag
182 *
183 * @return a boolean containing the value of the enabled flag
184 */
185 public boolean isEnabled() {
186 return m_enabled;
187 }
188
189 /**
190 * Returns the factory identifier
191 *
192 * @return A string containing a factory identifier or null
193 */
194 public String getFactoryIdentifier() {
195 return m_factory;
196 }
197
198 /**
Felix Meschberger65cce822007-08-14 11:33:05 +0000199 * Returns the flag that defines the activation policy for the component.
200 * <p>
201 * This method may only be trusted after this instance has been validated
202 * by the {@link #validate()} call. Else it will either return the value
203 * of an explicitly set "immediate" attribute or return false if a service
204 * element is set or true otherwise. This latter default value deduction
205 * may be unsafe while the descriptor has not been completely read.
206 *
Richard S. Hall0c111822006-09-17 19:43:50 +0000207 *
208 * @return a boolean that defines the activation policy
209 */
210 public boolean isImmediate() {
Felix Meschberger65cce822007-08-14 11:33:05 +0000211 // return explicit value if known
212 if ( m_immediate != null ) {
213 return m_immediate.booleanValue();
214 }
215
216 // deduce default value from service element presence
217 return m_service == null;
Richard S. Hall0c111822006-09-17 19:43:50 +0000218 }
219
220 /**
221 * Returns the name of the implementation class
222 *
223 * @return the name of the implementation class
224 */
225 public String getImplementationClassName() {
226 return m_implementationClassName;
227 }
228
229 /**
230 * Returns the associated ServiceMetadata
231 *
232 * @return a ServiceMetadata object or null if the Component does not provide any service
233 */
234 public ServiceMetadata getServiceMetadata() {
235 return m_service;
236 }
237
238 /**
239 * Returns the properties.
240 *
241 * @return the properties as a Dictionary
242 */
243 public Dictionary getProperties() {
244 return m_properties;
245 }
246
247 /**
248 * Returns the dependency descriptors
249 *
250 * @return a Collection of dependency descriptors
251 */
252 public List getDependencies() {
253 return m_references;
254 }
255
256 /**
257 * Test to see if this service is a factory
258 *
259 * @return true if it is a factory, false otherwise
260 */
261 public boolean isFactory() {
262 return m_factory != null;
263 }
264
265 /**
266 * Method used to verify if the semantics of this metadata are correct
267 */
268 void validate() {
269
270 // First check if the properties are valid (and extract property values)
271 Iterator propertyIterator = m_propertyMetaData.iterator();
272 while ( propertyIterator.hasNext() ) {
273 PropertyMetadata propMeta = (PropertyMetadata) propertyIterator.next();
274 propMeta.validate();
275 m_properties.put(propMeta.getName(), propMeta.getValue());
276 }
277 m_propertyMetaData.clear();
278
279 // Check that the provided services are valid too
280 if(m_service != null) {
281 m_service.validate();
282 }
283
284 // Check that the references are ok
285 Iterator referenceIterator = m_references.iterator();
286 while ( referenceIterator.hasNext() ) {
287 ((ReferenceMetadata)referenceIterator.next()).validate();
288 }
289
290 // 112.10 The name of the component is required
291 if( m_name == null ) {
292 throw new ComponentException("The component name has not been set");
293 }
294
295 // 112.10 There must be one implementation element and the class atribute is required
296 if ( m_implementationClassName == null ) {
297 throw new ComponentException("The implementation class name has not been set for this component");
298 }
299
300 // 112.2.3 A delayed component specifies a service, is not specified to be a factory component
301 // and does not have the immediate attribute of the component element set to true.
Felix Meschberger65cce822007-08-14 11:33:05 +0000302 if ( m_immediate != null && isImmediate() == false && m_service == null ) {
303 throw new ComponentException( "Component '" + m_name
304 + "' is specified as being delayed but does not provide any service." );
305 }
Richard S. Hall0c111822006-09-17 19:43:50 +0000306
Felix Meschberger65cce822007-08-14 11:33:05 +0000307 if ( m_factory != null && isImmediate() == false) {
Richard S. Hall0c111822006-09-17 19:43:50 +0000308 throw new ComponentException("A factory cannot be a delayed component");
309 }
310
Felix Meschberger65cce822007-08-14 11:33:05 +0000311 // 112.4.6 The serviceFactory attribute (of a provided service) must not be true if
Richard S. Hall0c111822006-09-17 19:43:50 +0000312 // the component is a factory component or an immediate component
Felix Meschberger65cce822007-08-14 11:33:05 +0000313 if ( m_service != null ) {
314 if ( m_service.isServiceFactory() && ( isFactory() || isImmediate() ) ) {
315 throw new ComponentException( "A ServiceFactory service cannot be a factory or immediate component" );
316 }
317 }
Richard S. Hall0c111822006-09-17 19:43:50 +0000318
319
320 m_validated = true;
321 // TODO: put a similar flag on the references and the services
322 }
323
324}