Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.application;
027
028import java.security.AccessController;
029import java.security.PrivilegedAction;
030
031/**
032 * Class that is extended to define an optional preloader for a
033 * JavaFX Application.
034 * An application may contain a preloader that is used
035 * to improve the application loading experience, especially for applications
036 * that are embedded in a browser or launched in webstart execution mode.
037 *
038 * <p>
039 * A preloader is a small application that is started
040 * before the main application to customize the startup experience.
041 * The preloader:
042 * </p>
043 * <ul>
044 * <li>gets notification of progress of loading application resources</li>
045 * <li>gets notification of errors</li>
046 * <li>gets notification of application initialization and startup</li>
047 * <li>decides when application should become visible</li>
048 * </ul>
049 *
050 * <p>
051 * The default preloader is shown on top of the application Stage, which is not
052 * visible until the preloader is visible. The preloader need to hide itself
053 * to make the application visible. Good practice is to do this no earlier than
054 * right before application.start() is called, as otherwise application itself
055 * is not visible.
056 * </p>
057 *
058 * <p>
059 * The preloader may also cooperate with the application to achieve advanced
060 * visual effects or share data (e.g. to implement login screen).
061 * The preloader gets a reference to the application and may pull data it
062 * needs for cooperation from the application if the application implements
063 * an interface that the preloader knows about and relies upon. Generally it
064 * is not recommended to design preloaders in such a way that an application
065 * would call them directly, as this will result in bad user experience if
066 * the application is signed and the preloader is not.
067 * </p>
068 *
069 * <p>
070 * If the application does not specify a preloader, then the default preloader
071 * is used. Default preloader appearance can be customized
072 * (set of parameters is TBD).
073 * </p>
074 *
075 * <p>
076 * Custom preloader implementations should follow these rules:
077 * </p>
078 * <ol>
079 *  <li>there should be class extending Preloader</li>
080 *  <li>classes needed for preloader need to be packaged in the separate jar.
081 *      We recommend this jar to be unsigned.</li>
082 *  <li>JNLP deployment descriptor should have preloader-class attribute
083 *      with full name of the class as value in the javafx-desc element
084 *      and jars needed for progress need to have download="progress" type</li>
085 * </ol>
086 *
087 * <p>
088 * Applications may also send custom notification to the preloader using the
089 * notifyCurrentPreloader() method. This way a preloader may also show
090 * application initialization progress.
091 * </p>
092 *
093 * <p>
094 * Note that preloaders are subject to the same rules as other JavaFX
095 * applications including FX threading rules. In particular, the class
096 * constructor and init() method will be called on a non-FX thread and start()
097 * will be executed on the FX application thread.
098 * This also means that the application constructor/init() will run concurrently
099 * with preloader start().
100 * </p>
101 *
102 * <p>
103 * Callbacks on preloader notification will be delivered on the FX
104 * application thread.
105 * </p>
106 *
107 * <p>
108 * Shutdown (including when stop() is called) is TBD.
109 * </p>
110 */
111public abstract class Preloader extends Application {
112
113    // Too bad this isn't already available in a Java core class
114    private static final String lineSeparator;
115
116    static {
117        String prop = AccessController.doPrivileged(new PrivilegedAction<String>() {
118            @Override public String run() {
119                return System.getProperty("line.separator");
120            }
121        });
122        lineSeparator = prop != null ? prop : "\n";
123    }
124
125    /**
126     * Indicates progress.
127     *
128     * <p>
129     * The implementation of this method provided by the Preloader class
130     * does nothing.
131     * </p>
132     *
133     * @param info the progress notification
134     */
135    public void handleProgressNotification(ProgressNotification info) {
136    }
137
138    /**
139     * Indicates a change in application state.
140     *
141     * <p>
142     * The implementation of this method provided by the Preloader class
143     * does nothing.
144     * </p>
145     *
146     * @param info the state change notification
147     */
148    public void handleStateChangeNotification(StateChangeNotification info) {
149    }
150
151    /**
152     * Indicates an application-generated notification.
153     * Application should not call this method directly, but should use
154     * notifyCurrentPreloader() instead to avoid mixed code dialog issues.
155     *
156     * <p>
157     * The implementation of this method provided by the Preloader class
158     * does nothing.
159     * </p>
160     *
161     * @param info the application-generated notification
162     */
163    public void handleApplicationNotification(PreloaderNotification info) {
164    }
165
166    /**
167     * Called when an error occurs.
168     *
169     * <p>
170     * The implementation of this method provided by the Preloader class
171     * returns false, indicating that the default error handler should
172     * show the message to the user.
173     * </p>
174     *
175     * @param info the error notification describing the cause of this error
176     *
177     * @return true if error was shown to the user by preloader and no
178     * additional visualization is needed; otherwise, false.
179     */
180    public boolean handleErrorNotification(ErrorNotification info) {
181        return false;
182    }
183
184//    /**
185//     * Called when security or other system modal dialog is shown or hidden
186//     * (such as proxy auth dialog).
187//     *
188//     * <p>
189//     * The implementation of this method provided by the Preloader class
190//     * does nothing.
191//     * </p>
192//     *
193//     * @param info the UI notification
194//     */
195//    public void handleUINotification(UINotification info) {
196//        // TODO RT-19601: not used for now pending completion of JRE work
197////        System.err.println("Preloader: handleUINotification = " + info);
198//    }
199
200    // ------------------------------------------------------------------------
201
202    /**
203     * Marker interface for all Preloader notification.
204     */
205    public static interface PreloaderNotification {
206    }
207
208    /**
209     * Preloader notification that reports an error.
210     * This is delivered to preloader in case of problem with applet startup.
211     */
212    public static class ErrorNotification implements PreloaderNotification {
213        private String location;
214        private String details = "";
215        private Throwable cause;
216
217        /**
218         * Constructs an error notification.
219         *
220         * @param location the URL associated with an error (if any); may be null
221         * @param details a string describing the error; must be non-null
222         * @param cause the cause of the error; may be null
223         */
224        public ErrorNotification(String location, String details, Throwable cause) {
225            if (details == null) throw new NullPointerException();
226
227            this.location = location;
228            this.details = details;
229            this.cause = cause;
230        }
231
232        /**
233         * Retrieves the URL associated with this error, if any.
234         * For example, if there is a download or singing check error, this
235         * will be the URL of the jar file that has the problem.
236         * It may be null.
237         *
238         * @return the location, or null
239         */
240        public String getLocation() {
241            return location;
242        }
243
244        /**
245         * Retrieves the description of the error.
246         * It may be the empty string, but is always non-null.
247         *
248         * @return the description of the error
249         */
250        public String getDetails() {
251            return details;
252        }
253
254        /**
255         * Retrieves the Exception or Error associated with this error
256         * notification, if any. It may be null.
257         *
258         * @return the cause of the error, or null
259         */
260        public Throwable getCause() {
261            return cause;
262        }
263
264        /**
265         * Returns a string representation of this {@code ErrorNotification} object.
266         * @return a string representation of this {@code ErrorNotification} object.
267         */ 
268        @Override public String toString() {
269            StringBuilder str = new StringBuilder("Preloader.ErrorNotification: ");
270            str.append(details);
271            if (cause != null) {
272                str.append(lineSeparator).append("Caused by: ").append(cause.toString());
273            }
274            if (location != null) {
275                str.append(lineSeparator).append("Location: ").append(location);
276            }
277            return str.toString();
278        }
279    }
280
281    /**
282     * Preloader notification that reports progress. This is typically used to
283     * report progress while downloading and initializing the application.
284     */
285    public static class ProgressNotification implements PreloaderNotification {
286        private final double progress;
287        private final String details;
288
289        /**
290         * Constructs a progress notification.
291         *
292         * @param progress a value indicating the progress.
293         * A negative value for progress indicates that the progress is
294         * indeterminate. A value between 0 and 1 indicates the amount
295         * of progress. Any value greater than 1 is interpreted as 1.
296         */
297        public ProgressNotification(double progress) {
298            this(progress, "");
299        }
300
301        // NOTE: We could consider exposing details in the future, but currently
302        // have no plan to do so. This method is private for now.
303        /**
304         * Constructs a progress notification.
305         *
306         * @param progress a value indicating the progress.
307         * A negative value for progress indicates that the progress is
308         * indeterminate. A value between 0 and 1 indicates the amount
309         * of progress. Any value greater than 1 is interpreted as 1.
310         *
311         * @param details the details of this notification
312         */
313        private ProgressNotification(double progress, String details) {
314            this.progress = progress;
315            this.details = details;
316        }
317
318        /**
319         * Retrieves the progress for this notification. Progress is in the
320         * range of 0 to 1, or is negative for indeterminate progress.
321         *
322         * @return the progress
323         */
324        public double getProgress() {
325            return progress;
326        }
327
328        /**
329         * Retrieves the details of the progress notification
330         *
331         * @return the details of this notification
332         */
333        private String getDetails() {
334            return details;
335        }
336    }
337
338    /**
339     * A notification that signals a change in the application state.
340     * A state change notification is sent to a preloader immediately prior
341     * to loading
342     * the application class (and constructing an instance), calling the
343     * application init method, or calling the application start method.
344     */
345    public static class StateChangeNotification implements PreloaderNotification {
346
347        /**
348         * Enum that defines the type of change associated with this notification
349         */
350        public enum Type {
351            /**
352             * Indicates that the application class is about to be loaded and
353             * constructed.
354             */
355            BEFORE_LOAD,
356
357            /**
358             * Indicates that the application's init method is about to be called.
359             */
360            BEFORE_INIT,
361
362            /**
363             * Indicates that the application's start method is about to be called.
364             */
365            BEFORE_START
366        }
367
368        private final Type notificationType;
369        private final Application application;
370
371        /**
372         * Constructs a StateChangeNotification of the specified type.
373         *
374         * @param notificationType the type of this notification.
375         */
376        public StateChangeNotification(Type notificationType){
377            this.notificationType = notificationType;
378            this.application = null;
379        }
380
381        /**
382         * Constructs an StateChangeNotification of the specified type for the
383         * specified application.
384         *
385         * @param notificationType the type of this notification.
386         * @param application the application instance associated with this
387         * notification.
388         */
389        public StateChangeNotification(Type notificationType, Application application) {
390            this.notificationType = notificationType;
391            this.application = application;
392        }
393
394        /**
395         * Returns the type of notification.
396         *
397         * @return one of: BEFORE_LOAD, BEFORE_INIT, BEFORE_START
398         */
399        public Type getType() {
400            return notificationType;
401        }
402
403        /**
404         * Returns the Application instance associated with this notification.
405         * This is null for a BEFORE_LOAD notification and non-null for other
406         * notification types.
407         *
408         * @return the Application instance or null.
409         */
410        public Application getApplication() {
411            return application;
412        }
413    }
414
415//    /**
416//     * Used to signal about global modal dialogs to be shown that block
417//     * application launch. In particular proxy and security dialogs
418//     */
419//    public static class UINotification implements PreloaderNotification {
420//       //TODO RT-19601: implementation pending JRE work
421//    }
422
423}