public ByteBuffer run(Retriever retriever) {
      if (!retriever.getState().equals(Retriever.RETRIEVER_STATE_SUCCESSFUL)) return null;

      HTTPRetriever htr = (HTTPRetriever) retriever;
      if (htr.getResponseCode() == HttpURLConnection.HTTP_NO_CONTENT) {
        // Mark tile as missing to avoid excessive attempts
        MercatorTiledImageLayer.this.levels.markResourceAbsent(tile);
        return null;
      }

      if (htr.getResponseCode() != HttpURLConnection.HTTP_OK) return null;

      URLRetriever r = (URLRetriever) retriever;
      ByteBuffer buffer = r.getBuffer();

      String suffix = WWIO.makeSuffixForMimeType(htr.getContentType());
      if (suffix == null) {
        return null; // TODO: log error
      }

      String path = tile.getPath().substring(0, tile.getPath().lastIndexOf("."));
      path += suffix;

      final File outFile = WorldWind.getDataFileStore().newFile(path);
      if (outFile == null) return null;

      try {
        WWIO.saveBuffer(buffer, outFile);
        return buffer;
      } catch (IOException e) {
        e.printStackTrace(); // TODO: log error
        return null;
      }
    }
  /**
   * Causes resources used by the World Window to be freed. The World Window cannot be used once
   * this method is called. An OpenGL context for the window must be current.
   */
  public void shutdown() {
    WorldWind.getDataFileStore().removePropertyChangeListener(this);

    if (this.inputHandler != null) {
      this.inputHandler.dispose();
      this.inputHandler = new NoOpInputHandler();
    }

    // Clear the texture cache
    if (this.getGpuResourceCache() != null) this.getGpuResourceCache().clear();

    // Dispose all the layers //  TODO: Need per-window dispose for layers
    if (this.getModel() != null && this.getModel().getLayers() != null) {
      for (Layer layer : this.getModel().getLayers()) {
        try {
          layer.dispose();
        } catch (Exception e) {
          Logging.logger()
              .log(
                  java.util.logging.Level.SEVERE,
                  Logging.getMessage("WorldWindowGLCanvas.ExceptionWhileShuttingDownWorldWindow"),
                  e);
        }
      }
    }

    SceneController sc = this.getSceneController();
    if (sc != null) sc.dispose();
  }
  public WorldWindowImpl() {
    this.sceneController =
        (SceneController) WorldWind.createConfigurationComponent(AVKey.SCENE_CONTROLLER_CLASS_NAME);

    // Set up to initiate a repaint whenever a file is retrieved and added to the local file store.
    WorldWind.getDataFileStore().addPropertyChangeListener(this);
  }
  private BufferedImage requestImage(MercatorTextureTile tile, String mimeType)
      throws URISyntaxException {
    String pathBase = tile.getPath().substring(0, tile.getPath().lastIndexOf("."));
    String suffix = WWIO.makeSuffixForMimeType(mimeType);
    String path = pathBase + suffix;
    URL url = WorldWind.getDataFileStore().findFile(path, false);

    if (url == null) // image is not local
    return null;

    if (WWIO.isFileOutOfDate(url, tile.getLevel().getExpiryTime())) {
      // The file has expired. Delete it.
      WorldWind.getDataFileStore().removeFile(url);
      String message = Logging.getMessage("generic.DataFileExpired", url);
      Logging.logger().fine(message);
    } else {
      try {
        File imageFile = new File(url.toURI());
        BufferedImage image = ImageIO.read(imageFile);
        if (image == null) {
          String message = Logging.getMessage("generic.ImageReadFailed", imageFile);
          throw new RuntimeException(message);
        }

        this.levels.unmarkResourceAbsent(tile);
        return image;
      } catch (IOException e) {
        // Assume that something's wrong with the file and delete it.
        gov.nasa.worldwind.WorldWind.getDataFileStore().removeFile(url);
        this.levels.markResourceAbsent(tile);
        String message = Logging.getMessage("generic.DeletedCorruptDataFile", url);
        Logging.logger().info(message);
      }
    }

    return null;
  }