/**
   * Resolves a reference to a local or remote file or element. If the link refers to an element in
   * the current document, this method returns that element. If the link refers to a remote
   * document, this method will initiate asynchronous retrieval of the document, and return a URL of
   * the downloaded document in the file cache, if it is available locally. If the link identifies a
   * COLLADA document, the document will be returned as a parsed ColladaRoot.
   *
   * @param link the address of the document or element to resolve. This may be a full URL, a URL
   *     fragment that identifies an element in the current document ("#myElement"), or a URL and a
   *     fragment identifier ("http://server.com/model.dae#myElement").
   * @return the requested element, or null if the element is not found.
   * @throws IllegalArgumentException if the address is null.
   */
  public Object resolveReference(String link) {
    if (link == null) {
      String message = Logging.getMessage("nullValue.DocumentSourceIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    try {
      String[] linkParts = link.split("#");
      String linkBase = linkParts[0];
      String linkRef = linkParts.length > 1 ? linkParts[1] : null;

      // See if it's a reference to an internal element.
      if (WWUtil.isEmpty(linkBase) && !WWUtil.isEmpty(linkRef)) return this.getItemByID(linkRef);

      // Interpret the path relative to the current document.
      String path = this.getSupportFilePath(linkBase);
      if (path == null) path = linkBase;

      // See if it's an already found and parsed COLLADA file.
      Object o = WorldWind.getSessionCache().get(path);
      if (o != null && o instanceof ColladaRoot)
        return linkRef != null ? ((ColladaRoot) o).getItemByID(linkRef) : o;

      URL url = WWIO.makeURL(path);
      if (url == null) {
        // See if the reference can be resolved to a local file.
        o = this.resolveLocalReference(path, linkRef);
      }

      // If we didn't find a local file, treat it as a remote reference.
      if (o == null) o = this.resolveRemoteReference(path, linkRef);

      if (o != null) return o;

      // If the reference was not resolved as a remote reference, look for a local element
      // identified by the
      // reference string. This handles the case of malformed internal references that omit the #
      // sign at the
      // beginning of the reference.
      return this.getItemByID(link);
    } catch (Exception e) {
      String message = Logging.getMessage("generic.UnableToResolveReference", link);
      Logging.logger().warning(message);
    }

    return null;
  }
  /**
   * Build the resource map from the KML Model's <i>ResourceMap</i> element.
   *
   * @param model Model from which to create the resource map.
   * @return Map that relates relative paths in the COLLADA document to paths relative to the KML
   *     document.
   */
  protected Map<String, String> createResourceMap(KMLModel model) {
    Map<String, String> map = new HashMap<String, String>();

    KMLResourceMap resourceMap = model.getResourceMap();
    if (resourceMap == null) return Collections.emptyMap();

    for (KMLAlias alias : resourceMap.getAliases()) {
      if (alias != null
          && !WWUtil.isEmpty(alias.getSourceRef())
          && !WWUtil.isEmpty(alias.getTargetHref())) {
        map.put(alias.getSourceRef(), alias.getTargetHref());
      }
    }

    return map.size() > 0 ? map : Collections.<String, String>emptyMap();
  }
Пример #3
0
  /**
   * Unzips the sole entry in the specified zip file, and saves it in a temporary directory, and
   * returns a File to the temporary location.
   *
   * @param path the path to the source file.
   * @param suffix the suffix to give the temp file.
   * @return a {@link File} for the temp file.
   * @throws IllegalArgumentException if the <code>path</code> is <code>null</code> or empty.
   */
  public static File unzipAndSaveToTempFile(String path, String suffix) {
    if (WWUtil.isEmpty(path)) {
      String message = Logging.getMessage("nullValue.PathIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    InputStream stream = null;

    try {
      stream = WWIO.openStream(path);

      ByteBuffer buffer = WWIO.readStreamToBuffer(stream);
      File file = WWIO.saveBufferToTempFile(buffer, WWIO.getFilename(path));

      buffer = WWIO.readZipEntryToBuffer(file, null);
      return WWIO.saveBufferToTempFile(buffer, suffix);
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      WWIO.closeStream(stream, path);
    }

    return null;
  }
  public WMSLayerCapabilities getLayerByName(String name) {
    if (WWUtil.isEmpty(name)) return null;

    List<WMSLayerCapabilities> namedLayers = this.getNamedLayers();
    for (WMSLayerCapabilities layer : namedLayers) {
      if (layer.getName().equals(name)) return layer;
    }

    return null;
  }
Пример #5
0
 private void openVPFCoveragePanel(VPFDatabase db, VPFLayer layer) {
   VPFCoveragePanel panel = new VPFCoveragePanel(getWwd(), db);
   panel.setLayer(layer);
   JFrame frame = new JFrame(db.getName());
   frame.setResizable(true);
   frame.setAlwaysOnTop(true);
   frame.add(panel);
   frame.pack();
   WWUtil.alignComponent(this, frame, AVKey.CENTER);
   frame.setVisible(true);
 }
  /**
   * Determines and stores the network sites to test for public network connectivity. The sites are
   * drawn from the JVM's gov.nasa.worldwind.avkey.NetworkStatusTestSites property ({@link
   * AVKey#NETWORK_STATUS_TEST_SITES}). If that property is not defined, the sites are drawn from
   * the same property in the World Wind or application configuration file. If the sites are not
   * specified there, the set of sites specified in {@link #DEFAULT_NETWORK_TEST_SITES} are used. To
   * indicate an empty list in the JVM property or configuration file property, specify an empty
   * site list, "".
   */
  protected void establishNetworkTestSites() {
    String testSites = System.getProperty(AVKey.NETWORK_STATUS_TEST_SITES);

    if (testSites == null)
      testSites = Configuration.getStringValue(AVKey.NETWORK_STATUS_TEST_SITES);

    if (testSites == null) {
      this.networkTestSites.addAll(Arrays.asList(DEFAULT_NETWORK_TEST_SITES));
    } else {
      String[] sites = testSites.split(",");
      List<String> actualSites = new ArrayList<String>(sites.length);

      for (String site : sites) {
        site = WWUtil.removeWhiteSpace(site);
        if (!WWUtil.isEmpty(site)) actualSites.add(site);
      }

      this.setNetworkTestSites(actualSites);
    }
  }
  /**
   * Thread's off a task to determine whether the resource is local or remote and then retrieves it
   * either from disk cache or a remote server.
   *
   * @param dc the current draw context.
   */
  protected void requestResource(DrawContext dc) {
    if (WorldWind.getTaskService().isFull()) return;

    KMLLink link = this.model.getLink();
    if (link == null) return;

    String address = link.getAddress(dc);
    if (address != null) address = address.trim();

    if (WWUtil.isEmpty(address)) return;

    WorldWind.getTaskService().addTask(new RequestTask(this, address));
  }
  public ViewViewVolume() {
    this.getContentPane().setLayout(new BorderLayout(5, 5));

    this.wwp = new WWPanel(new Dimension(650, 500));
    this.getContentPane().add(wwp);

    this.pack();
    this.setResizable(true);

    WWUtil.alignComponent(null, this, AVKey.CENTER);

    this.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
  }
Пример #9
0
  /**
   * Create a surface polygon from a KML GroundOverlay.
   *
   * @param tc the current {@link KMLTraversalContext}.
   * @param overlay the {@link gov.nasa.worldwind.ogc.kml.KMLGroundOverlay} to render as a polygon.
   * @throws NullPointerException if the geometry is null.
   * @throws IllegalArgumentException if the parent placemark or the traversal context is null.
   */
  public KMLSurfacePolygonImpl(KMLTraversalContext tc, KMLGroundOverlay overlay) {
    if (tc == null) {
      String msg = Logging.getMessage("nullValue.TraversalContextIsNull");
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    if (overlay == null) {
      String msg = Logging.getMessage("nullValue.ParentIsNull");
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    this.parent = overlay;

    // Positions are specified either as a kml:LatLonBox or a gx:LatLonQuad
    Position.PositionList corners = overlay.getPositions();
    this.setOuterBoundary(corners.list);

    if (overlay.getName() != null) this.setValue(AVKey.DISPLAY_NAME, overlay.getName());

    if (overlay.getDescription() != null)
      this.setValue(AVKey.BALLOON_TEXT, overlay.getDescription());

    if (overlay.getSnippetText() != null)
      this.setValue(AVKey.SHORT_DESCRIPTION, overlay.getSnippetText());

    String colorStr = overlay.getColor();
    if (!WWUtil.isEmpty(colorStr)) {
      Color color = WWUtil.decodeColorABGR(colorStr);

      ShapeAttributes attributes = new BasicShapeAttributes();
      attributes.setDrawInterior(true);
      attributes.setInteriorMaterial(new Material(color));
      this.setAttributes(attributes);
    }
  }
Пример #10
0
  protected static String makeFullLibName(String libName) {
    if (WWUtil.isEmpty(libName)) return null;

    if (gov.nasa.worldwind.Configuration.isWindowsOS()) {
      if (!libName.toLowerCase().endsWith(".dll")) return libName + ".dll";
    } else if (gov.nasa.worldwind.Configuration.isMacOS()) {
      if (!libName.toLowerCase().endsWith(".jnilib") && !libName.toLowerCase().startsWith("lib"))
        return "lib" + libName + ".jnilib";
    } else if (gov.nasa.worldwind.Configuration.isUnixOS()) // covers Solaris and Linux
    {
      if (!libName.toLowerCase().endsWith(".so") && !libName.toLowerCase().startsWith("lib"))
        return "lib" + libName + ".so";
    }
    return libName;
  }
Пример #11
0
  /**
   * Create a layer described by an XML layer description.
   *
   * @param domElement the XML element describing the layer to create.
   * @param params any parameters to apply when creating the layer.
   * @return a new layer
   * @throws WWUnrecognizedException if the layer type or service type given in the describing
   *     element is unrecognized.
   * @see #createTiledImageLayer(org.w3c.dom.Element, gov.nasa.worldwind.avlist.AVList).
   */
  protected Layer createFromLayerDocument(Element domElement, AVList params) {
    String className = WWXML.getText(domElement, "@className");
    if (className != null && className.length() > 0) {
      Layer layer = (Layer) WorldWind.createComponent(className);
      String actuate = WWXML.getText(domElement, "@actuate");
      layer.setEnabled(WWUtil.isEmpty(actuate) || actuate.equals("onLoad"));
      WWXML.invokePropertySetters(layer, domElement);
      return layer;
    }

    AVList props = WWXML.copyProperties(domElement, null);
    if (props != null) { // Copy params and add any properties for this layer to the copy
      if (params != null) props.setValues(params);
      params = props;
    }

    Layer layer;
    String href = WWXML.getText(domElement, "@href");
    if (href != null && href.length() > 0) {
      Object o = this.createFromConfigSource(href, params);
      if (o == null) return null;

      if (!(o instanceof Layer)) {
        String msg =
            Logging.getMessage("LayerFactory.UnexpectedTypeForLayer", o.getClass().getName());
        throw new WWRuntimeException(msg);
      }

      layer = (Layer) o;
    } else {
      String layerType = WWXML.getText(domElement, "@layerType");
      if (layerType != null && layerType.equals("TiledImageLayer")) {
        layer = this.createTiledImageLayer(domElement, params);
      } else {
        String msg = Logging.getMessage("generic.UnrecognizedLayerType", layerType);
        throw new WWUnrecognizedException(msg);
      }
    }

    if (layer != null) {
      String actuate = WWXML.getText(domElement, "@actuate");
      layer.setEnabled(actuate != null && actuate.equals("onLoad"));
      WWXML.invokePropertySetters(layer, domElement);
    }

    return layer;
  }
Пример #12
0
  public static void loadLibrary(String libName)
      throws WWRuntimeException, IllegalArgumentException {
    if (WWUtil.isEmpty(libName)) {
      String message = Logging.getMessage("nullValue.LibraryIsNull");
      throw new IllegalArgumentException(message);
    }

    try {
      System.loadLibrary(libName);
    } catch (java.lang.UnsatisfiedLinkError ule) {
      String message = Logging.getMessage("generic.LibraryNotLoaded", libName, ule.getMessage());
      throw new WWRuntimeException(message);
    } catch (Throwable t) {
      String message = Logging.getMessage("generic.LibraryNotLoaded", libName, t.getMessage());
      throw new WWRuntimeException(message);
    }
  }
  /**
   * Resolves a reference to a remote element identified by address and identifier, where {@code
   * linkBase} identifies a remote document, and {@code linkRef} is the id of the desired element.
   * This method retrieves resources asynchronously using the {@link
   * gov.nasa.worldwind.cache.FileStore}.
   *
   * <p>The return value is null if the file is not yet available in the FileStore. If {@code
   * linkBase} refers to a COLLADA file and {@code linkRef} is non-null, the return value is the
   * element identified by {@code linkRef}. If {@code linkBase} refers to a COLLADA file and {@code
   * linkRef} is null, the return value is a parsed {@link ColladaRoot} for the COLLADA file
   * identified by {@code linkBase}. Otherwise the return value is a {@link URL} to the file in the
   * file cache.
   *
   * @param linkBase the address of the document containing the requested element.
   * @param linkRef the element's identifier.
   * @return URL to the requested file, parsed ColladaRoot, or COLLADA element. Returns null if the
   *     document is not yet available in the FileStore.
   * @throws IllegalArgumentException if the {@code linkBase} is null.
   */
  public Object resolveRemoteReference(String linkBase, String linkRef) {
    if (linkBase == null) {
      String message = Logging.getMessage("nullValue.DocumentSourceIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    try {
      // See if it's in the cache. If not, requestFile will start another thread to retrieve it and
      // return null.
      URL url = WorldWind.getDataFileStore().requestFile(linkBase);
      if (url == null) return null;

      // It's in the cache. If it's a COLLADA file try to parse it so we can search for the
      // specified reference.
      // If it's not COLLADA, just return the url for the cached file.
      String contentType = WorldWind.getDataFileStore().getContentType(linkBase);
      if (contentType == null) {
        String suffix = WWIO.getSuffix(linkBase.split(";")[0]); // strip of trailing garbage
        if (!WWUtil.isEmpty(suffix)) contentType = WWIO.makeMimeTypeForSuffix(suffix);
      }

      if (!this.canParseContentType(contentType)) return url;

      // If the file is a COLLADA document, attempt to open it. We can't open it as a File with
      // createAndParse
      // because the ColladaRoot that will be created needs to have the remote address in order to
      // resolve any
      // relative references within it.
      ColladaRoot refRoot = this.parseCachedColladaFile(url, linkBase);

      // Add the parsed file to the session cache so it doesn't have to be parsed again.
      WorldWind.getSessionCache().put(linkBase, refRoot);

      // Now check the newly opened COLLADA file for the referenced item, if a reference was
      // specified.
      if (linkRef != null) return refRoot.getItemByID(linkRef);
      else return refRoot;
    } catch (Exception e) {
      String message =
          Logging.getMessage("generic.UnableToResolveReference", linkBase + "/" + linkRef);
      Logging.logger().warning(message);
      return null;
    }
  }
Пример #14
0
  protected void doDrawOnTo(BufferedImageRaster canvas) {
    Sector sector = this.getSector();
    if (null == sector) {
      String message = Logging.getMessage("nullValue.SectorIsNull");
      Logging.logger().severe(message);
      throw new IllegalArgumentException(message);
    }

    if (!sector.intersects(canvas.getSector())) {
      return;
    }

    java.awt.Graphics2D g2d = null;
    java.awt.Shape prevClip = null;
    java.awt.Composite prevComposite = null;
    java.lang.Object prevInterpolation = null, prevAntialiasing = null;

    try {
      int canvasWidth = canvas.getWidth();
      int canvasHeight = canvas.getHeight();

      // Apply the transform that correctly maps the image onto the canvas.
      java.awt.geom.AffineTransform transform =
          this.computeSourceToDestTransform(
              this.getWidth(),
              this.getHeight(),
              this.getSector(),
              canvasWidth,
              canvasHeight,
              canvas.getSector());

      AffineTransformOp op = new AffineTransformOp(transform, AffineTransformOp.TYPE_BILINEAR);
      Rectangle2D rect = op.getBounds2D(this.getBufferedImage());

      int clipWidth =
          (int) Math.ceil((rect.getMaxX() >= canvasWidth) ? canvasWidth : rect.getMaxX());
      int clipHeight =
          (int) Math.ceil((rect.getMaxY() >= canvasHeight) ? canvasHeight : rect.getMaxY());

      if (clipWidth <= 0 || clipHeight <= 0) {
        return;
      }

      g2d = canvas.getGraphics();

      prevClip = g2d.getClip();
      prevComposite = g2d.getComposite();
      prevInterpolation = g2d.getRenderingHint(RenderingHints.KEY_INTERPOLATION);
      prevAntialiasing = g2d.getRenderingHint(RenderingHints.KEY_ANTIALIASING);

      // Set the alpha composite for appropriate alpha blending.
      g2d.setComposite(java.awt.AlphaComposite.SrcOver);
      g2d.setRenderingHint(
          RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
      g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

      g2d.drawImage(this.getBufferedImage(), transform, null);
    }
    //        catch (java.awt.image.ImagingOpException ioe)
    //        {
    //            // If we catch a ImagingOpException, then the transformed image has a width or
    // height of 0.
    //            // This indicates that there is no intersection between the source image and the
    // canvas,
    //            // or the intersection is smaller than one pixel.
    //        }
    //        catch (java.awt.image.RasterFormatException rfe)
    //        {
    //            // If we catch a RasterFormatException, then the transformed image has a width or
    // height of 0.
    //            // This indicates that there is no intersection between the source image and the
    // canvas,
    //            // or the intersection is smaller than one pixel.
    //        }
    catch (Throwable t) {
      String reason = WWUtil.extractExceptionReason(t);
      Logging.logger().log(java.util.logging.Level.SEVERE, reason, t);
    } finally {
      // Restore the previous clip, composite, and transform.
      try {
        if (null != g2d) {
          if (null != prevClip) g2d.setClip(prevClip);

          if (null != prevComposite) g2d.setComposite(prevComposite);

          if (null != prevInterpolation)
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, prevInterpolation);

          if (null != prevAntialiasing)
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, prevAntialiasing);
        }
      } catch (Throwable t) {
        Logging.logger().log(java.util.logging.Level.FINEST, WWUtil.extractExceptionReason(t), t);
      }
    }
  }
  /**
   * Create an screen image.
   *
   * @param tc the current {@link KMLTraversalContext}.
   * @param overlay the <i>Overlay</i> element containing.
   * @throws NullPointerException if the traversal context is null.
   * @throws IllegalArgumentException if the parent overlay or the traversal context is null.
   */
  public KMLScreenImageImpl(KMLTraversalContext tc, KMLScreenOverlay overlay) {
    this.parent = overlay;

    if (tc == null) {
      String msg = Logging.getMessage("nullValue.TraversalContextIsNull");
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    if (overlay == null) {
      String msg = Logging.getMessage("nullValue.ParentIsNull");
      Logging.logger().severe(msg);
      throw new IllegalArgumentException(msg);
    }

    KMLVec2 xy = this.parent.getScreenXY();
    if (xy != null) {
      this.screenOffset =
          new Offset(
              xy.getX(),
              xy.getY(),
              KMLUtil.kmlUnitsToWWUnits(xy.getXunits()),
              KMLUtil.kmlUnitsToWWUnits(xy.getYunits()));
    }

    xy = this.parent.getOverlayXY();
    if (xy != null) {
      this.imageOffset =
          new Offset(
              xy.getX(),
              xy.getY(),
              KMLUtil.kmlUnitsToWWUnits(xy.getXunits()),
              KMLUtil.kmlUnitsToWWUnits(xy.getYunits()));
    }

    this.setRotation(overlay.getRotation());

    xy = this.parent.getRotationXY();
    if (xy != null) {
      setRotationOffset(
          new Offset(
              xy.getX(),
              xy.getY(),
              KMLUtil.kmlUnitsToWWUnits(xy.getXunits()),
              KMLUtil.kmlUnitsToWWUnits(xy.getYunits())));
    }

    String colorStr = overlay.getColor();
    if (colorStr != null) {
      Color color = WWUtil.decodeColorABGR(colorStr);
      this.setColor(color);
    }

    // Compute desired image size, and the scale factor that will make it that size
    KMLVec2 kmlSize = this.parent.getSize();
    if (kmlSize != null) {
      Size size = new Size();
      size.setWidth(
          getSizeMode(kmlSize.getX()),
          kmlSize.getX(),
          KMLUtil.kmlUnitsToWWUnits(kmlSize.getXunits()));
      size.setHeight(
          getSizeMode(kmlSize.getY()),
          kmlSize.getY(),
          KMLUtil.kmlUnitsToWWUnits(kmlSize.getYunits()));
      this.setSize(size);
    }
  }
Пример #16
0
  /**
   * Export the placemark attributes to KML as a {@code <Style>} element. The {@code output} object
   * will receive the data. This object must be one of: java.io.Writer<br>
   * java.io.OutputStream<br>
   * javax.xml.stream.XMLStreamWriter
   *
   * @param output Object to receive the generated KML.
   * @throws XMLStreamException If an exception occurs while writing the KML
   * @see #export(String, Object)
   */
  protected void exportAsKML(Object output) throws XMLStreamException {
    XMLStreamWriter xmlWriter = null;
    XMLOutputFactory factory = XMLOutputFactory.newInstance();
    boolean closeWriterWhenFinished = true;

    if (output instanceof XMLStreamWriter) {
      xmlWriter = (XMLStreamWriter) output;
      closeWriterWhenFinished = false;
    } else if (output instanceof Writer) {
      xmlWriter = factory.createXMLStreamWriter((Writer) output);
    } else if (output instanceof OutputStream) {
      xmlWriter = factory.createXMLStreamWriter((OutputStream) output);
    }

    if (xmlWriter == null) {
      String message = Logging.getMessage("Export.UnsupportedOutputObject");
      Logging.logger().warning(message);
      throw new IllegalArgumentException(message);
    }

    xmlWriter.writeStartElement("Style");

    // Line style
    xmlWriter.writeStartElement("LineStyle");

    final Color lineColor = this.getOutlineMaterial().getDiffuse();
    if (lineColor != null) {
      xmlWriter.writeStartElement("color");
      xmlWriter.writeCharacters(KMLExportUtil.stripHexPrefix(WWUtil.encodeColorABGR(lineColor)));
      xmlWriter.writeEndElement();

      xmlWriter.writeStartElement("colorMode");
      xmlWriter.writeCharacters("normal");
      xmlWriter.writeEndElement();
    }

    final Double lineWidth = this.getOutlineWidth();
    if (lineWidth != null) {
      xmlWriter.writeStartElement("width");
      xmlWriter.writeCharacters(Double.toString(lineWidth));
      xmlWriter.writeEndElement();
    }

    xmlWriter.writeEndElement(); // LineStyle

    // Poly style
    xmlWriter.writeStartElement("PolyStyle");

    final Color fillColor = this.getInteriorMaterial().getDiffuse();
    if (fillColor != null) {
      xmlWriter.writeStartElement("color");
      xmlWriter.writeCharacters(KMLExportUtil.stripHexPrefix(WWUtil.encodeColorABGR(fillColor)));
      xmlWriter.writeEndElement();

      xmlWriter.writeStartElement("colorMode");
      xmlWriter.writeCharacters("normal");
      xmlWriter.writeEndElement();
    }

    xmlWriter.writeStartElement("fill");
    xmlWriter.writeCharacters(kmlBoolean(isDrawInterior()));
    xmlWriter.writeEndElement();

    xmlWriter.writeStartElement("outline");
    xmlWriter.writeCharacters(kmlBoolean(isDrawOutline()));
    xmlWriter.writeEndElement();

    xmlWriter.writeEndElement(); // PolyStyle
    xmlWriter.writeEndElement(); // Style

    xmlWriter.flush();
    if (closeWriterWhenFinished) xmlWriter.close();
  }