KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > ui > internal > handlers > HandlerProxy


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * IBM Corporation - initial API and implementation
10  *******************************************************************************/

11
12 package org.eclipse.ui.internal.handlers;
13
14 import java.util.Map JavaDoc;
15
16 import org.eclipse.core.commands.AbstractHandler;
17 import org.eclipse.core.commands.ExecutionEvent;
18 import org.eclipse.core.commands.ExecutionException;
19 import org.eclipse.core.commands.HandlerEvent;
20 import org.eclipse.core.commands.IHandler;
21 import org.eclipse.core.commands.IHandlerListener;
22 import org.eclipse.core.expressions.EvaluationResult;
23 import org.eclipse.core.expressions.Expression;
24 import org.eclipse.core.expressions.IEvaluationContext;
25 import org.eclipse.core.runtime.CoreException;
26 import org.eclipse.core.runtime.IConfigurationElement;
27 import org.eclipse.core.runtime.IStatus;
28 import org.eclipse.core.runtime.Status;
29 import org.eclipse.jface.util.IPropertyChangeListener;
30 import org.eclipse.jface.util.PropertyChangeEvent;
31 import org.eclipse.ui.commands.IElementUpdater;
32 import org.eclipse.ui.internal.WorkbenchPlugin;
33 import org.eclipse.ui.internal.services.IEvaluationReference;
34 import org.eclipse.ui.internal.services.IEvaluationService;
35 import org.eclipse.ui.internal.util.BundleUtility;
36 import org.eclipse.ui.menus.UIElement;
37
38 /**
39  * <p>
40  * A proxy for a handler that has been defined in XML. This delays the class
41  * loading until the handler is really asked for information (besides the
42  * priority or the command identifier). Asking a proxy for anything but the
43  * attributes defined publicly in this class will cause the proxy to instantiate
44  * the proxied handler.
45  * </p>
46  *
47  * @since 3.0
48  */

