protected void openFromPath(final String path) {
      Thread t =
          new Thread(
              new Runnable() {
                public void run() {
                  final ArrayList<Airspace> airspaces = new ArrayList<Airspace>();
                  try {
                    loadAirspacesFromPath(path, airspaces);
                  } finally {
                    SwingUtilities.invokeLater(
                        new Runnable() {
                          public void run() {
                            setAirspaces(airspaces);
                            setEnabled(true);
                            getApp().setCursor(null);
                            getApp().getWwd().redraw();
                          }
                        });
                  }
                }
              });

      this.setEnabled(false);
      getApp().setCursor(new Cursor(Cursor.WAIT_CURSOR));
      t.start();
    }
    public void run() {
      if (Thread.currentThread().isInterrupted())
        return; // the task was cancelled because it's a duplicate or for some other reason

      try {
        this.placemark.retrieveModel(this.address);
      } catch (IOException e) {
        String message = Logging.getMessage("generic.ExceptionWhileReading", e.getMessage());
        Logging.logger().warning(message);
      } catch (XMLStreamException e) {
        String message =
            Logging.getMessage("generic.ExceptionAttemptingToParseXml", e.getMessage());
        Logging.logger().warning(message);
      }
    }
  /**
   * @param fileName the name of the file to find
   * @param checkClassPath if <code>true</code>, the class path is first searched for the file,
   *     otherwise the class path is not searched unless it's one of the explicit paths in the cache
   *     search directories
   * @return a handle to the requested file if it exists in the cache, otherwise null
   * @throws IllegalArgumentException if <code>fileName</code> is null
   */
  public java.net.URL findFile(String fileName, boolean checkClassPath) {
    if (fileName == null) {
      String message = Logging.getMessage("nullValue.FilePathIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    if (checkClassPath) {
      java.net.URL url = this.getClass().getClassLoader().getResource(fileName);
      if (url != null) return url;

      // Check for a thread context class loader. This allows the file store to find resources in a
      // case
      // in which different parts of the application are handled by different class loaders.
      ClassLoader tccl = Thread.currentThread().getContextClassLoader();
      if (tccl != null) {
        url = tccl.getResource(fileName);
        if (url != null) return url;
      }
    }

    for (StoreLocation location : this.readLocations) {
      java.io.File dir = location.getFile();
      if (!dir.exists()) continue;

      java.io.File file = new java.io.File(makeAbsolutePath(dir, fileName));
      if (file.exists()) {
        try {
          if (location.isMarkWhenUsed()) markFileUsed(file);
          else markFileUsed(file.getParentFile());

          return file.toURI().toURL();
        } catch (java.net.MalformedURLException e) {
          Logging.logger()
              .log(
                  Level.SEVERE,
                  Logging.getMessage("FileStore.ExceptionCreatingURLForFile", file.getPath()),
                  e);
        }
      }
    }

    return null;
  }
    protected void saveToFile() {
      if (this.fileChooser == null) {
        this.fileChooser = new JFileChooser();
        this.fileChooser.setCurrentDirectory(new File(Configuration.getUserHomeDirectory()));
      }

      this.fileChooser.setDialogTitle("Choose Directory to Place Airspaces");
      this.fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
      this.fileChooser.setMultiSelectionEnabled(false);
      int status = this.fileChooser.showSaveDialog(null);
      if (status != JFileChooser.APPROVE_OPTION) return;

      final File dir = this.fileChooser.getSelectedFile();
      if (dir == null) return;

      if (!dir.exists()) {
        //noinspection ResultOfMethodCallIgnored
        dir.mkdirs();
      }

      final Iterable<AirspaceEntry> entries = this.getModel().getEntries();

      Thread t =
          new Thread(
              new Runnable() {
                public void run() {
                  try {
                    java.text.DecimalFormat f = new java.text.DecimalFormat("####");
                    f.setMinimumIntegerDigits(4);
                    int counter = 0;

                    for (AirspaceEntry entry : entries) {
                      Airspace a = entry.getAirspace();
                      AirspaceAttributes currentAttribs = a.getAttributes();
                      a.setAttributes(entry.getAttributes());

                      String xmlString = a.getRestorableState();
                      if (xmlString != null) {
                        try {
                          PrintWriter of =
                              new PrintWriter(
                                  new File(
                                      dir,
                                      a.getClass().getName()
                                          + "-"
                                          + entry.getName()
                                          + "-"
                                          + f.format(counter++)
                                          + ".xml"));
                          of.write(xmlString);
                          of.flush();
                          of.close();
                        } catch (Exception e) {
                          e.printStackTrace();
                        }
                      }

                      a.setAttributes(currentAttribs);
                    }
                  } finally {
                    SwingUtilities.invokeLater(
                        new Runnable() {
                          public void run() {
                            setEnabled(true);
                            getApp().setCursor(null);
                            getApp().getWwd().redraw();
                          }
                        });
                  }
                }
              });
      this.setEnabled(false);
      getApp().setCursor(new Cursor(Cursor.WAIT_CURSOR));
      t.start();
    }
    protected void openFromFile() {
      if (this.fileChooser == null) {
        this.fileChooser = new JFileChooser();
        this.fileChooser.setCurrentDirectory(new File(Configuration.getUserHomeDirectory()));
      }

      this.fileChooser.setDialogTitle("Choose Airspace File Directory");
      this.fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
      this.fileChooser.setMultiSelectionEnabled(false);
      int status = this.fileChooser.showOpenDialog(null);
      if (status != JFileChooser.APPROVE_OPTION) return;

      final File dir = this.fileChooser.getSelectedFile();
      if (dir == null) return;

      Thread t =
          new Thread(
              new Runnable() {
                public void run() {
                  final ArrayList<Airspace> airspaces = new ArrayList<Airspace>();
                  try {
                    File[] files =
                        dir.listFiles(
                            new FilenameFilter() {
                              public boolean accept(File dir, String name) {
                                return name.startsWith("gov.nasa.worldwind.render.airspaces")
                                    && name.endsWith(".xml");
                              }
                            });

                    for (File file : files) {
                      String[] name = file.getName().split("-");
                      try {
                        Class c = Class.forName(name[0]);
                        Airspace airspace = (Airspace) c.newInstance();
                        BufferedReader input = new BufferedReader(new FileReader(file));
                        String s = input.readLine();
                        airspace.restoreState(s);
                        airspaces.add(airspace);

                        if (name.length >= 2) {
                          airspace.setValue(AVKey.DISPLAY_NAME, name[1]);
                        }
                      } catch (Exception e) {
                        e.printStackTrace();
                      }
                    }
                  } finally {
                    SwingUtilities.invokeLater(
                        new Runnable() {
                          public void run() {
                            setAirspaces(airspaces);
                            setEnabled(true);
                            getApp().setCursor(null);
                            getApp().getWwd().redraw();
                          }
                        });
                  }
                }
              });
      this.setEnabled(false);
      getApp().setCursor(new Cursor(Cursor.WAIT_CURSOR));
      t.start();
    }