001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.felix.ipojo;
020
021import static java.lang.String.format;
022
023import org.apache.felix.ipojo.architecture.ComponentTypeDescription;
024import org.apache.felix.ipojo.architecture.PropertyDescription;
025import org.apache.felix.ipojo.extender.internal.Extender;
026import org.apache.felix.ipojo.metadata.Element;
027import org.apache.felix.ipojo.util.Log;
028import org.apache.felix.ipojo.util.Logger;
029import org.apache.felix.ipojo.util.SecurityHelper;
030import org.osgi.framework.BundleContext;
031import org.osgi.framework.Constants;
032import org.osgi.framework.ServiceReference;
033import org.osgi.framework.ServiceRegistration;
034import org.osgi.service.cm.ManagedServiceFactory;
035
036import java.util.*;
037import java.util.concurrent.ConcurrentHashMap;
038import java.util.concurrent.atomic.AtomicLong;
039
040/**
041 * This class defines common mechanisms of iPOJO component factories
042 * (i.e. component type).
043 *
044 * The factory is also tracking Factory configuration from the configuration admin to created / delete and update
045 * instances from this factory.
046 *
047 * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
048 */
049public abstract class IPojoFactory implements Factory {
050    /*
051     * TODO there is potentially an issue when calling FactoryStateListener callbacks with the lock
052     * It should be called by a separate thread dispatching events to listeners.
053     */
054
055    /**
056     * The list of the managed instance name.
057     * This list is shared by all factories and is used to assert name uniqueness.
058     */
059    protected static final List<String> INSTANCE_NAME = Collections.synchronizedList(new ArrayList<String>());
060
061    /**
062     * The component type description exposed by the {@link Factory} service.
063     */
064    protected ComponentTypeDescription m_componentDesc;
065
066    /**
067     * The list of the managed instance managers.
068     * The key of this map is the name (i.e. instance names) of the created instance
069     */
070    protected final Map<String, ComponentInstance> m_componentInstances = new ConcurrentHashMap<String, ComponentInstance>();
071
072    /**
073     * The component type metadata.
074     */
075    protected final Element m_componentMetadata;
076
077    /**
078     * The bundle context reference.
079     */
080    protected final BundleContext m_context;
081
082    /**
083     * The factory name.
084     * Could be the component class name if the factory name is not set.
085     * Immutable once set.
086     */
087    protected String m_factoryName;
088
089    /**
090     * The list of required handlers.
091     */
092    protected final List<RequiredHandler> m_requiredHandlers = new ArrayList<RequiredHandler>();
093
094    /**
095     * The list of factory state listeners.
096     * @see FactoryStateListener
097     */
098    protected List<FactoryStateListener> m_listeners = new ArrayList<FactoryStateListener>(1);
099
100    /**
101     * The logger for the factory.
102     */
103    protected final Logger m_logger;
104
105    /**
106     * Is the factory public (exposed as services).
107     */
108    protected final boolean m_isPublic;
109
110    /**
111     * The version of the component type.
112     */
113    protected final String m_version;
114
115    /**
116     * The service registration of this factory (Factory & ManagedServiceFactory).
117     * @see ManagedServiceFactory
118     * @see Factory
119     */
120    protected ServiceRegistration m_sr;
121
122    /**
123     * The factory state.
124     * Can be:
125     * <li>{@link Factory#INVALID}</li>
126     * <li>{@link Factory#VALID}</li>
127     * The factory is invalid at the beginning.
128     * A factory becomes valid if every required handlers
129     * are available (i.e. can be created).
130     */
131    protected int m_state = Factory.INVALID;
132
133    /**
134     * The flag indicating if this factory has already a
135     * computed description or not.
136     */
137    private boolean m_described;
138
139    /**
140     * Generates a unique instance name if not provided by the configuration.
141     */
142    private final NameGenerator m_generator = new RetryNameGenerator(new DefaultNameGenerator());
143
144    /**
145     * Creates an iPOJO Factory.
146     * At the end of this method, the required set of handler is computed.
147     * But the result is computed by a sub-class.
148     * @param context the bundle context of the bundle containing the factory.
149     * @param metadata the description of the component type.
150     * @throws ConfigurationException if the element describing the factory is malformed.
151     */
152    public IPojoFactory(BundleContext context, Element metadata) throws ConfigurationException {
153        m_context = context;
154        m_componentMetadata = metadata;
155        m_factoryName = getFactoryName();
156        String fac = metadata.getAttribute("public");
157        m_isPublic = fac == null || !fac.equalsIgnoreCase("false");
158        m_logger = new Logger(m_context, m_factoryName);
159
160        // Compute the component type version.
161        String version = metadata.getAttribute("version");
162        if ("bundle".equalsIgnoreCase(version)) { // Handle the "bundle" constant: use the bundle version.
163            // The cast is necessary in KF.
164            m_version = (String) m_context.getBundle().getHeaders().get(Constants.BUNDLE_VERSION);
165        } else {
166            m_version = version;
167        }
168
169        m_requiredHandlers.addAll(getRequiredHandlerList()); // Call sub-class to get the list of required handlers.
170
171        m_logger.log(Logger.INFO, "New factory created : " + m_factoryName);
172    }
173
174    /**
175     * Gets the component type description.
176     * @return the component type description
177     */
178    public ComponentTypeDescription getComponentTypeDescription() {
179        return new ComponentTypeDescription(this);
180    }
181
182    /**
183     * Adds a factory listener.
184     * @param listener the factory listener to add.
185     * @see org.apache.felix.ipojo.Factory#addFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
186     */
187    public void addFactoryStateListener(FactoryStateListener listener) {
188        synchronized (this) {
189            m_listeners.add(listener);
190        }
191    }
192
193    /**
194     * Gets the logger used by instances created by the current factory.
195     * @return the factory logger.
196     */
197    public Logger getLogger() {
198        return m_logger;
199    }
200
201    /**
202     * Computes the factory name.
203     * Each sub-type must override this method.
204     * @return the factory name.
205     */
206    public abstract String getFactoryName();
207
208    /**
209     * Computes the required handler list.
210     * Each sub-type must override this method.
211     * @return the required handler list
212     * @throws ConfigurationException when the list of handler cannot be computed.
213     */
214    public abstract List<RequiredHandler> getRequiredHandlerList() throws ConfigurationException;
215
216    /**
217     * Creates an instance.
218     * This method is called with the monitor lock.
219     * @param config the instance configuration
220     * @param context the iPOJO context to use
221     * @param handlers the handler array to use
222     * @return the new component instance.
223     * @throws ConfigurationException if the instance creation failed during the configuration process.
224     */
225    public abstract ComponentInstance createInstance(Dictionary config, IPojoContext context, HandlerManager[] handlers)
226        throws ConfigurationException;
227
228    /**
229     * Creates an instance.
230     * This method creates the instance in the global context.
231     * @param configuration the configuration of the created instance.
232     * @return the created component instance.
233     * @throws UnacceptableConfiguration if the given configuration is not consistent with the component type of this factory.
234     * @throws MissingHandlerException if an handler is unavailable when the instance is created.
235     * @throws org.apache.felix.ipojo.ConfigurationException if the instance or type configuration are not correct.
236     * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
237     */
238    public ComponentInstance createComponentInstance(Dictionary configuration) throws UnacceptableConfiguration, MissingHandlerException,
239            ConfigurationException {
240        return createComponentInstance(configuration, null);
241    }
242
243    /**
244     * Creates an instance in the specified service context.
245     * This method is synchronized to assert the validity of the factory during the creation.
246     * Callbacks to sub-class and  created instances need to be aware that they are holding the monitor lock.
247     * This method call the override {@link IPojoFactory#createInstance(Dictionary, IPojoContext, HandlerManager[])}
248     * method.
249     * @param configuration the configuration of the created instance.
250     * @param serviceContext the service context to push for this instance.
251     * @return the created component instance.
252     * @throws UnacceptableConfiguration if the given configuration is not consistent with the component type of this factory.
253     * @throws MissingHandlerException if an handler is unavailable when creating the instance.
254     * @throws org.apache.felix.ipojo.ConfigurationException if the instance configuration failed.
255     * @see org.apache.felix.ipojo.Factory#createComponentInstance(java.util.Dictionary)
256     */
257    public synchronized ComponentInstance createComponentInstance(Dictionary configuration, ServiceContext serviceContext) throws UnacceptableConfiguration, // NOPMD
258            MissingHandlerException, ConfigurationException {
259        if (configuration == null) {
260            configuration = new Properties();
261        }
262
263        IPojoContext context;
264        if (serviceContext == null) {
265            context = new IPojoContext(m_context);
266        } else {
267            context = new IPojoContext(m_context, serviceContext);
268        }
269
270        try {
271            checkAcceptability(configuration);
272        } catch (UnacceptableConfiguration e) {
273            m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
274            throw new UnacceptableConfiguration("The configuration "
275                    + configuration + " is not acceptable for " + m_factoryName
276                    , e);
277        }
278
279        // Find name in the configuration
280        String name = findInstanceName(configuration);
281
282        // Execute name generation and verification in a synchronized block to ensure uniqueness
283        synchronized (INSTANCE_NAME) {
284            if (name != null) {
285                // Needs to ensure name uniqueness
286                if (INSTANCE_NAME.contains(name)) {
287                    // name already in use, try to append factory's version
288                    if (m_version != null) {
289                        name = name + "-" + m_version;
290                        if (INSTANCE_NAME.contains(name)) {
291                            // It's still not unique
292                            // We've done our best: throw an Exception
293                            throw new UnacceptableConfiguration(format("%s : Instance name (suffixed with factory's version) \"%s\" is already used", getFactoryName(), name));
294                        }
295                    } else {
296                        // No version provided: we cannot do more
297                        throw new UnacceptableConfiguration(format("%s : Instance name (provided by the instance) \"%s\" is already used", getFactoryName(), name));
298                    }
299                }
300            } else {
301                // Generated name is always unique, no verification required
302                name = m_generator.generate(this, INSTANCE_NAME);
303            }
304
305            // Reserve name
306            INSTANCE_NAME.add(name);
307        }
308
309        // Update name in configuration
310        configuration.put(Factory.INSTANCE_NAME_PROPERTY, name);
311
312        // Here we are sure to be valid until the end of the method.
313        HandlerManager[] handlers = new HandlerManager[m_requiredHandlers.size()];
314        for (int i = 0; i < handlers.length; i++) {
315            handlers[i] = getHandler(m_requiredHandlers.get(i), serviceContext);
316        }
317
318        try {
319            ComponentInstance instance = createInstance(configuration, context, handlers);
320            m_componentInstances.put(name, instance);
321            m_logger.log(Logger.INFO, "Instance " + name + " from factory " + m_factoryName + " created");
322            // Register the instance on the ConfigurationTracker to be updated if needed.
323            ConfigurationTracker.get().instanceCreated(instance);
324            return instance;
325        } catch (ConfigurationException e) {
326            INSTANCE_NAME.remove(name);
327            m_logger.log(Logger.ERROR, e.getMessage());
328            throw new ConfigurationException(e.getMessage(), e, m_factoryName);
329        }
330
331
332    }
333
334    private String findInstanceName(final Dictionary configuration) {
335        String name;
336        if (configuration.get(Factory.INSTANCE_NAME_PROPERTY) == null && configuration.get("name") == null) {
337            // No name provided
338            name = null;
339        } else {
340            // Support both instance.name & name
341            name = (String) configuration.get(Factory.INSTANCE_NAME_PROPERTY);
342            if (name == null) {
343                name = (String) configuration.get("name");
344                getLogger().log(Logger.WARNING, "The 'name' (" + name + ") attribute, used as the instance name, is deprecated, please use the 'instance.name' attribute");
345            }
346        }
347        return name;
348    }
349
350    /**
351     * Gets the bundle context of the factory.
352     * @return the bundle context of the factory.
353     * @see org.apache.felix.ipojo.Factory#getBundleContext()
354     */
355    public BundleContext getBundleContext() {
356        return m_context;
357    }
358
359    /**
360     * Gets the factory class name.
361     * @return the factory class name.
362     * @see org.apache.felix.ipojo.Factory#getClassName()
363     */
364    public abstract String getClassName();
365
366    /**
367     * Gets the component type description.
368     * @return the component type description object. <code>Null</code> if not already computed.
369     */
370    public ComponentTypeDescription getComponentDescription() {
371        return m_componentDesc;
372    }
373
374    /**
375     * Gets the component type description (Element-Attribute form).
376     * @return the component type description.
377     * @see org.apache.felix.ipojo.Factory#getDescription()
378     */
379    public Element getDescription() {
380        // Can be null, if not already computed.
381        if (m_componentDesc == null) {
382            return new Element("No description available for " + m_factoryName, "");
383        }
384        return m_componentDesc.getDescription();
385    }
386
387    /**
388     * Gets the component metadata.
389     * @return the component metadata
390     * @see org.apache.felix.ipojo.Factory#getComponentMetadata()
391     */
392    public Element getComponentMetadata() {
393        return m_componentMetadata;
394    }
395
396    /**
397     * Gets the list of instances created by the factory. The instances must be still alive.
398     *
399     * @return the list of created (and living) instances
400     * @since 1.11.0
401     */
402    public List<ComponentInstance> getInstances() {
403        // m_componentInstances is a concurrent hashmap, we can create retrieve values directly.
404        return new ArrayList<ComponentInstance>(m_componentInstances.values());
405    }
406
407    /**
408     * Gets the list of the names of the instances created by the factory. The instances must be still alive.
409     *
410     * @return the list of the names of created (and living) instances
411     * @since 1.11.0
412     */
413    public List<String> getInstancesNames() {
414        // m_componentInstances is a concurrent hashmap, we can create retrieve values directly.
415        return new ArrayList<String>(m_componentInstances.keySet());
416    }
417
418    /**
419     * Computes the list of missing handlers.
420     * @return the list of missing handlers.
421     * @see org.apache.felix.ipojo.Factory#getMissingHandlers()
422     */
423    public List<String> getMissingHandlers() {
424        List<String> list = new ArrayList<String>();
425        for (RequiredHandler req : m_requiredHandlers) {
426            if (req.getReference() == null) {
427                list.add(req.getFullName());
428            }
429        }
430        return list;
431    }
432
433    /**
434     * Gets the factory name.
435     * This name is immutable once set.
436     * @return the factory name.
437     * @see org.apache.felix.ipojo.Factory#getName()
438     */
439    public String getName() {
440        return m_factoryName;
441    }
442
443    /**
444     * Gets the list of required handlers.
445     * The required handler list cannot change.
446     * @return the list of required handlers.
447     * @see org.apache.felix.ipojo.Factory#getRequiredHandlers()
448     */
449    public List<String> getRequiredHandlers() {
450        List<String> list = new ArrayList<String>();
451        for (RequiredHandler req : m_requiredHandlers) {
452            list.add(req.getFullName());
453        }
454        return list;
455    }
456
457    /**
458     * Gets the actual factory state.
459     * Must be synchronized as this state is dependent of handler availability.
460     * @return the actual factory state.
461     * @see org.apache.felix.ipojo.Factory#getState()
462     */
463    public synchronized int getState() {
464        return m_state;
465    }
466
467    /**
468     * Gets a component instance created by the current factory.
469     * @param name the instance name
470     * @return the component instance, {@literal null} if not found
471     */
472    public ComponentInstance getInstanceByName(String name) {
473        return m_componentInstances.get(name);
474    }
475
476    /**
477     * Checks if the configuration is acceptable.
478     * @param conf the configuration to test.
479     * @return <code>true</code> if the configuration is acceptable.
480     * @see org.apache.felix.ipojo.Factory#isAcceptable(java.util.Dictionary)
481     */
482    public boolean isAcceptable(Dictionary conf) {
483        try {
484            checkAcceptability(conf);
485        } catch (MissingHandlerException e) {
486            return false;
487        } catch (UnacceptableConfiguration e) {
488            return false;
489        }
490        return true;
491    }
492
493    /**
494     * Checks if the configuration is acceptable.
495     * This method checks the following assertions:
496     * <li>All handlers can be creates</li>
497     * <li>The configuration does not override immutable properties</li>
498     * <li>The configuration contains a value for every unvalued property</li>
499     * @param conf the configuration to test.
500     * @throws UnacceptableConfiguration if the configuration is unacceptable.
501     * @throws MissingHandlerException if an handler is missing.
502     */
503    public void checkAcceptability(Dictionary<String, ?> conf) throws UnacceptableConfiguration,
504            MissingHandlerException {
505        PropertyDescription[] props;
506        synchronized (this) {
507            if (m_state == Factory.INVALID) {
508                throw new MissingHandlerException(getMissingHandlers());
509            }
510            props = m_componentDesc.getProperties(); // Stack confinement.
511            // The property list is up to date, as the factory is valid.
512        }
513
514        // Check that the configuration does not override immutable properties.
515
516        for (PropertyDescription prop : props) {
517            // Is the property immutable
518            if (prop.isImmutable() && conf.get(prop.getName()) != null) {
519                throw new UnacceptableConfiguration("The property " + prop + " cannot be overridden : immutable " +
520                        "property"); // The instance configuration tries to override an immutable property.
521            }
522            // Is the property required ?
523            if (prop.isMandatory() && prop.getValue() == null && conf.get(prop.getName()) == null) {
524                throw new UnacceptableConfiguration("The mandatory property " + prop.getName() + " is missing"); // The property must be set.
525            }
526        }
527    }
528
529    /**
530     * Reconfigures an existing instance.
531     * The acceptability of the configuration is checked before the reconfiguration. Moreover,
532     * the configuration must contain the 'instance.name' property specifying the instance
533     * to reconfigure.
534     * This method is synchronized to assert the validity of the factory during the reconfiguration.
535     * @param properties the new configuration to push.
536     * @throws UnacceptableConfiguration if the new configuration is not consistent with the component type.
537     * @throws MissingHandlerException if the current factory is not valid.
538     * @see org.apache.felix.ipojo.Factory#reconfigure(java.util.Dictionary)
539     */
540    public synchronized void reconfigure(Dictionary properties) throws UnacceptableConfiguration, MissingHandlerException {
541        if (properties == null || (properties.get(Factory.INSTANCE_NAME_PROPERTY) == null && properties.get("name") == null)) { // Support both instance.name and name
542            throw new UnacceptableConfiguration("The configuration does not contains the \"instance.name\" property");
543        }
544
545        String name = (String) properties.get(Factory.INSTANCE_NAME_PROPERTY);
546        if (name == null) {
547            name = (String) properties.get("name");
548        }
549
550        ComponentInstance instance = m_componentInstances.get(name);
551        if (instance == null) { // The instance does not exists.
552            return;
553        }
554
555        checkAcceptability(properties); // Test if the configuration is acceptable
556        instance.reconfigure(properties); // re-configure the instance
557    }
558
559    /**
560     * Removes a factory listener.
561     * @param listener the factory listener to remove.
562     * @see org.apache.felix.ipojo.Factory#removeFactoryStateListener(org.apache.felix.ipojo.FactoryStateListener)
563     */
564    public void removeFactoryStateListener(FactoryStateListener listener) {
565        synchronized (this) {
566            m_listeners.remove(listener);
567        }
568    }
569
570    /**
571     * Stopping method.
572     * This method is call when the factory is stopping.
573     * This method is called when holding the lock on the factory.
574     */
575    public abstract void stopping();
576
577    /**
578     * Stops all the instance managers.
579     * This method calls the {@link IPojoFactory#stopping()} method,
580     * notifies listeners, and disposes created instances. Moreover,
581     * if the factory is public, services are also unregistered.
582     *
583     */
584    public synchronized void stop() {
585        ComponentInstance[] instances;
586        if (m_sr != null) {
587            m_sr.unregister();
588            m_sr = null;
589        }
590
591        ConfigurationTracker.get().unregisterFactory(this);
592
593        stopping(); // Method called when holding the lock.
594        int oldState = m_state; // Create a variable to store the old state. Using a variable is important as
595                                // after the next instruction, the getState() method must return INVALID.
596        m_state = INVALID; // Set here to avoid to create instances during the stops.
597
598        Set<String> col = m_componentInstances.keySet();
599        Iterator<String> it = col.iterator();
600        instances = new ComponentInstance[col.size()]; // Stack confinement
601        int index = 0;
602        while (it.hasNext()) {
603            instances[index] = m_componentInstances.get(it.next());
604            index++;
605        }
606
607        if (oldState == VALID) { // Check if the old state was valid.
608            for (FactoryStateListener listener : m_listeners) {
609                listener.stateChanged(this, INVALID);
610            }
611        }
612
613        // Dispose created instances.
614        for (ComponentInstance instance : instances) {
615            if (instance.getState() != ComponentInstance.DISPOSED) {
616                instance.dispose();
617            }
618        }
619
620        // Release each handler
621        for (RequiredHandler req : m_requiredHandlers) {
622            req.unRef();
623        }
624
625        m_described = false;
626        m_componentDesc = null;
627        m_componentInstances.clear();
628
629        m_logger.log(Logger.INFO, "Factory " + m_factoryName + " stopped");
630
631    }
632
633    /**
634     * Destroys the factory.
635     * The factory cannot be restarted. Only the {@link Extender} can call this method.
636     */
637    public synchronized void dispose() {
638        // Fast exit if already disposed
639        // The m_listeners field is ONLY set to null after dispose(), so if it's null, that
640        // means the factory has already be disposed. We can return safely.
641        if (m_listeners == null) {
642            return;
643        }
644        stop(); // Does not hold the lock.
645        m_requiredHandlers.clear();
646        m_listeners = null;
647    }
648
649    /**
650     * Starting method.
651     * This method is called when the factory is starting.
652     * This method is <strong>not</strong> called when holding the lock on the factory.
653     */
654    public abstract void starting();
655
656    /**
657     * Starts the factory.
658     * Tries to compute the component type description,
659     * calls the {@link IPojoFactory#starting()} method,
660     * and published services if the factory is public.
661     */
662    public void start() {
663        synchronized (this) {
664            if (m_described) { // Already started.
665                return;
666            }
667        }
668
669        m_componentDesc = getComponentTypeDescription();
670
671        starting();
672
673        synchronized (this) {
674            computeFactoryState();
675        }
676
677        if (m_isPublic) {
678            // Exposition of the factory service
679            if (m_componentDesc == null) {
680                m_logger.log(Logger.ERROR, "Unexpected state, the description of " + m_factoryName + "  is null");
681                return;
682            }
683            BundleContext bc = SecurityHelper.selectContextToRegisterServices(m_componentDesc.getFactoryInterfacesToPublish(),
684                    m_context, getIPOJOBundleContext());
685            if (SecurityHelper.canRegisterService(bc)) {
686                m_sr =
687                        bc.registerService(m_componentDesc.getFactoryInterfacesToPublish(), this, m_componentDesc
688                                .getPropertiesToPublish());
689                m_logger.log(Logger.INFO, "Factory " + m_factoryName + " started");
690            } else {
691                m_logger.log(Log.ERROR, "Cannot register the Factory service with the bundle context of the bundle "
692                        + bc.getBundle().getBundleId() + " - the bundle is in the state " + bc.getBundle().getState()
693                );
694            }
695        }
696    }
697
698    /**
699     * For testing purpose <b>ONLY</b>.
700     * This method recomputes the required handler list.
701     */
702    public void restart() {
703        // Call sub-class to get the list of required handlers.
704        m_requiredHandlers.clear();
705        try {
706            m_requiredHandlers.addAll(getRequiredHandlerList());
707        } catch (ConfigurationException e) {
708            // Swallow the exception.
709        }
710    }
711
712    /**
713     * Gets the iPOJO Bundle Context.
714     * @return the iPOJO Bundle Context
715     */
716    protected final BundleContext getIPOJOBundleContext() {
717        return Extender.getIPOJOBundleContext();
718    }
719
720    /**
721     * Creates or updates an instance.
722     * This method is used from the configuration tracker.
723     * @param name the name of the instance
724     * @param properties the new configuration of the instance
725     */
726    public void updated(String name, Dictionary properties) throws org.osgi.service.cm
727            .ConfigurationException {
728        ComponentInstance instance;
729        synchronized (this) {
730            instance = m_componentInstances.get(name);
731        }
732
733        if (instance == null) {
734            try {
735                properties.put(Factory.INSTANCE_NAME_PROPERTY, name); // Add the name in the configuration
736                // If an instance with this name was created before, this creation will failed.
737                createComponentInstance(properties);
738            } catch (UnacceptableConfiguration e) {
739                m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
740                throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage(), e);
741            } catch (MissingHandlerException e) {
742                m_logger.log(Logger.ERROR, "Handler not available : " + e.getMessage());
743                throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage(), e);
744            } catch (ConfigurationException e) {
745                m_logger.log(Logger.ERROR, "The Component Type metadata are not correct : " + e.getMessage());
746                throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage(), e);
747            }
748        } else {
749            try {
750                properties.put(Factory.INSTANCE_NAME_PROPERTY, name); // Add the name in the configuration
751                reconfigure(properties); // re-configure the component
752            } catch (UnacceptableConfiguration e) {
753                m_logger.log(Logger.ERROR, "The configuration is not acceptable : " + e.getMessage());
754                throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage(), e);
755            } catch (MissingHandlerException e) {
756                m_logger.log(Logger.ERROR, "The factory is not valid, at least one handler is missing : " + e.getMessage());
757                throw new org.osgi.service.cm.ConfigurationException(properties.toString(), e.getMessage(), e);
758            }
759        }
760    }
761
762    /**
763     * Deletes an instance.
764     * @param name the name of the instance to delete
765     */
766    public synchronized void deleted(String name) {
767        INSTANCE_NAME.remove(name);
768        ComponentInstance instance = m_componentInstances.remove(name);
769        if (instance != null) {
770            instance.dispose();
771        }
772    }
773
774    /**
775     * Callback called by instance when disposed.
776     * @param instance the destroyed instance
777     */
778    public void disposed(ComponentInstance instance) {
779        String name = instance.getInstanceName();
780        m_componentInstances.remove(name);
781        INSTANCE_NAME.remove(name);
782    }
783
784    /**
785     * Computes the component type description.
786     * To do this, it creates a 'ghost' instance of the handler
787     * and calls the {@link Handler#initializeComponentFactory(ComponentTypeDescription, Element)}
788     * method. The handler instance is then deleted.
789     * The factory must be valid when calling this method.
790     * This method is called with the lock.
791     */
792    protected void computeDescription() {
793        for (RequiredHandler req : m_requiredHandlers) {
794            HandlerManager handlerManager = null;
795            try {
796                handlerManager = getHandler(req, null);
797            } catch (Exception e) {
798                m_logger.log(Logger.ERROR, "Cannot extract handler object from " + m_factoryName + " " + req
799                        .getFullName());
800                return;
801            }
802
803            if (handlerManager == null) {
804                m_logger.log(Logger.ERROR, "Cannot extract handler object from " + m_factoryName + " " + req
805                        .getFullName());
806                return;
807            }
808
809            Handler handler = handlerManager.getHandler();
810            try {
811                handler.setFactory(this);
812                handler.initializeComponentFactory(m_componentDesc, m_componentMetadata);
813                ((Pojo) handler).getComponentInstance().dispose();
814            } catch (ConfigurationException e) {
815                ((Pojo) handler).getComponentInstance().dispose();
816                m_logger.log(Logger.ERROR, e.getMessage());
817                stop();
818                throw new IllegalStateException(e);
819            }
820        }
821    }
822
823    /**
824     * Computes factory state.
825     * The factory is valid if every required handler are available.
826     * If the factory becomes valid for the first time, the component
827     * type description is computed.
828     * This method is called when holding the lock on the current factory.
829     */
830    protected void computeFactoryState() {
831        boolean isValid = true;
832        for (RequiredHandler req : m_requiredHandlers) {
833            if (req.getReference() == null) {
834                isValid = false;
835                break;
836            }
837
838        }
839
840        if (isValid) {
841            if (m_state == INVALID) {
842
843                if (!m_described) {
844                    computeDescription();
845                    m_described = true;
846                }
847
848                m_state = VALID;
849                if (m_sr != null) {
850                    if (SecurityHelper.canUpdateService(m_sr)) {
851                        m_sr.setProperties(m_componentDesc.getPropertiesToPublish());
852                    }
853                }
854
855                // Register the factory on the ConfigurationTracker
856                ConfigurationTracker.get().registerFactory(this);
857
858                for (FactoryStateListener listener : m_listeners) {
859                    listener.stateChanged(this, VALID);
860                }
861            }
862        } else {
863            if (m_state == VALID) {
864                m_state = INVALID;
865
866                // Un-register the factory on the ConfigurationTracker
867                ConfigurationTracker.get().unregisterFactory(this);
868
869                // Notify listeners.
870                for (FactoryStateListener listener : m_listeners) {
871                    listener.stateChanged(this, INVALID);
872                }
873
874                // Dispose created instances.
875                // We must create a copy to avoid concurrent exceptions
876                Set<? extends String> keys = new HashSet<String>(m_componentInstances.keySet());
877                for (String key : keys) {
878                    ComponentInstance instance = m_componentInstances.get(key);
879                    if (instance.getState() != ComponentInstance.DISPOSED) {
880                        instance.dispose();
881                    }
882                    INSTANCE_NAME.remove(instance.getInstanceName());
883                }
884
885                m_componentInstances.clear();
886
887                if (SecurityHelper.canUpdateService(m_sr)) {
888                    // No null check required as the security helper is checking this too.
889                    m_sr.setProperties(m_componentDesc.getPropertiesToPublish());
890                }
891            }
892        }
893    }
894
895    /**
896     * Checks if the given handler identifier and the service reference match.
897     * Does not need to be synchronized as the method does not use any fields.
898     * @param req the handler identifier.
899     * @param ref the service reference.
900     * @return <code>true</code> if the service reference can fulfill the handler requirement
901     */
902    protected boolean match(RequiredHandler req, ServiceReference<?> ref) {
903        String name = (String) ref.getProperty(Handler.HANDLER_NAME_PROPERTY);
904        String namespace = (String) ref.getProperty(Handler.HANDLER_NAMESPACE_PROPERTY);
905        if (HandlerFactory.IPOJO_NAMESPACE.equals(namespace)) {
906            return name.equalsIgnoreCase(req.getName()) && req.getNamespace() == null;
907        }
908        return name.equalsIgnoreCase(req.getName()) && namespace.equalsIgnoreCase(req.getNamespace());
909    }
910
911    /**
912     * Returns the handler object for the given required handler.
913     * The handler is instantiated in the given service context.
914     * This method is called with the lock.
915     * @param req the handler to create.
916     * @param context the service context in which the handler is created (same as the instance context).
917     * @return the handler object.
918     */
919    protected HandlerManager getHandler(RequiredHandler req, ServiceContext context) throws MissingHandlerException,
920            UnacceptableConfiguration, ConfigurationException {
921        try {
922            return (HandlerManager) req.getFactory().createComponentInstance(null, context);
923        } catch (MissingHandlerException e) {
924            m_logger.log(Logger.ERROR, "The creation of the handler " + req.getFullName() + " has failed: " + e.getMessage());
925            stop();
926            throw e;
927        } catch (UnacceptableConfiguration e) {
928            m_logger.log(Logger.ERROR, "The creation of the handler "
929                    + req.getFullName()
930                    + " has failed (UnacceptableConfiguration): "
931                    + e.getMessage());
932            stop();
933            throw e;
934        } catch (org.apache.felix.ipojo.ConfigurationException e) {
935            m_logger.log(Logger.ERROR, "The configuration of the handler "
936                    + req.getFullName()
937                    + " has failed (ConfigurationException): "
938                    + e.getMessage());
939            stop();
940            throw e;
941        }
942    }
943
944    /**
945     * Structure storing required handlers.
946     * Access to this class must mostly be with the lock on the factory.
947     * (except to access final fields)
948     */
949    protected class RequiredHandler implements Comparable {
950        /**
951         * The factory to create this handler.
952         */
953        private HandlerFactory m_factory;
954
955        /**
956         * The handler name.
957         */
958        private final String m_name;
959
960        /**
961         * The handler start level.
962         */
963        private int m_level = Integer.MAX_VALUE;
964
965        /**
966         * The handler namespace.
967         */
968        private final String m_namespace;
969
970        /**
971         * The Service Reference of the handler factory.
972         */
973        private ServiceReference<? extends HandlerFactory> m_reference;
974
975        /**
976         * Crates a Required Handler.
977         * @param name the handler name.
978         * @param namespace the handler namespace.
979         */
980        public RequiredHandler(String name, String namespace) {
981            m_name = name;
982            m_namespace = namespace;
983        }
984
985        /**
986         * Equals method.
987         * Two handlers are equals if they have same name and namespace or they share the same service reference.
988         * @param object the object to compare to the current object.
989         * @return <code>true</code> if the two compared object are equals
990         * @see java.lang.Object#equals(java.lang.Object)
991         */
992        public boolean equals(Object object) {
993            if (object instanceof RequiredHandler) {
994                RequiredHandler req = (RequiredHandler) object;
995                if (m_namespace == null) {
996                    return req.m_name.equalsIgnoreCase(m_name) && req.m_namespace == null;
997                } else {
998                    return req.m_name.equalsIgnoreCase(m_name) && m_namespace.equalsIgnoreCase(req.m_namespace);
999                }
1000            } else {
1001                return false;
1002            }
1003
1004        }
1005
1006        /**
1007         * Hashcode method.
1008         * This method delegates to the {@link Object#hashCode()}.
1009         * @return the object hashcode.
1010         * @see java.lang.Object#hashCode()
1011         */
1012        public int hashCode() {
1013            return super.hashCode();
1014        }
1015
1016        /**
1017         * Gets the factory object used for this handler.
1018         * The object is get when used for the first time.
1019         * This method is called with the lock avoiding concurrent modification and on a valid factory.
1020         * @return the factory object.
1021         */
1022        public HandlerFactory getFactory() {
1023            if (m_reference == null) {
1024                return null;
1025            }
1026            if (m_factory == null) {
1027                m_factory = m_context.getService(getReference());
1028            }
1029            return m_factory;
1030        }
1031
1032        /**
1033         * Gets the handler qualified name (<code>namespace:name</code>).
1034         * @return the handler full name
1035         */
1036        public String getFullName() {
1037            if (m_namespace == null) {
1038                return HandlerFactory.IPOJO_NAMESPACE + ":" + m_name;
1039            } else {
1040                return m_namespace + ":" + m_name;
1041            }
1042        }
1043
1044        public String getName() {
1045            return m_name;
1046        }
1047
1048        public String getNamespace() {
1049            return m_namespace;
1050        }
1051
1052        public ServiceReference<? extends HandlerFactory> getReference() {
1053            return m_reference;
1054        }
1055
1056        public int getLevel() {
1057            return m_level;
1058        }
1059
1060        /**
1061         * Releases the reference of the used factory.
1062         * This method is called with the lock on the current factory.
1063         */
1064        public void unRef() {
1065            if (m_reference != null) {
1066                m_factory = null;
1067                m_reference = null;
1068            }
1069        }
1070
1071        /**
1072         * Sets the service reference. If the new service reference is <code>null</code>, it ungets the used factory (if already get).
1073         * This method is called with the lock on the current factory.
1074         * @param ref the new service reference.
1075         */
1076        public void setReference(ServiceReference<? extends HandlerFactory> ref) {
1077            m_reference = ref;
1078            Integer level = (Integer) m_reference.getProperty(Handler.HANDLER_LEVEL_PROPERTY);
1079            if (level != null) {
1080                m_level = level;
1081            }
1082        }
1083
1084        /**
1085         * Start level Comparison.
1086         * This method is used to sort the handler array.
1087         * This method is called with the lock.
1088         * @param object the object on which compare.
1089         * @return <code>-1</code>, <code>0</code>, <code>+1</code> according to the comparison of their start levels.
1090         * @see java.lang.Comparable#compareTo(java.lang.Object)
1091         */
1092        public int compareTo(Object object) {
1093            if (object instanceof RequiredHandler) {
1094                RequiredHandler req = (RequiredHandler) object;
1095                if (this.m_level == req.m_level) {
1096                    return 0;
1097                } else if (this.m_level < req.m_level) {
1098                    return -1;
1099                } else {
1100                    return +1;
1101                }
1102            }
1103            return 0;
1104        }
1105    }
1106
1107
1108    /**
1109     * This generator implements the default naming strategy.
1110     * The name is composed of the factory name suffixed with a unique number identifier (starting from 0).
1111     */
1112    public static class DefaultNameGenerator implements NameGenerator {
1113
1114        private AtomicLong m_nextId = new AtomicLong();
1115
1116        public String generate(Factory factory, List<String> reserved) throws UnacceptableConfiguration {
1117            StringBuilder sb = new StringBuilder();
1118            sb.append(factory.getName());
1119            if (factory.getVersion() != null) {
1120                sb.append("/");
1121                sb.append(factory.getVersion());
1122            }
1123            sb.append("-");
1124            sb.append(m_nextId.getAndIncrement());
1125            return sb.toString();
1126        }
1127    }
1128
1129    /**
1130     * This generator implements a retry naming strategy.
1131     * It uses a delegate {@link org.apache.felix.ipojo.IPojoFactory.NameGenerator}, and call it in sequence until an unused value is found.
1132     */
1133    public static class RetryNameGenerator implements NameGenerator {
1134
1135        private final NameGenerator m_delegate;
1136
1137        /**
1138         * Bound the loop to avoid Stack overflows
1139         */
1140        private long maximum = 8096;
1141
1142        public RetryNameGenerator(final NameGenerator delegate) {
1143            m_delegate = delegate;
1144        }
1145
1146        public void setMaximum(final long maximum) {
1147            this.maximum = maximum;
1148        }
1149
1150        public String generate(final Factory factory, final List<String> reserved) throws UnacceptableConfiguration {
1151            // Loop until we obtain a unique value (or counter overflow)
1152            long counter = 0;
1153            while (counter < maximum) {
1154                String generated = m_delegate.generate(factory, reserved);
1155                counter++;
1156                // Verify uniqueness
1157                if (!reserved.contains(generated)) {
1158                    return generated;
1159                }
1160            }
1161
1162            // Should never happen (except is NameGenerator composition is broken: like a delegate that
1163            // never change its return value)
1164            throw new UnacceptableConfiguration(format("Cannot generate unique instance name for factory %s/%s from bundle %d",
1165                                                       factory.getName(),
1166                                                       factory.getVersion(),
1167                                                       factory.getBundleContext().getBundle().getBundleId()));
1168        }
1169    }
1170
1171    /**
1172     * Generate a unique name for a component instance.
1173     */
1174    public static interface NameGenerator {
1175
1176        /**
1177         * @return a unique name.
1178         * @param factory Factory called to create the instance
1179         * @param reserved List of reserved (already used) instance names.
1180         *                 This has to be used tp ensure generated name is unique among all other instances.
1181         */
1182        String generate(Factory factory, List<String> reserved) throws UnacceptableConfiguration;
1183    }
1184}