001    /*
002     * Copyright (c) OSGi Alliance (2001, 2008). All Rights Reserved.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.osgi.service.cm;
017    
018    import java.util.Dictionary;
019    
020    /**
021     * A service that can receive configuration data from a Configuration Admin
022     * service.
023     * 
024     * <p>
025     * A Managed Service is a service that needs configuration data. Such an object
026     * should be registered with the Framework registry with the
027     * <code>service.pid</code> property set to some unique identifier called a
028     * PID.
029     * 
030     * <p>
031     * If the Configuration Admin service has a <code>Configuration</code> object
032     * corresponding to this PID, it will callback the <code>updated()</code>
033     * method of the <code>ManagedService</code> object, passing the properties of
034     * that <code>Configuration</code> object.
035     * 
036     * <p>
037     * If it has no such <code>Configuration</code> object, then it calls back
038     * with a <code>null</code> properties argument. Registering a Managed Service
039     * will always result in a callback to the <code>updated()</code> method
040     * provided the Configuration Admin service is, or becomes active. This callback
041     * must always be done asynchronously.
042     * 
043     * <p>
044     * Else, every time that either of the <code>updated()</code> methods is
045     * called on that <code>Configuration</code> object, the
046     * <code>ManagedService.updated()</code> method with the new properties is
047     * called. If the <code>delete()</code> method is called on that
048     * <code>Configuration</code> object, <code>ManagedService.updated()</code>
049     * is called with a <code>null</code> for the properties parameter. All these
050     * callbacks must be done asynchronously.
051     * 
052     * <p>
053     * The following example shows the code of a serial port that will create a port
054     * depending on configuration information.
055     * 
056     * <pre>
057     *  
058     *   class SerialPort implements ManagedService {
059     *  
060     *     ServiceRegistration registration;
061     *     Hashtable configuration;
062     *     CommPortIdentifier id;
063     *  
064     *     synchronized void open(CommPortIdentifier id,
065     *     BundleContext context) {
066     *       this.id = id;
067     *       registration = context.registerService(
068     *         ManagedService.class.getName(),
069     *         this,
070     *         getDefaults()
071     *       );
072     *     }
073     *  
074     *     Hashtable getDefaults() {
075     *       Hashtable defaults = new Hashtable();
076     *       defaults.put( &quot;port&quot;, id.getName() );
077     *       defaults.put( &quot;product&quot;, &quot;unknown&quot; );
078     *       defaults.put( &quot;baud&quot;, &quot;9600&quot; );
079     *       defaults.put( Constants.SERVICE_PID,
080     *         &quot;com.acme.serialport.&quot; + id.getName() );
081     *       return defaults;
082     *     }
083     *  
084     *     public synchronized void updated(
085     *       Dictionary configuration  ) {
086     *       if ( configuration == 
087     * <code>
088     * null
089     * </code>
090     *   )
091     *         registration.setProperties( getDefaults() );
092     *       else {
093     *         setSpeed( configuration.get(&quot;baud&quot;) );
094     *         registration.setProperties( configuration );
095     *       }
096     *     }
097     *     ...
098     *   }
099     *   
100     * </pre>
101     * 
102     * <p>
103     * As a convention, it is recommended that when a Managed Service is updated, it
104     * should copy all the properties it does not recognize into the service
105     * registration properties. This will allow the Configuration Admin service to
106     * set properties on services which can then be used by other applications.
107     * 
108     * @version $Revision: 5673 $
109     */
110    public interface ManagedService {
111            /**
112             * Update the configuration for a Managed Service.
113             * 
114             * <p>
115             * When the implementation of <code>updated(Dictionary)</code> detects any
116             * kind of error in the configuration properties, it should create a new
117             * <code>ConfigurationException</code> which describes the problem. This
118             * can allow a management system to provide useful information to a human
119             * administrator.
120             * 
121             * <p>
122             * If this method throws any other <code>Exception</code>, the
123             * Configuration Admin service must catch it and should log it.
124             * <p>
125             * The Configuration Admin service must call this method asynchronously
126             * which initiated the callback. This implies that implementors of Managed
127             * Service can be assured that the callback will not take place during
128             * registration when they execute the registration in a synchronized method.
129             * 
130             * @param properties A copy of the Configuration properties, or
131             *        <code>null</code>. This argument must not contain the
132             *        "service.bundleLocation" property. The value of this property may
133             *        be obtained from the <code>Configuration.getBundleLocation</code>
134             *        method.
135             * @throws ConfigurationException when the update fails
136             */
137            public void updated(Dictionary properties) throws ConfigurationException;
138    }