49 public final class HandlerProxy extends AbstractHandler implements
50         IElementUpdater {
51
52     /**
53      *
54      */

55     private static final String JavaDoc PROP_ENABLED = "enabled"; //$NON-NLS-1$
56

57     /**
58      * The configuration element from which the handler can be created. This
59      * value will exist until the element is converted into a real class -- at
60      * which point this value will be set to <code>null</code>.
61      */

62     private IConfigurationElement configurationElement;
63
64     /**
65      * The <code>enabledWhen</code> expression for the handler. Only if this
66      * expression evaluates to <code>true</code> (or the value is
67      * <code>null</code>) should we consult the handler.
68      */

69     private final Expression enabledWhenExpression;
70
71     /**
72      * The real handler. This value is <code>null</code> until the proxy is
73      * forced to load the real handler. At this point, the configuration element
74      * is converted, nulled out, and this handler gains a reference.
75      */

76     private IHandler handler = null;
77
78     /**
79      * The name of the configuration element attribute which contains the
80      * information necessary to instantiate the real handler.
81      */

82     private final String JavaDoc handlerAttributeName;
83
84     private IHandlerListener handlerListener;
85
86     /**
87      * The evaluation service to use when evaluating
88      * <code>enabledWhenExpression</code>. This value may be
89      * <code>null</code> only if the <code>enabledWhenExpression</code> is
90      * <code>null</code>.
91      */

92     private IEvaluationService evaluationService;
93
94     private IPropertyChangeListener enablementListener;
95
96     private IEvaluationReference enablementRef;
97
98     private boolean proxyEnabled;
99
100     /**
101      * Constructs a new instance of <code>HandlerProxy</code> with all the
102      * information it needs to try to avoid loading until it is needed.
103      *
104      * @param configurationElement
105      * The configuration element from which the real class can be
106      * loaded at run-time; must not be <code>null</code>.
107      * @param handlerAttributeName
108      * The name of the attibute or element containing the handler
109      * executable extension; must not be <code>null</code>.
110      */

111     public HandlerProxy(final IConfigurationElement configurationElement,
112             final String JavaDoc handlerAttributeName) {
113         this(configurationElement, handlerAttributeName, null, null);
114     }
115
116     /**
117      * Constructs a new instance of <code>HandlerProxy</code> with all the
118      * information it needs to try to avoid loading until it is needed.
119      *
120      * @param configurationElement
121      * The configuration element from which the real class can be
122      * loaded at run-time; must not be <code>null</code>.
123      * @param handlerAttributeName
124      * The name of the attribute or element containing the handler
125      * executable extension; must not be <code>null</code>.
126      * @param enabledWhenExpression
127      * The name of the element containing the enabledWhen expression.
128      * This should be a child of the
129      * <code>configurationElement</code>. If this value is
130      * <code>null</code>, then there is no enablement expression
131      * (i.e., enablement will be delegated to the handler when
132      * possible).
133      * @param evaluationService
134      * The evaluation service to manage enabledWhen expressions
135      * trying to evaluate the <code>enabledWhenExpression</code>.
136      * This value may be <code>null</code> only if the
137      * <code>enabledWhenExpression</code> is <code>null</code>.
138      */

139     public HandlerProxy(final IConfigurationElement configurationElement,
140             final String JavaDoc handlerAttributeName,
141             final Expression enabledWhenExpression,
142             final IEvaluationService evaluationService) {
143         if (configurationElement == null) {
144             throw new NullPointerException JavaDoc(
145                     "The configuration element backing a handler proxy cannot be null"); //$NON-NLS-1$
146
}
147
148         if (handlerAttributeName == null) {
149             throw new NullPointerException JavaDoc(
150                     "The attribute containing the handler class must be known"); //$NON-NLS-1$
151
}
152
153         if ((enabledWhenExpression != null) && (evaluationService == null)) {
154             throw new NullPointerException JavaDoc(
155                     "We must have a handler service and evaluation service to support the enabledWhen expression"); //$NON-NLS-1$
156
}
157
158         this.configurationElement = configurationElement;
159         this.handlerAttributeName = handlerAttributeName;
160         this.enabledWhenExpression = enabledWhenExpression;
161         this.evaluationService = evaluationService;
162         if (enabledWhenExpression != null) {
163             setProxyEnabled(false);
164             registerEnablement();
165         } else {
166             setProxyEnabled(true);
167         }
168     }
169
170     /**
171      *
172      */

173     private void registerEnablement() {
174         enablementRef = evaluationService.addEvaluationListener(
175                 enabledWhenExpression, getEnablementListener(), PROP_ENABLED,
176                 null);
177     }
178
179     void setEnabledFor(IEvaluationContext context) throws ExecutionException {
180         if (enabledWhenExpression != null) {
181             try {
182                 setProxyEnabled(enabledWhenExpression.evaluate(context) == EvaluationResult.TRUE);
183             } catch (CoreException e) {
184                 throw new ExecutionException(e.getMessage(), e);
185             }
186         }
187     }
188
189     void setProxyEnabled(boolean enabled) {
190         proxyEnabled = enabled;
191     }
192
193     boolean getProxyEnabled() {
194         return proxyEnabled;
195     }
196
197     /**
198      * @return
199      */

200     private IPropertyChangeListener getEnablementListener() {
201         if (enablementListener == null) {
202             enablementListener = new IPropertyChangeListener() {
203                 public void propertyChange(PropertyChangeEvent event) {
204                     if (event.getProperty() == PROP_ENABLED) {
205                         setProxyEnabled(event.getNewValue() == null ? false
206                                 : ((Boolean JavaDoc) event.getNewValue())
207                                         .booleanValue());
208                         fireHandlerChanged(new HandlerEvent(HandlerProxy.this,
209                                 true, false));
210                     }
211                 }
212             };
213         }
214         return enablementListener;
215     }
216
217     /**
218      * Passes the dipose on to the proxied handler, if it has been loaded.
219      */

220     public final void dispose() {
221         if (handler != null) {
222             if (handlerListener != null) {
223                 handler.removeHandlerListener(handlerListener);
224                 handlerListener = null;
225             }
226             handler.dispose();
227             handler = null;
228         }
229         if (enablementListener != null) {
230             evaluationService.removeEvaluationListener(enablementRef);
231             enablementRef = null;
232             enablementListener = null;
233         }
234     }
235
236     public final Object JavaDoc execute(final ExecutionEvent event)
237             throws ExecutionException {
238         if (loadHandler()) {
239             return handler.execute(event);
240         }
241
242         return null;
243     }
244
245     public final boolean isEnabled() {
246         if (enabledWhenExpression != null) {
247             // proxyEnabled reflects the enabledWhen clause
248
if (!getProxyEnabled()) {
249                 return false;
250             }
251             if (isOkToLoad() && loadHandler()) {
252                 return handler.isEnabled();
253             }
254
255             return true;
256         }
257
258         /*
259          * There is no enabled when expression, so we just need to consult the
260          * handler.
261          */

262         if (isOkToLoad() && loadHandler()) {
263             return handler.isEnabled();
264         }
265         return true;
266     }
267
268     public final boolean isHandled() {
269         if (configurationElement != null) {
270             return true;
271         }
272
273         if (isOkToLoad() && loadHandler()) {
274             return handler.isHandled();
275         }
276
277         return false;
278     }
279
280     /**
281      * Loads the handler, if possible. If the handler is loaded, then the member
282      * variables are updated accordingly.
283      *
284      * @return <code>true</code> if the handler is now non-null;
285      * <code>false</code> otherwise.
286      */

287     private final boolean loadHandler() {
288         if (handler == null) {
289             // Load the handler.
290
try {
291                 if (configurationElement != null) {
292                     handler = (IHandler) configurationElement
293                             .createExecutableExtension(handlerAttributeName);
294                     configurationElement = null;
295                     handler.addHandlerListener(getHandlerListener());
296                     return true;
297                 }
298
299             } catch (final ClassCastException JavaDoc e) {
300                 final String JavaDoc message = "The proxied handler was the wrong class"; //$NON-NLS-1$
301
final IStatus status = new Status(IStatus.ERROR,
302                         WorkbenchPlugin.PI_WORKBENCH, 0, message, e);
303                 WorkbenchPlugin.log(message, status);
304                 configurationElement = null;
305
306             } catch (final CoreException e) {
307                 final String JavaDoc message = "The proxied handler for '" + configurationElement.getAttribute(handlerAttributeName) //$NON-NLS-1$
308
+ "' could not be loaded"; //$NON-NLS-1$
309
IStatus status = new Status(IStatus.ERROR,
310                         WorkbenchPlugin.PI_WORKBENCH, 0, message, e);
311                 WorkbenchPlugin.log(message, status);
312                 configurationElement = null;
313             }
314             return false;
315         }
316
317         return true;
318     }
319
320     /**
321      * @return
322      */

323     private IHandlerListener getHandlerListener() {
324         if (handlerListener == null) {
325             handlerListener = new IHandlerListener() {
326                 public void handlerChanged(HandlerEvent handlerEvent) {
327                     fireHandlerChanged(new HandlerEvent(HandlerProxy.this,
328                             handlerEvent.isEnabledChanged(), handlerEvent
329                                     .isHandledChanged()));
330                 }
331             };
332         }
333         return handlerListener;
334     }
335
336     public final String JavaDoc toString() {
337         if (handler == null) {
338             if (configurationElement != null) {
339                 return configurationElement.getAttribute(handlerAttributeName);
340             }
341             return "HandlerProxy()"; //$NON-NLS-1$
342
}
343
344         return handler.toString();
345     }
346
347     private boolean isOkToLoad() {
348         if (configurationElement != null) {
349             final String JavaDoc bundleId = configurationElement.getContributor()
350                     .getName();
351             return BundleUtility.isActive(bundleId);
352         }
353         return true;
354     }
355
356     /*
357      * (non-Javadoc)
358      *
359      * @see org.eclipse.ui.commands.IElementUpdater#updateElement(org.eclipse.ui.menus.UIElement,
360      * java.util.Map)
361      */

362     public void updateElement(UIElement element, Map JavaDoc parameters) {
363         if (handler != null && handler instanceof IElementUpdater) {
364             ((IElementUpdater) handler).updateElement(element, parameters);
365         }
366     }
367 }
368
Popular Tags