source: josm/trunk/src/org/openstreetmap/josm/Main.java@ 14134

Last change on this file since 14134 was 14134, checked in by Don-vip, 6 years ago

see #15229 - deprecate Main*.undoRedo - make UndoRedoHandler a singleton

  • Property svn:eol-style set to native
File size: 17.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.Component;
7import java.io.IOException;
8import java.net.URL;
9import java.nio.file.InvalidPathException;
10import java.util.Collection;
11import java.util.Collections;
12import java.util.List;
13import java.util.Map;
14import java.util.Set;
15import java.util.concurrent.Callable;
16import java.util.concurrent.ExecutionException;
17import java.util.concurrent.ExecutorService;
18import java.util.concurrent.Executors;
19import java.util.concurrent.Future;
20
21import org.openstreetmap.josm.data.Preferences;
22import org.openstreetmap.josm.data.UndoRedoHandler;
23import org.openstreetmap.josm.data.coor.conversion.CoordinateFormatManager;
24import org.openstreetmap.josm.data.coor.conversion.DecimalDegreesCoordinateFormat;
25import org.openstreetmap.josm.data.coor.conversion.ICoordinateFormat;
26import org.openstreetmap.josm.data.osm.DataSet;
27import org.openstreetmap.josm.data.osm.IPrimitive;
28import org.openstreetmap.josm.data.osm.OsmData;
29import org.openstreetmap.josm.data.osm.OsmPrimitive;
30import org.openstreetmap.josm.data.preferences.JosmBaseDirectories;
31import org.openstreetmap.josm.data.projection.Projection;
32import org.openstreetmap.josm.data.projection.ProjectionChangeListener;
33import org.openstreetmap.josm.data.projection.ProjectionRegistry;
34import org.openstreetmap.josm.io.FileWatcher;
35import org.openstreetmap.josm.io.NetworkManager;
36import org.openstreetmap.josm.io.OnlineResource;
37import org.openstreetmap.josm.spi.lifecycle.InitializationTask;
38import org.openstreetmap.josm.spi.preferences.Config;
39import org.openstreetmap.josm.spi.preferences.IUrls;
40import org.openstreetmap.josm.tools.ImageProvider;
41import org.openstreetmap.josm.tools.JosmRuntimeException;
42import org.openstreetmap.josm.tools.Logging;
43import org.openstreetmap.josm.tools.Platform;
44import org.openstreetmap.josm.tools.PlatformHook;
45import org.openstreetmap.josm.tools.PlatformHookOsx;
46import org.openstreetmap.josm.tools.PlatformHookWindows;
47import org.openstreetmap.josm.tools.Utils;
48import org.openstreetmap.josm.tools.bugreport.BugReport;
49
50/**
51 * Abstract class holding various static global variables and methods used in large parts of JOSM application.
52 * @since 98
53 */
54public abstract class Main {
55
56 /**
57 * Global parent component for all dialogs and message boxes
58 */
59 public static Component parent;
60
61 /**
62 * Global application.
63 */
64 public static volatile Main main;
65
66 /**
67 * Global application preferences
68 */
69 public static final Preferences pref = new Preferences(JosmBaseDirectories.getInstance());
70
71 /**
72 * The commands undo/redo handler.
73 * @deprecated Use {@link UndoRedoHandler#getInstance}
74 */
75 @Deprecated
76 public final UndoRedoHandler undoRedo = UndoRedoHandler.getInstance();
77
78 /**
79 * The file watcher service.
80 * @deprecated Use {@link FileWatcher#getDefaultInstance}
81 */
82 @Deprecated
83 public static final FileWatcher fileWatcher = FileWatcher.getDefaultInstance();
84
85 /**
86 * Platform specific code goes in here.
87 * Plugins may replace it, however, some hooks will be called before any plugins have been loaded.
88 * So if you need to hook into those early ones, split your class and send the one with the early hooks
89 * to the JOSM team for inclusion.
90 */
91 public static volatile PlatformHook platform;
92
93 /**
94 * Constructs new {@code Main} object.
95 * @see #initialize()
96 */
97 protected Main() {
98 setInstance(this);
99 }
100
101 private static void setInstance(Main instance) {
102 main = instance;
103 }
104
105 /**
106 * Initializes the main object. A lot of global variables are initialized here.
107 * @since 10340
108 */
109 public void initialize() {
110 // Initializes tasks that must be run before parallel tasks
111 runInitializationTasks(beforeInitializationTasks());
112
113 // Initializes tasks to be executed (in parallel) by a ExecutorService
114 try {
115 ExecutorService service = Executors.newFixedThreadPool(
116 Runtime.getRuntime().availableProcessors(), Utils.newThreadFactory("main-init-%d", Thread.NORM_PRIORITY));
117 for (Future<Void> i : service.invokeAll(parallelInitializationTasks())) {
118 i.get();
119 }
120 // asynchronous initializations to be completed eventually
121 asynchronousRunnableTasks().forEach(service::submit);
122 asynchronousCallableTasks().forEach(service::submit);
123 try {
124 service.shutdown();
125 } catch (SecurityException e) {
126 Logging.log(Logging.LEVEL_ERROR, "Unable to shutdown executor service", e);
127 }
128 } catch (InterruptedException | ExecutionException ex) {
129 throw new JosmRuntimeException(ex);
130 }
131
132 // Initializes tasks that must be run after parallel tasks
133 runInitializationTasks(afterInitializationTasks());
134 }
135
136 private static void runInitializationTasks(List<InitializationTask> tasks) {
137 for (InitializationTask task : tasks) {
138 try {
139 task.call();
140 } catch (JosmRuntimeException e) {
141 // Can happen if the current projection needs NTV2 grid which is not available
142 // In this case we want the user be able to change his projection
143 BugReport.intercept(e).warn();
144 }
145 }
146 }
147
148 /**
149 * Returns tasks that must be run before parallel tasks.
150 * @return tasks that must be run before parallel tasks
151 * @see #afterInitializationTasks
152 * @see #parallelInitializationTasks
153 */
154 protected List<InitializationTask> beforeInitializationTasks() {
155 return Collections.emptyList();
156 }
157
158 /**
159 * Returns tasks to be executed (in parallel) by a ExecutorService.
160 * @return tasks to be executed (in parallel) by a ExecutorService
161 */
162 protected Collection<InitializationTask> parallelInitializationTasks() {
163 return Collections.emptyList();
164 }
165
166 /**
167 * Returns asynchronous callable initializations to be completed eventually
168 * @return asynchronous callable initializations to be completed eventually
169 */
170 protected List<Callable<?>> asynchronousCallableTasks() {
171 return Collections.emptyList();
172 }
173
174 /**
175 * Returns asynchronous runnable initializations to be completed eventually
176 * @return asynchronous runnable initializations to be completed eventually
177 */
178 protected List<Runnable> asynchronousRunnableTasks() {
179 return Collections.emptyList();
180 }
181
182 /**
183 * Returns tasks that must be run after parallel tasks.
184 * @return tasks that must be run after parallel tasks
185 * @see #beforeInitializationTasks
186 * @see #parallelInitializationTasks
187 */
188 protected List<InitializationTask> afterInitializationTasks() {
189 return Collections.emptyList();
190 }
191
192 /**
193 * Replies the current selected OSM primitives, from a end-user point of view.
194 * It is not always technically the same collection of primitives than {@link DataSet#getSelected()}.
195 * @return The current selected OSM primitives, from a end-user point of view. Can be {@code null}.
196 * @since 6546
197 */
198 public Collection<OsmPrimitive> getInProgressSelection() {
199 return Collections.emptyList();
200 }
201
202 /**
203 * Replies the current selected primitives, from a end-user point of view.
204 * It is not always technically the same collection of primitives than {@link OsmData#getSelected()}.
205 * @return The current selected primitives, from a end-user point of view. Can be {@code null}.
206 * @since 13926
207 */
208 public Collection<? extends IPrimitive> getInProgressISelection() {
209 return Collections.emptyList();
210 }
211
212 /**
213 * Gets the active edit data set (not read-only).
214 * @return That data set, <code>null</code>.
215 * @see #getActiveDataSet
216 * @since 12691
217 */
218 public abstract DataSet getEditDataSet();
219
220 /**
221 * Gets the active data set (can be read-only).
222 * @return That data set, <code>null</code>.
223 * @see #getEditDataSet
224 * @since 13434
225 */
226 public abstract DataSet getActiveDataSet();
227
228 /**
229 * Sets the active data set (and also edit data set if not read-only).
230 * @param ds New data set, or <code>null</code>
231 * @since 13434
232 */
233 public abstract void setActiveDataSet(DataSet ds);
234
235 /**
236 * Determines if the list of data sets managed by JOSM contains {@code ds}.
237 * @param ds the data set to look for
238 * @return {@code true} if the list of data sets managed by JOSM contains {@code ds}
239 * @since 12718
240 */
241 public abstract boolean containsDataSet(DataSet ds);
242
243 ///////////////////////////////////////////////////////////////////////////
244 // Implementation part
245 ///////////////////////////////////////////////////////////////////////////
246
247 /**
248 * Should be called before the main constructor to setup some parameter stuff
249 */
250 public static void preConstructorInit() {
251 // init default coordinate format
252 ICoordinateFormat fmt = CoordinateFormatManager.getCoordinateFormat(Config.getPref().get("coordinates"));
253 if (fmt == null) {
254 fmt = DecimalDegreesCoordinateFormat.INSTANCE;
255 }
256 CoordinateFormatManager.setCoordinateFormat(fmt);
257 }
258
259 /**
260 * Closes JOSM and optionally terminates the Java Virtual Machine (JVM).
261 * @param exit If {@code true}, the JVM is terminated by running {@link System#exit} with a given return code.
262 * @param exitCode The return code
263 * @return {@code true}
264 * @since 12636
265 */
266 public static boolean exitJosm(boolean exit, int exitCode) {
267 if (Main.main != null) {
268 Main.main.shutdown();
269 }
270
271 if (exit) {
272 System.exit(exitCode);
273 }
274 return true;
275 }
276
277 /**
278 * Shutdown JOSM.
279 */
280 protected void shutdown() {
281 ImageProvider.shutdown(false);
282 try {
283 pref.saveDefaults();
284 } catch (IOException | InvalidPathException ex) {
285 Logging.log(Logging.LEVEL_WARN, tr("Failed to save default preferences."), ex);
286 }
287 ImageProvider.shutdown(true);
288 }
289
290 /**
291 * Identifies the current operating system family and initializes the platform hook accordingly.
292 * @since 1849
293 */
294 public static void determinePlatformHook() {
295 platform = Platform.determinePlatform().accept(PlatformHook.CONSTRUCT_FROM_PLATFORM);
296 }
297
298 /**
299 * Replies the current projection.
300 *
301 * @return the currently active projection
302 * @deprecated Use {@link ProjectionRegistry#getProjection}
303 */
304 @Deprecated
305 public static Projection getProjection() {
306 return ProjectionRegistry.getProjection();
307 }
308
309 /**
310 * Sets the current projection
311 *
312 * @param p the projection
313 * @deprecated Use {@link ProjectionRegistry#setProjection}
314 */
315 @Deprecated
316 public static void setProjection(Projection p) {
317 ProjectionRegistry.setProjection(p);
318 }
319
320 /**
321 * Register a projection change listener.
322 * The listener is registered to be weak, so keep a reference of it if you want it to be preserved.
323 *
324 * @param listener the listener. Ignored if <code>null</code>.
325 * @deprecated Use {@link ProjectionRegistry#addProjectionChangeListener}
326 */
327 @Deprecated
328 public static void addProjectionChangeListener(ProjectionChangeListener listener) {
329 ProjectionRegistry.addProjectionChangeListener(listener);
330 }
331
332 /**
333 * Removes a projection change listener.
334 *
335 * @param listener the listener. Ignored if <code>null</code>.
336 * @deprecated Use {@link ProjectionRegistry#removeProjectionChangeListener}
337 */
338 @Deprecated
339 public static void removeProjectionChangeListener(ProjectionChangeListener listener) {
340 ProjectionRegistry.removeProjectionChangeListener(listener);
341 }
342
343 /**
344 * Remove all projection change listeners. For testing purposes only.
345 * @since 13322
346 * @deprecated Use {@link ProjectionRegistry#clearProjectionChangeListeners}
347 */
348 @Deprecated
349 public static void clearProjectionChangeListeners() {
350 ProjectionRegistry.clearProjectionChangeListeners();
351 }
352
353 /**
354 * Adds a new network error that occur to give a hint about broken Internet connection.
355 * Do not use this method for errors known for sure thrown because of a bad proxy configuration.
356 *
357 * @param url The accessed URL that caused the error
358 * @param t The network error
359 * @return The previous error associated to the given resource, if any. Can be {@code null}
360 * @deprecated Use {@link NetworkManager#addNetworkError(URL, Throwable)}
361 * @since 6642
362 */
363 @Deprecated
364 public static Throwable addNetworkError(URL url, Throwable t) {
365 return NetworkManager.addNetworkError(url, t);
366 }
367
368 /**
369 * Adds a new network error that occur to give a hint about broken Internet connection.
370 * Do not use this method for errors known for sure thrown because of a bad proxy configuration.
371 *
372 * @param url The accessed URL that caused the error
373 * @param t The network error
374 * @return The previous error associated to the given resource, if any. Can be {@code null}
375 * @deprecated Use {@link NetworkManager#addNetworkError(String, Throwable)}
376 * @since 6642
377 */
378 @Deprecated
379 public static Throwable addNetworkError(String url, Throwable t) {
380 return NetworkManager.addNetworkError(url, t);
381 }
382
383 /**
384 * Returns the network errors that occured until now.
385 * @return the network errors that occured until now, indexed by URL
386 * @deprecated Use {@link NetworkManager#getNetworkErrors}
387 * @since 6639
388 */
389 @Deprecated
390 public static Map<String, Throwable> getNetworkErrors() {
391 return NetworkManager.getNetworkErrors();
392 }
393
394 /**
395 * Clears the network errors cache.
396 * @deprecated Use {@link NetworkManager#clearNetworkErrors}
397 * @since 12011
398 */
399 @Deprecated
400 public static void clearNetworkErrors() {
401 NetworkManager.clearNetworkErrors();
402 }
403
404 /**
405 * Returns the JOSM website URL.
406 * @return the josm website URL
407 * @deprecated Use {@link IUrls#getJOSMWebsite}
408 * @since 6897
409 */
410 @Deprecated
411 public static String getJOSMWebsite() {
412 return Config.getUrls().getJOSMWebsite();
413 }
414
415 /**
416 * Returns the JOSM XML URL.
417 * @return the josm XML URL
418 * @deprecated Use {@link IUrls#getXMLBase}
419 * @since 6897
420 */
421 @Deprecated
422 public static String getXMLBase() {
423 return Config.getUrls().getXMLBase();
424 }
425
426 /**
427 * Returns the OSM website URL.
428 * @return the OSM website URL
429 * @deprecated Use {@link IUrls#getOSMWebsite}
430 * @since 6897
431 */
432 @Deprecated
433 public static String getOSMWebsite() {
434 return Config.getUrls().getOSMWebsite();
435 }
436
437 /**
438 * Replies the base URL for browsing information about a primitive.
439 * @return the base URL, i.e. https://www.openstreetmap.org
440 * @deprecated Use {@link IUrls#getBaseBrowseUrl}
441 * @since 7678
442 */
443 @Deprecated
444 public static String getBaseBrowseUrl() {
445 return Config.getUrls().getBaseBrowseUrl();
446 }
447
448 /**
449 * Replies the base URL for browsing information about a user.
450 * @return the base URL, i.e. https://www.openstreetmap.org/user
451 * @deprecated Use {@link IUrls#getBaseUserUrl}
452 * @since 7678
453 */
454 @Deprecated
455 public static String getBaseUserUrl() {
456 return Config.getUrls().getBaseUserUrl();
457 }
458
459 /**
460 * Determines if we are currently running on OSX.
461 * @return {@code true} if we are currently running on OSX
462 * @since 6957
463 */
464 public static boolean isPlatformOsx() {
465 return Main.platform instanceof PlatformHookOsx;
466 }
467
468 /**
469 * Determines if we are currently running on Windows.
470 * @return {@code true} if we are currently running on Windows
471 * @since 7335
472 */
473 public static boolean isPlatformWindows() {
474 return Main.platform instanceof PlatformHookWindows;
475 }
476
477 /**
478 * Determines if the given online resource is currently offline.
479 * @param r the online resource
480 * @return {@code true} if {@code r} is offline and should not be accessed
481 * @deprecated Use {@link NetworkManager#isOffline}
482 * @since 7434
483 */
484 @Deprecated
485 public static boolean isOffline(OnlineResource r) {
486 return NetworkManager.isOffline(r);
487 }
488
489 /**
490 * Sets the given online resource to offline state.
491 * @param r the online resource
492 * @return {@code true} if {@code r} was not already offline
493 * @deprecated Use {@link NetworkManager#setOffline}
494 * @since 7434
495 */
496 @Deprecated
497 public static boolean setOffline(OnlineResource r) {
498 return NetworkManager.setOffline(r);
499 }
500
501 /**
502 * Sets the given online resource to online state.
503 * @param r the online resource
504 * @return {@code true} if {@code r} was offline
505 * @deprecated Use {@link NetworkManager#setOnline}
506 * @since 8506
507 */
508 @Deprecated
509 public static boolean setOnline(OnlineResource r) {
510 return NetworkManager.setOnline(r);
511 }
512
513 /**
514 * Replies the set of online resources currently offline.
515 * @return the set of online resources currently offline
516 * @deprecated Use {@link NetworkManager#getOfflineResources}
517 * @since 7434
518 */
519 @Deprecated
520 public static Set<OnlineResource> getOfflineResources() {
521 return NetworkManager.getOfflineResources();
522 }
523}
Note: See TracBrowser for help on using the repository browser.