001package com.kabira.platform.switchconfig;
002
003/*
004 * $RCSfile: ConfigurationListener.java,v $
005 * $Revision: 1.1.2.14.4.2 $ $Date: 2015/05/10 16:08:12 $
006 *
007 * Copyright 2010-2015 TIBCO Software Inc. ALL RIGHTS RESERVED. 
008 * TIBCO Software Inc. Confidential Information
009 */
010import com.kabira.platform.DeleteTrigger;
011import com.kabira.platform.InOutParameter;
012import com.kabira.platform.KeyFieldValueList;
013import com.kabira.platform.KeyManager;
014import com.kabira.platform.KeyQuery;
015import com.kabira.platform.LockMode;
016import com.kabira.platform.ManagedObject;
017import com.kabira.platform.annotation.Managed;
018import java.util.List;
019
020/**
021 * Listener for lifecycle changes to configuration versions.
022 * <p>
023 * Instances of this class will listen for configuration
024 * lifecycle events - <code>load</code>, <code>activate</code>,
025 * <code>deactivate</code>, <code>replace</code>, and <code>remove</code>.
026 * <p>
027 * Creating a listener instance implicitly registers the instance for
028 * a configuration type.  A listener instance can only listen for one
029 * configuration type. Each type
030 * may have zero, one, or more listener instances registered. If multiple
031 * listeners are registered for the same configuration type, each listener
032 * will be called for each lifecycle event. The order in which they are invoked
033 * is non-deterministic.
034 * See the
035 * Configuration chapter of the Developer's Guide for more information
036 * on configuration types.
037 * <p>
038 * This class provides both audit and lifecycle callbacks.
039 * <p>
040 * Audit methods are invoked before the state transition, and may veto
041 * the requested change if a state or consistency problem is detected.
042 * As an example, you may disallow deactivate and replace of a version
043 * if it is currently managing a connected network resource.
044 * <p>
045 * Lifecycle callbacks occur after the state transition
046 * is confirmed. In the lifecycle callbacks, you should implement any
047 * application-visible changes to follow the new configuration state - for
048 * example, creating and starting network resources based on a Config instance.
049 */
050@Managed
051public class ConfigurationListener implements DeleteTrigger
052{
053    private Notifier m_delegate;
054
055    /**
056     * Create an instance to listen for configuration lifecycle events.
057     * <p>
058     * All configuration listeners must provide a constructor that overrides
059     * this constructor.  The configuration type must be specified in the
060     * child constructor and passed to this constructor using super.
061     * <p>
062         * Creating an instance of a configuration listener implicitly
063         * registers a listener for the configurationType.
064         * <p>
065         * @param configurationType Configuration type
066         */
067    public ConfigurationListener(String configurationType)
068    {
069        KeyQuery<GroupKind> kq;
070        KeyFieldValueList kfvl;
071        GroupKind type;
072
073        //  The configuration type is selected using the ByGroupKind key.
074        //  Take a write-lock because we are going to modify the type
075        //  when we install the notifier
076        //
077        kq = new KeyManager<GroupKind>().createKeyQuery(
078                                            GroupKind.class, "ByGroupKind");
079        kfvl = new KeyFieldValueList();
080        kfvl.add("groupKind", configurationType);
081        kq.defineQuery(kfvl);
082        type = kq.getOrCreateSingleResult(LockMode.WRITELOCK, null);
083
084        // Create a configuration notifier that will map the switchconfig 
085        // notifier calls to the ConfigurationListener interface.
086        //
087        m_delegate = new ListenerDelegate(this);
088
089        // Register the configuration notifier.
090        //
091        InOutParameter<Notifier> notifier = new InOutParameter<Notifier>();
092        notifier.setValue(m_delegate);
093        type.registerNotifier(notifier);
094    }
095
096        @Override
097    public void uponDelete() 
098    {
099        if (m_delegate != null)
100        {
101            ManagedObject.delete(m_delegate);
102        }
103    }
104
105    /**
106     * Called when a new version has been loaded for a registered configuration
107     * type. The listener may provide additional Config instances to be appended
108     * to the version by passing them back in the <code>additions</code>
109     * parameter.
110     * <p>
111     * This method may also veto the load by throwing
112     * <code>ConfigurationException</code>.
113     *
114     * @param version Version instance that has been loaded.
115     * @param additions a list of Config instances to be added to the
116     * newly-loaded version. This will be a valid List instance supporting
117     * <code>add</code> when the method is invoked.
118     * @throws ConfigurationException thrown by the implementation 
119     * in order to veto the version load.
120     */
121    public void loaded(
122            final Version version,
123            List<Config> additions)
124            throws ConfigurationException
125    {
126        /* TBI by subtype  */
127    }
128
129    /**
130     * Called when a configuration version has been activated for a registered
131     * configuration type. Note that this is called only when there is no
132     * version already active for the configuration that <code>version</code>
133     * belongs to.  If the new version is replacing a previous active version, 
134     * then {@link #replaced} is called instead.
135     * <p>
136     * Implementations that modify non-transactional resources should
137     * manage this carefully in activated() and deactivated(). See the
138     * Transactions chapter of the  Developer's Guide.
139     *
140     * @param version A version instance that has been activated.
141     */
142    public void activated(final Version version)
143    {
144        /* TBI by subtype */
145    }
146
147    /**
148     * Called when a configuration version has been deactivated for a registered
149     * configuration type. Note that this is called only when there is no
150     * other version that will immediately replace this one. If a new version
151     * is replacing this version, then
152     * {@link #replaced} is called instead.
153     * @param version A version instance that has been deactivated.
154     */
155    public void deactivated(final Version version)
156    {
157        /* TBI by subtype */
158    }
159
160    /**
161     * Called when a configuration version has been activated, replacing an
162     * existing, active, version.
163     * <p>
164     * The default implementation of this method is to call the
165     * <code>deactivated</code> and <code>activated</code>
166     * methods directly.
167     * <p>
168     * @param deactivated Version instance that has been deactivated.
169     * @param activated Version instance that has been activated.
170     */
171    public void replaced(final Version deactivated,
172                         final Version activated)
173    {
174        deactivated(deactivated);
175        activated(activated);
176    }
177
178    /**
179     * Called when a configuration version has been removed.
180     * @param version Version instance that has been removed.
181     */
182    public void removed(final Version version)
183    {
184        /* TBI by subtype */
185    }
186
187    /**
188     * Called when a configuration version is loaded for a registered
189     * configuration type. This operation will be called after
190     * the entire version has been loaded.  This means that
191     * <code>versionLoaded</code> will be invoked on all registered listeners
192     * before <code>auditLoad</code> is called on any listener.
193     * <p>
194     * This method should check whether the given version is
195     * legal to be loaded. If this version is not legal, the listener
196     * may veto the version by throwing <code>ConfigurationException</code>.
197     *
198     * @param version The version instance about to be loaded.
199     * @throws ConfigurationException to veto the entire version load.
200     */
201    public void auditLoad(final Version version)
202                          throws ConfigurationException
203    {
204        /* TBI by subtype */
205    }
206
207    /**
208     * Called before a configuration version is activated for a registered
209     * configuration type. Note that this is called only when there is no
210     * version already active for the configuration that <code>version</code>
211     * belongs to.  If the new version will replace a previous active version, 
212     * then {@link #auditReplace} is called instead.
213     * <p>
214     * This method should check whether the given version is
215     * legal to be activated. It may veto the activation by throwing
216     * <code>ConfigurationException</code>.
217     * <p>
218     * @param version The version instance to be activated.
219     * @throws ConfigurationException to veto the version activation.
220     */
221    public void auditActivate(final Version version) 
222                                throws ConfigurationException
223    {
224        /* TBI by subtype */
225    }
226    /**
227     * Called before a configuration version is deactivated for a registered
228     * configuration type. Note that this is called only when there is no
229     * version being activated for the configuration that <code>version</code> 
230     * belongs to.  If a new version will replace the previously-active version,
231     * then {@link #auditReplace} is called instead.
232     * <p>
233     * This method should check whether the given version is
234     * legal to be deactivated. It may veto the deactivation by throwing
235     * <code>ConfigurationException</code>.
236     * <p>
237     * @param version The version instance to be deactivated.
238     * @throws ConfigurationException to veto the version deactivation.
239     */
240    public void auditDeactivate(
241            final Version version) throws ConfigurationException
242    {
243        /* TBI by subtype */
244    }
245
246    /**
247     * Called before a configuration version is replacing the active version
248     * for a registered configuration type.
249     * Note that this is called only when a new version is replacing an
250     * existing active version.
251     * <p>
252     * This method should check whether the given version replacement is
253     * legal. It may veto the replace operation by throwing
254     * <code>ConfigurationException</code>.
255     * <p>
256     * @param deactivating The version to be deactivated.
257     * @param activating The version to be activated.
258     * @throws ConfigurationException to veto the version replace.
259     */
260    public void auditReplace(
261            final Version deactivating,
262            final Version activating)
263            throws ConfigurationException
264    {
265        /* TBI by subtype */
266    }
267
268    /**
269     * Called before a configuration version is removed
270     * for a registered configuration type.
271     * <p>
272     * This method should check whether the given remove is
273     * legal. It may veto the remove operation by throwing
274     * <code>ConfigurationException</code>.
275     * <p>
276     * @param version The version to be removed.
277     * @throws ConfigurationException to veto the version removal.
278     */
279    public void auditRemove(final Version version) throws ConfigurationException
280    {
281        /* TBI by subtype */
282    }
283}