KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > osgi > service > application > ApplicationDescriptor


1 /*
2  * $Header: /cvsroot/eclipse/org.eclipse.equinox.app/src/org/osgi/service/application/ApplicationDescriptor.java,v 1.7 2006/09/15 14:46:00 twatson Exp $
3  *
4  * Copyright (c) OSGi Alliance (2004, 2006). All Rights Reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */

18
19 package org.osgi.service.application;
20
21 import java.util.Iterator JavaDoc;
22 import java.util.Map JavaDoc;
23 import org.eclipse.equinox.internal.app.AppPersistence;
24 import org.osgi.framework.Constants;
25 import org.osgi.framework.InvalidSyntaxException;
26
27 /**
28  * An OSGi service that represents an installed application and stores
29  * information about it. The application descriptor can be used for instance
30  * creation.
31  */

32
33 public abstract class ApplicationDescriptor {
34     /*
35      * NOTE: An implementor may also choose to replace this class in
36      * their distribution with a class that directly interfaces with the
37      * org.osgi.service.application implementation. This replacement class MUST NOT alter the
38      * public/protected signature of this class.
39      */

40
41     /**
42      * The property key for the localized name of the application.
43      */

44     public static final String JavaDoc APPLICATION_NAME = "application.name";
45
46     /**
47      * The property key for the localized icon of the application.
48      */

49     public static final String JavaDoc APPLICATION_ICON = "application.icon";
50
51     /**
52      * The property key for the unique identifier (PID) of the application.
53      */

54     public static final String JavaDoc APPLICATION_PID = Constants.SERVICE_PID;
55
56     /**
57      * The property key for the version of the application.
58      */

59     public static final String JavaDoc APPLICATION_VERSION = "application.version";
60
61     /**
62      * The property key for the name of the application vendor.
63      */

64     public static final String JavaDoc APPLICATION_VENDOR = Constants.SERVICE_VENDOR;
65
66
67     /**
68      * The property key for the visibility property of the application.
69      */

70     public static final String JavaDoc APPLICATION_VISIBLE = "application.visible";
71
72     /**
73      * The property key for the launchable property of the application.
74      */

75     public static final String JavaDoc APPLICATION_LAUNCHABLE = "application.launchable";
76
77     /**
78      * The property key for the locked property of the application.
79      */

80     public static final String JavaDoc APPLICATION_LOCKED = "application.locked";
81
82     /**
83      * The property key for the localized description of the application.
84      */

85     public static final String JavaDoc APPLICATION_DESCRIPTION = "application.description";
86
87     /**
88      * The property key for the localized documentation of the application.
89      */

90     public static final String JavaDoc APPLICATION_DOCUMENTATION = "application.documentation";
91
92     /**
93      * The property key for the localized copyright notice of the application.
94      */

95     public static final String JavaDoc APPLICATION_COPYRIGHT = "application.copyright";
96
97     /**
98      * The property key for the localized license of the application.
99      */

100     public static final String JavaDoc APPLICATION_LICENSE = "application.license";
101
102     /**
103      * The property key for the application container of the application.
104      */

105     public static final String JavaDoc APPLICATION_CONTAINER = "application.container";
106
107     /**
108      * The property key for the location of the application.
109      */

110     public static final String JavaDoc APPLICATION_LOCATION = "application.location";
111
112     
113     private final String JavaDoc pid;
114
115     private boolean[] locked = {false};
116
117     /**
118      * Constructs the <code>ApplicationDescriptor</code>.
119      *
120      * @param applicationId
121      * The identifier of the application. Its value is also available
122      * as the <code>service.pid</code> service property of this
123      * <code>ApplicationDescriptor</code> service. This parameter must not
124      * be <code>null</code>.
125      * @throws NullPointerException if the specified <code>applicationId</code> is null.
126      */

127     protected ApplicationDescriptor(String JavaDoc applicationId) {
128         if(null == applicationId ) {
129             throw new NullPointerException JavaDoc("Application ID must not be null!");
130         }
131         
132         this.pid = applicationId;
133         locked[0] = isLocked();
134     }
135
136     /**
137      * Returns the identifier of the represented application.
138      *
139      * @return the identifier of the represented application
140      */

141     public final String JavaDoc getApplicationId() {
142         return pid;
143     }
144
145     /**
146      * This method verifies whether the specified <code>pattern</code>
147      * matches the Distinguished Names of any of the certificate chains
148      * used to authenticate this application.
149      * <P>
150      * The <code>pattern</code> must adhere to the
151      * syntax defined in {@link org.osgi.service.application.ApplicationAdminPermission}
152      * for signer attributes.
153      * <p>
154      * This method is used by {@link ApplicationAdminPermission#implies(java.security.Permission)} method
155      * to match target <code>ApplicationDescriptor</code> and filter.
156      *
157      * @param pattern a pattern for a chain of Distinguished Names. It must not be null.
158      * @return <code>true</code> if the specified pattern matches at least
159      * one of the certificate chains used to authenticate this application
160      * @throws NullPointerException if the specified <code>pattern</code> is null.
161      * @throws IllegalStateException if the application descriptor was
162      * unregistered
163      */

164     public abstract boolean matchDNChain( String JavaDoc pattern );
165     
166     /**
167      * Returns the properties of the application descriptor as key-value pairs.
168      * The return value contains the locale aware and unaware properties as
169      * well. The returned <code>Map</code> will include the service
170      * properties of this <code>ApplicationDescriptor</code> as well.
171      * <p>
172      * This method will call the <code>getPropertiesSpecific</code> method
173      * to enable the container implementation to insert application model and/or
174      * container implementation specific properties.
175      * <P>
176      * The returned {@link java.util.Map} will contain the standard OSGi service
177      * properties as well
178      * (e.g. service.id, service.vendor etc.) and specialized application
179      * descriptors may offer further service properties. The returned Map contains
180      * a snapshot of the properties. It will not reflect further changes in the
181      * property values nor will the update of the Map change the corresponding
182      * service property.
183      *
184      * @param locale
185      * the locale string, it may be null, the value null means the
186      * default locale. If the provided locale is the empty String
187      * (<code>""</code>)then raw (non-localized) values are returned.
188      *
189      * @return copy of the service properties of this application descriptor service,
190      * according to the specified locale. If locale is null then the
191      * default locale's properties will be returned. (Since service
192      * properties are always exist it cannot return null.)
193      *
194      * @throws IllegalStateException
195      * if the application descriptor is unregistered
196      */

197     public final Map JavaDoc getProperties(String JavaDoc locale) {
198         Map JavaDoc props = getPropertiesSpecific( locale );
199         Boolean JavaDoc containerLocked = (Boolean JavaDoc) props.remove( APPLICATION_LOCKED );
200         synchronized (locked) {
201             if (containerLocked != null && containerLocked.booleanValue() != locked[0]) {
202                 if (locked[0])
203                     lockSpecific();
204                 else
205                     unlockSpecific();
206             }
207         }
208         props.put( APPLICATION_LOCKED, new Boolean JavaDoc( locked[0] ) );
209         return props;
210     }
211     
212     /**
213      * Container implementations can provide application model specific
214      * and/or container implementation specific properties via this
215      * method.
216      *
217      * Localizable properties must be returned localized if the provided
218      * <code>locale</code> argument is not the empty String. The value
219      * <code>null</code> indicates to use the default locale, for other
220      * values the specified locale should be used.
221      *
222      * The returned {@link java.util.Map} must contain the standard OSGi service
223      * properties as well
224      * (e.g. service.id, service.vendor etc.) and specialized application
225      * descriptors may offer further service properties.
226      * The returned <code>Map</code>
227      * contains a snapshot of the properties. It will not reflect further changes in the
228      * property values nor will the update of the Map change the corresponding
229      * service property.
230
231      * @param locale the locale to be used for localizing the properties.
232      * If <code>null</code> the default locale should be used. If it is
233      * the empty String (<code>""</code>) then raw (non-localized) values
234      * should be returned.
235      *
236      * @return the application model specific and/or container implementation
237      * specific properties of this application descriptor.
238      *
239      * @throws IllegalStateException
240      * if the application descriptor is unregistered
241      */

242     protected abstract Map JavaDoc getPropertiesSpecific(String JavaDoc locale);
243
244     /**
245      * Launches a new instance of an application. The <code>args</code> parameter specifies
246      * the startup parameters for the instance to be launched, it may be null.
247      * <p>
248      * The following steps are made:
249      * <UL>
250      * <LI>Check for the appropriate permission.
251      * <LI>Check the locking state of the application. If locked then return
252      * null otherwise continue.
253      * <LI>Calls the <code>launchSpecific()</code> method to create and start an application
254      * instance.
255      * <LI>Returns the <code>ApplicationHandle</code> returned by the
256      * launchSpecific()
257      * </UL>
258      * The caller has to have ApplicationAdminPermission(applicationPID,
259      * "launch") in order to be able to perform this operation.
260      * <P>
261      * The <code>Map</code> argument of the launch method contains startup
262      * arguments for the
263      * application. The keys used in the Map must be non-null, non-empty <code>String<code>
264      * objects. They can be standard or application
265      * specific. OSGi defines the <code>org.osgi.triggeringevent</code>
266      * key to be used to
267      * pass the triggering event to a scheduled application, however
268      * in the future it is possible that other well-known keys will be defined.
269      * To avoid unwanted clashes of keys, the following rules should be applied:
270      * <ul>
271      * <li>The keys starting with the dash (-) character are application
272      * specific, no well-known meaning should be associated with them.</li>
273      * <li>Well-known keys should follow the reverse domain name based naming.
274      * In particular, the keys standardized in OSGi should start with
275      * <code>org.osgi.</code>.</li>
276      * </ul>
277      * <P>
278      * The method is synchonous, it return only when the application instance was
279      * successfully started or the attempt to start it failed.
280      * <P>
281      * This method never returns <code>null</code>. If launching an application fails,
282      * the appropriate exception is thrown.
283      *
284      * @param arguments
285      * Arguments for the newly launched application, may be null
286      *
287      * @return the registered ApplicationHandle, which represents the newly
288      * launched application instance. Never returns <code>null</code>.
289      *
290      * @throws SecurityException
291      * if the caller doesn't have "lifecycle"
292      * ApplicationAdminPermission for the application.
293      * @throws ApplicationException
294      * if starting the application failed
295      * @throws IllegalStateException
296      * if the application descriptor is unregistered
297      * @throws IllegalArgumentException
298      * if the specified <code>Map</code> contains invalid keys
299      * (null objects, empty <code>String</code> or a key that is not
300      * <code>String</code>)
301      */

302     public final ApplicationHandle launch(Map JavaDoc arguments)
303             throws ApplicationException {
304         SecurityManager JavaDoc sm = System.getSecurityManager();
305         if (sm!= null)
306             sm.checkPermission(new ApplicationAdminPermission(this, ApplicationAdminPermission.LIFECYCLE_ACTION));
307         synchronized (locked) {
308             if (locked[0])
309                 throw new ApplicationException(ApplicationException.APPLICATION_LOCKED, "Application is locked, can't launch!");
310         }
311         if( !isLaunchableSpecific() )
312             throw new ApplicationException(ApplicationException.APPLICATION_NOT_LAUNCHABLE,
313                      "Cannot launch the application!");
314         checkArgs(arguments);
315         try {
316             return launchSpecific(arguments);
317         } catch(IllegalStateException JavaDoc ise) {
318             throw ise;
319         } catch(SecurityException JavaDoc se) {
320             throw se;
321         } catch( ApplicationException ae) {
322             throw ae;
323         } catch(Exception JavaDoc t) {
324             throw new ApplicationException(ApplicationException.APPLICATION_INTERNAL_ERROR, t);
325         }
326     }
327
328     /**
329      * Called by launch() to create and start a new instance in an application
330      * model specific way. It also creates and registeres the application handle
331      * to represent the newly created and started instance and registeres it.
332      * The method is synchonous, it return only when the application instance was
333      * successfully started or the attempt to start it failed.
334      * <P>
335      * This method must not return <code>null</code>. If launching the application
336      * failed, and exception must be thrown.
337      *
338      * @param arguments
339      * the startup parameters of the new application instance, may be
340      * null
341      *
342      * @return the registered application model
343      * specific application handle for the newly created and started
344      * instance.
345      *
346      * @throws IllegalStateException
347      * if the application descriptor is unregistered
348      * @throws Exception
349      * if any problem occures.
350      */

351     protected abstract ApplicationHandle launchSpecific(Map JavaDoc arguments)
352             throws Exception JavaDoc;
353     
354     /**
355      * This method is called by launch() to verify that according to the
356      * container, the application is launchable.
357      *
358      * @return true, if the application is launchable according to the
359      * container, false otherwise.
360      *
361      * @throws IllegalStateException
362      * if the application descriptor is unregistered
363      */

364     protected abstract boolean isLaunchableSpecific();
365
366     /**
367      * Schedules the application at a specified event. Schedule information
368      * should not get lost even if the framework or the device restarts so it
369      * should be stored in a persistent storage. The method registers a
370      * {@link ScheduledApplication} service in Service Registry, representing
371      * the created schedule.
372      * <p>
373      * The <code>Map</code> argument of the method contains startup
374      * arguments for the application. The keys used in the Map must be non-null,
375      * non-empty <code>String<code> objects.
376      * <p>
377      * The created schedules have a unique identifier within the scope of this
378      * <code>ApplicationDescriptor</code>. This identifier can be specified
379      * in the <code>scheduleId</code> argument. If this argument is <code>null</code>,
380      * the identifier is automatically generated.
381      *
382      * @param scheduleId
383      * the identifier of the created schedule. It can be <code>null</code>,
384      * in this case the identifier is automatically generated.
385      * @param arguments
386      * the startup arguments for the scheduled application, may be
387      * null
388      * @param topic
389      * specifies the topic of the triggering event, it may contain a
390      * trailing asterisk as wildcard, the empty string is treated as
391      * "*", must not be null
392      * @param eventFilter
393      * specifies and LDAP filter to filter on the properties of the
394      * triggering event, may be null
395      * @param recurring
396      * if the recurring parameter is false then the application will
397      * be launched only once, when the event firstly occurs. If the
398      * parameter is true then scheduling will take place for every
399      * event occurrence; i.e. it is a recurring schedule
400      *
401      * @return the registered scheduled application service
402      *
403      * @throws NullPointerException
404      * if the topic is <code>null</code>
405      * @throws InvalidSyntaxException
406      * if the specified <code>eventFilter</code> is not syntactically correct
407      * @throws ApplicationException
408      * if the schedule couldn't be created. The possible error
409      * codes are
410      * <ul>
411      * <li> {@link ApplicationException#APPLICATION_DUPLICATE_SCHEDULE_ID}
412      * if the specified <code>scheduleId</code> is already used
413      * for this <code>ApplicationDescriptor</code>
414      * <li> {@link ApplicationException#APPLICATION_SCHEDULING_FAILED}
415      * if the scheduling failed due to some internal reason
416      * (e.g. persistent storage error).
417      * </ul>
418      * @throws SecurityException
419      * if the caller doesn't have "schedule"
420      * ApplicationAdminPermission for the application.
421      * @throws IllegalStateException
422      * if the application descriptor is unregistered
423      * @throws IllegalArgumentException
424      * if the specified <code>Map</code> contains invalid keys
425      * (null objects, empty <code>String</code> or a key that is not
426      * <code>String</code>)
427      */

428     public final ScheduledApplication schedule(String JavaDoc scheduleId, Map JavaDoc arguments, String JavaDoc topic,
429             String JavaDoc eventFilter, boolean recurring) throws InvalidSyntaxException,
430             ApplicationException {
431         SecurityManager JavaDoc sm = System.getSecurityManager();
432         if (sm != null)
433             sm.checkPermission(new ApplicationAdminPermission(this, ApplicationAdminPermission.SCHEDULE_ACTION));
434         checkArgs(arguments);
435         isLaunchableSpecific(); // checks if the ApplicationDescriptor was already unregistered
436
return AppPersistence.addScheduledApp(this, scheduleId, arguments, topic, eventFilter, recurring);
437     }
438
439     /**
440      * Sets the lock state of the application. If an application is locked then
441      * launching a new instance is not possible. It does not affect the already
442      * launched instances.
443      *
444      * @throws SecurityException
445      * if the caller doesn't have "lock" ApplicationAdminPermission
446      * for the application.
447      * @throws IllegalStateException
448      * if the application descriptor is unregistered
449      */

450     public final void lock() {
451         SecurityManager JavaDoc sm = System.getSecurityManager();
452         if (sm != null)
453             sm.checkPermission(new ApplicationAdminPermission(this, ApplicationAdminPermission.LOCK_ACTION));
454         synchronized (locked) {
455             if (locked[0])
456                 return;
457             locked[0] = true;
458             lockSpecific();
459             saveLock(true);
460         }
461     }
462     
463     /**
464      * This method is used to notify the container implementation that the
465      * corresponding application has been locked and it should update the
466      * <code>application.locked</code> service property accordingly.
467      * @throws IllegalStateException
468      * if the application descriptor is unregistered
469      */

470     protected abstract void lockSpecific();
471
472     /**
473      * Unsets the lock state of the application.
474      *
475      * @throws SecurityException
476      * if the caller doesn't have "lock" ApplicationAdminPermission
477      * for the application.
478      * @throws IllegalStateException
479      * if the application descriptor is unregistered
480      */

481     public final void unlock() {
482         SecurityManager JavaDoc sm = System.getSecurityManager();
483         if (sm != null)
484             sm.checkPermission(new ApplicationAdminPermission(this, ApplicationAdminPermission.LOCK_ACTION));
485         synchronized (locked) {
486             if (!locked[0])
487                 return;
488             locked[0] = false;
489             unlockSpecific();
490             saveLock(false);
491         }
492     }
493     
494     /**
495      * This method is used to notify the container implementation that the
496      * corresponding application has been unlocked and it should update the
497      * <code>application.locked</code> service property accordingly.
498
499      * @throws IllegalStateException
500      * if the application descriptor is unregistered
501      */

502     protected abstract void unlockSpecific();
503
504     private void saveLock(boolean locked) {
505         AppPersistence.saveLock(this, locked);
506     }
507
508     private boolean isLocked() {
509         return AppPersistence.isLocked(this);
510     }
511
512     private void checkArgs(Map JavaDoc arguments) {
513         if (arguments == null)
514             return;
515         for (Iterator JavaDoc keys = arguments.keySet().iterator(); keys.hasNext();) {
516             Object JavaDoc key = keys.next();
517             if (!(key instanceof String JavaDoc))
518                 throw new IllegalArgumentException JavaDoc("Invalid key type: " + key == null ? "<null>" : key.getClass().getName());
519             if ("".equals(key)) //$NON-NLS-1$
520
throw new IllegalArgumentException JavaDoc("Empty string is an invalid key");
521         }
522     }
523
524
525 }
Popular Tags