Revision: 4755
          http://sourceforge.net/p/jump-pilot/code/4755
Author:   edso
Date:     2016-01-10 16:11:37 +0000 (Sun, 10 Jan 2016)
Log Message:
-----------
adapt to new Logger
fix wfs 401 error introduced before because the userinfo was not url decoded 
anymore

Modified Paths:
--------------
    
core/trunk/src/com/vividsolutions/jump/workbench/ui/cursortool/AbstractCursorTool.java
    
core/trunk/src/com/vividsolutions/jump/workbench/ui/cursortool/FeatureInfoTool.java
    core/trunk/src/com/vividsolutions/wms/AbstractParser.java
    core/trunk/src/com/vividsolutions/wms/AbstractWMSRequest.java
    core/trunk/src/com/vividsolutions/wms/AxisOrder.java
    core/trunk/src/com/vividsolutions/wms/Capabilities.java
    core/trunk/src/com/vividsolutions/wms/FeatureInfoRequest.java
    core/trunk/src/com/vividsolutions/wms/IParser.java
    core/trunk/src/com/vividsolutions/wms/MapRequest.java
    core/trunk/src/com/vividsolutions/wms/MapStyle.java
    core/trunk/src/com/vividsolutions/wms/Parser.java

Modified: 
core/trunk/src/com/vividsolutions/jump/workbench/ui/cursortool/AbstractCursorTool.java
===================================================================
--- 
core/trunk/src/com/vividsolutions/jump/workbench/ui/cursortool/AbstractCursorTool.java
      2016-01-10 15:53:09 UTC (rev 4754)
+++ 
core/trunk/src/com/vividsolutions/jump/workbench/ui/cursortool/AbstractCursorTool.java
      2016-01-10 16:11:37 UTC (rev 4755)
@@ -57,13 +57,12 @@
 import javax.swing.ImageIcon;
 import javax.swing.SwingUtilities;
 
-import org.apache.log4j.Logger;
-
 import com.vividsolutions.jts.geom.Coordinate;
 import com.vividsolutions.jump.I18N;
 import com.vividsolutions.jump.util.Blackboard;
 import com.vividsolutions.jump.util.StringUtil;
 import com.vividsolutions.jump.workbench.JUMPWorkbench;
+import com.vividsolutions.jump.workbench.Logger;
 import com.vividsolutions.jump.workbench.model.UndoableCommand;
 import com.vividsolutions.jump.workbench.plugin.AbstractPlugIn;
 import com.vividsolutions.jump.workbench.plugin.EnableCheck;
@@ -96,7 +95,7 @@
  * {@link #redrawImage()} method.
  */
 public abstract class AbstractCursorTool implements CursorTool {
-       private static Logger LOG = Logger.getLogger(AbstractCursorTool.class);
+
        
        private boolean snappingInitialized = false;
 
@@ -473,7 +472,7 @@
     // http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7153339
     catch (java.lang.InternalError ie){
       ie.printStackTrace(System.err);
-      LOG.error(ie.getLocalizedMessage() +": 
"+Arrays.toString(ie.getStackTrace()));
+      Logger.error(ie.getLocalizedMessage() +": 
"+Arrays.toString(ie.getStackTrace()));
     }
     finally {
       cleanup(graphics);
@@ -671,7 +670,7 @@
       return I18N.get(key);
     } catch (java.util.MissingResourceException e) {
       // No I18N for the PlugIn so log it, but don't stop
-      LOG.error(e.getMessage() + " " + tool.getClass().getName());
+      Logger.error(e.getMessage() + " " + tool.getClass().getName());
       return StringUtil.toFriendlyName(tool.getClass().getName(),
           I18N.get("ui.cursortool.AbstractCursorTool.tool"));
     }

Modified: 
core/trunk/src/com/vividsolutions/jump/workbench/ui/cursortool/FeatureInfoTool.java
===================================================================
--- 
core/trunk/src/com/vividsolutions/jump/workbench/ui/cursortool/FeatureInfoTool.java
 2016-01-10 15:53:09 UTC (rev 4754)
+++ 
core/trunk/src/com/vividsolutions/jump/workbench/ui/cursortool/FeatureInfoTool.java
 2016-01-10 16:11:37 UTC (rev 4755)
@@ -47,7 +47,6 @@
 import javax.swing.Icon;
 import javax.swing.ImageIcon;
 
-import org.apache.commons.io.IOUtils;
 import org.openjump.core.CheckOS;
 import org.openjump.core.rasterimage.RasterImageLayer;
 import 
org.openjump.core.rasterimage.RasterImageLayer.RasterDataNotFoundException;
@@ -55,6 +54,7 @@
 import com.vividsolutions.jts.geom.Coordinate;
 import com.vividsolutions.jts.geom.Envelope;
 import com.vividsolutions.jump.workbench.JUMPWorkbench;
+import com.vividsolutions.jump.workbench.Logger;
 import com.vividsolutions.jump.workbench.model.FenceLayerFinder;
 import com.vividsolutions.jump.workbench.model.Layer;
 import com.vividsolutions.jump.workbench.model.Layerable;
@@ -196,8 +196,7 @@
 //            String fiu2 = request.getURL().toString();
             
             try {
-              wmsResponse = IOUtils
-                  .toString(request.getConnection().getInputStream());
+              wmsResponse = request.getText();
               wmsResponse = cleanWmsResponse(wmsResponse);
             } catch (Exception ex) {
               StringWriter sw = new StringWriter();
@@ -205,6 +204,8 @@
               wmsResponse = sw.toString();
               JUMPWorkbench.getInstance().getFrame().log(sw.toString());
               wmsResponse = wmsResponse.concat(newLine);
+              
+              Logger.debug(ex);
             }
             
             response = response.concat(wmsResponse);

Modified: core/trunk/src/com/vividsolutions/wms/AbstractParser.java
===================================================================
--- core/trunk/src/com/vividsolutions/wms/AbstractParser.java   2016-01-10 
15:53:09 UTC (rev 4754)
+++ core/trunk/src/com/vividsolutions/wms/AbstractParser.java   2016-01-10 
16:11:37 UTC (rev 4755)
@@ -43,7 +43,6 @@
 import java.util.LinkedList;
 import java.util.List;
 
-import org.apache.log4j.Logger;
 import org.apache.xerces.parsers.DOMParser;
 import org.w3c.dom.CharacterData;
 import org.w3c.dom.Document;
@@ -57,6 +56,7 @@
 import org.xml.sax.SAXException;
 
 import com.vividsolutions.jump.I18N;
+import com.vividsolutions.jump.workbench.Logger;
 import com.vividsolutions.wms.util.XMLTools;
 
 
@@ -67,7 +67,7 @@
  */
 public abstract class AbstractParser implements IParser {
     
-    private static Logger LOG = Logger.getLogger(AbstractParser.class);
+
    
    /** 
     * Creates a Parser for dealing with WMS XML.
@@ -262,7 +262,7 @@
                 }
             } catch( Exception e ) {
                 e.printStackTrace();
-                LOG.error( "Exception caught in wmsLayerFromNode(): " + 
e.toString() );
+                Logger.error( "Exception caught in wmsLayerFromNode(): " + 
e.toString() );
             }
         }
 

Modified: core/trunk/src/com/vividsolutions/wms/AbstractWMSRequest.java
===================================================================
--- core/trunk/src/com/vividsolutions/wms/AbstractWMSRequest.java       
2016-01-10 15:53:09 UTC (rev 4754)
+++ core/trunk/src/com/vividsolutions/wms/AbstractWMSRequest.java       
2016-01-10 16:11:37 UTC (rev 4755)
@@ -1,12 +1,12 @@
 package com.vividsolutions.wms;
 
 import java.awt.Image;
-import java.io.BufferedReader;
 import java.io.IOException;
-import java.io.InputStreamReader;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.net.URLConnection;
+import java.nio.charset.Charset;
 import java.util.List;
 import java.util.Map.Entry;
 
@@ -14,14 +14,23 @@
 
 import net.iharder.Base64;
 
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.io.input.BoundedInputStream;
+import org.openjump.util.UriUtil;
+
+import com.vividsolutions.jump.util.FileUtil;
+import com.vividsolutions.jump.workbench.Logger;
+
 abstract public class AbstractWMSRequest implements WMSRequest {
 
   protected WMService service;
   protected String version = WMService.WMS_1_1_1;
+  protected HttpURLConnection con = null;
 
   protected AbstractWMSRequest(WMService service) {
     this.service = service;
-    // we use the services version by default, can be overwritten later via 
setter
+    // we use the services version by default,
+    // can be overwritten later via setter
     this.version = service.getWmsVersion();
   }
 
@@ -57,19 +66,25 @@
    * @return
    * @throws IOException
    */
-  protected URLConnection prepareConnection() throws IOException {
+  protected HttpURLConnection prepareConnection() throws IOException {
     URL requestUrl = getURL();
-    URLConnection con = requestUrl.openConnection();
+    con = (HttpURLConnection) requestUrl.openConnection();
+
+    Logger.trace(Base64.encodeBytes(UriUtil.urlDecode(requestUrl.getUserInfo())
+        .getBytes(Charset.forName("UTF-8"))));
+
     con.setConnectTimeout(WMService.TIMEOUT_OPEN);
     con.setReadTimeout(WMService.TIMEOUT_READ);
-    
+
     // add this service's auth info
-    String userinfo = requestUrl.getUserInfo();
-    if (userinfo != null) {
-      con.setRequestProperty("Authorization",
-          "Basic " + Base64.encodeBytes(requestUrl.getUserInfo().getBytes()));
+    String userInfo = requestUrl.getUserInfo();
+    if (userInfo != null) {
+      con.setRequestProperty(
+          "Authorization",
+          "Basic "
+              + Base64.encodeBytes(UriUtil.urlDecode(userInfo).getBytes(
+                  Charset.forName("UTF-8"))));
     }
-    con.setRequestProperty("Host", requestUrl.getHost());
 
     return con;
   }
@@ -80,8 +95,10 @@
    * 
    * @Override
    */
-  public URLConnection getConnection() throws IOException {
-    return prepareConnection();
+  public HttpURLConnection getConnection() throws IOException {
+    if (con == null)
+      con = prepareConnection();
+    return con;
   }
 
   /**
@@ -90,41 +107,66 @@
    * @return the retrieved map Image
    */
   public Image getImage() throws IOException {
-    URLConnection con = getConnection();
+    HttpURLConnection con = getConnection();
 
+    boolean httpOk = con.getResponseCode() == HttpURLConnection.HTTP_OK;
+
     boolean isImage = false;
-    // System.out.println(requestUrl);
-    for (Entry<String, List<String>> entry : con.getHeaderFields().entrySet()) 
{
+    if (httpOk) {
+      for (Entry<String, List<String>> entry : 
con.getHeaderFields().entrySet()) {
 
-      String key = entry.getKey() != null ? entry.getKey() : "";
-      String value = null;
-      try {
-        value = entry.getValue().get(0).toString();
-      } catch (Exception e) {
+        String key = entry.getKey() != null ? entry.getKey() : "";
+        String value = null;
+        try {
+          value = entry.getValue().get(0).toString();
+        } catch (Exception e) {
+        }
+        // System.out.println(key + "/" + value);
+        if (key.matches("^(?i)Content-Type$") && 
value.matches("^(?i)image/.*"))
+          isImage = true;
       }
-
-      // System.out.println(key + "/" + value);
-
-      if (key.matches("^(?i)Content-Type$") && value.matches("^(?i)image/.*"))
-        isImage = true;
     }
 
     if (isImage)
       return ImageIO.read(con.getInputStream());
 
-    readConnection(con);
+    // finally, no image? ok we just printout what we received
+    readToLog(con);
     return null;
   }
 
-  protected void readConnection(URLConnection con) throws IOException {
-    BufferedReader reader = new BufferedReader(new InputStreamReader(
-        con.getInputStream()));
-    StringBuilder result = new StringBuilder();
-    String line;
-    while ((line = reader.readLine()) != null) {
-      result.append(line);
+  /**
+   * connect and retrieve response as text
+   * 
+   * @return
+   * @throws IOException
+   */
+  public String getText() throws IOException {
+    HttpURLConnection con = getConnection();
+    return readConnection(con, 0, false);
+  }
+
+  protected String readToLog(HttpURLConnection con) throws IOException {
+    return readConnection(con, 1024, true);
+  }
+
+  protected String readConnection(HttpURLConnection con, long limit,
+      boolean debug) throws IOException {
+    boolean httpOk = con.getResponseCode() == HttpURLConnection.HTTP_OK;
+    // get correct stream
+    InputStream in = httpOk ? con.getInputStream() : con.getErrorStream();
+    // limit max chars
+    BoundedInputStream bin = new BoundedInputStream(in, limit > 0 ? limit : 
-1);
+
+    String result = IOUtils.toString(bin);
+    FileUtil.close(bin);
+
+    if (debug) {
+      Logger.info("Response code: " + con.getResponseCode());
+      Logger.info("Response body:\n" + result + "\n");
     }
-    System.out.println(result.toString());
+
+    return result;
   }
 
 }

Modified: core/trunk/src/com/vividsolutions/wms/AxisOrder.java
===================================================================
--- core/trunk/src/com/vividsolutions/wms/AxisOrder.java        2016-01-10 
15:53:09 UTC (rev 4754)
+++ core/trunk/src/com/vividsolutions/wms/AxisOrder.java        2016-01-10 
16:11:37 UTC (rev 4755)
@@ -37,10 +37,12 @@
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-import java.util.Collections;
-import org.apache.log4j.Logger;
 
+import com.vividsolutions.jump.workbench.Logger;
+
+
 /**
  * An enum class with two values to determine if coordinates are given in the 
  * Longitude / Latitude order or in the Latitude / Longitude order in a 
@@ -51,7 +53,7 @@
     
     LATLON, LONLAT;
     
-    private static Logger LOG = Logger.getLogger(AxisOrder.class);
+
     public static final List<String> LATLONCRS = new ArrayList<String>();
     public static boolean initialized = false;
     
@@ -87,11 +89,11 @@
                 }
             }
             initialized = true;
-            LOG.info("LatLon CRS list has been initialized for WMS 1.3.0");
+            Logger.info("LatLon CRS list has been initialized for WMS 1.3.0");
         }
         catch(IOException ioe) {
             System.out.println("Initialization of 'latlonaxisorder.csv' failed 
!");
-            LOG.error("Initialization of 'latlonaxisorder.csv' failed !");
+            Logger.error("Initialization of 'latlonaxisorder.csv' failed !");
         }
         finally {
             if (br != null) try {br.close();} catch(IOException e){}

Modified: core/trunk/src/com/vividsolutions/wms/Capabilities.java
===================================================================
--- core/trunk/src/com/vividsolutions/wms/Capabilities.java     2016-01-10 
15:53:09 UTC (rev 4754)
+++ core/trunk/src/com/vividsolutions/wms/Capabilities.java     2016-01-10 
16:11:37 UTC (rev 4755)
@@ -131,13 +131,14 @@
     String serviceUrl = service.getServerUrl();
     // reuse servers auth if there is none in the url
     // already and the server is the same
-    if (UriUtil.urlGetUser(featureInfoURL).isEmpty()
+    if (UriUtil.isURL(featureInfoURL) && 
UriUtil.urlGetUser(featureInfoURL).isEmpty()
         && UriUtil.urlGetHost(featureInfoURL).equals(
             UriUtil.urlGetHost(serviceUrl)))
       return UriUtil.urlAddUserInfo(featureInfoURL, service.getServerUrlAsUrl()
           .getUserInfo());
     
-    return featureInfoURL;
+    // try serverurl if featinfo url is empty
+    return UriUtil.isURL(featureInfoURL) ? featureInfoURL : serviceUrl;
   }
   
   public void setGetMapURL(String url) {

Modified: core/trunk/src/com/vividsolutions/wms/FeatureInfoRequest.java
===================================================================
--- core/trunk/src/com/vividsolutions/wms/FeatureInfoRequest.java       
2016-01-10 15:53:09 UTC (rev 4754)
+++ core/trunk/src/com/vividsolutions/wms/FeatureInfoRequest.java       
2016-01-10 16:11:37 UTC (rev 4755)
@@ -8,6 +8,7 @@
 import java.util.List;
 
 import com.vividsolutions.jts.geom.Envelope;
+import com.vividsolutions.jump.workbench.Logger;
 import com.vividsolutions.jump.workbench.model.WMSLayer;
 import com.vividsolutions.jump.workbench.ui.cursortool.FeatureInfoTool;
 
@@ -91,7 +92,7 @@
 
     featInfoUrl = featInfoUrl.concat("&FEATURE_COUNT=10 ");
 
-    System.out.println(featInfoUrl);
+    Logger.trace(featInfoUrl);
     return new URL(featInfoUrl);
   }
 

Modified: core/trunk/src/com/vividsolutions/wms/IParser.java
===================================================================
--- core/trunk/src/com/vividsolutions/wms/IParser.java  2016-01-10 15:53:09 UTC 
(rev 4754)
+++ core/trunk/src/com/vividsolutions/wms/IParser.java  2016-01-10 16:11:37 UTC 
(rev 4755)
@@ -38,36 +38,16 @@
 
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.LinkedList;
-import java.util.List;
 
-import org.apache.log4j.Logger;
-import org.apache.xerces.parsers.DOMParser;
-import org.w3c.dom.CharacterData;
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.bootstrap.DOMImplementationRegistry;
-import org.w3c.dom.ls.DOMImplementationLS;
-import org.w3c.dom.ls.LSSerializer;
-import org.xml.sax.InputSource;
-import org.xml.sax.SAXException;
-
-import com.vividsolutions.jump.I18N;
-import com.vividsolutions.wms.util.XMLTools;
-
-
 /**
  * Pulls WMS objects out of the XML
+ * 
  * @author Chris Hodgson chodg...@refractions.net
  * @author Michael Michaud michael.mich...@free.fr
  */
 public interface IParser {
-    
-    public Capabilities parseCapabilities(WMService service, InputStream 
inStream) throws IOException;
-      
+
+  public Capabilities parseCapabilities(WMService service, InputStream 
inStream)
+      throws IOException;
+
 }

Modified: core/trunk/src/com/vividsolutions/wms/MapRequest.java
===================================================================
--- core/trunk/src/com/vividsolutions/wms/MapRequest.java       2016-01-10 
15:53:09 UTC (rev 4754)
+++ core/trunk/src/com/vividsolutions/wms/MapRequest.java       2016-01-10 
16:11:37 UTC (rev 4755)
@@ -34,35 +34,21 @@
 
 import static java.net.URLEncoder.encode;
 
-import java.awt.Image;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
 import java.io.UnsupportedEncodingException;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.net.URLConnection;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map.Entry;
 
-import javax.imageio.ImageIO;
+import com.vividsolutions.jump.workbench.Logger;
 
-import net.iharder.Base64;
-
-import org.apache.log4j.Logger;
-import org.openjump.util.UriUtil;
-
 /**
  * Represents all of the parameters of a getMap request from a WMS server.
  * @author Chris Hodgson chodg...@refractions.net
  */
 public class MapRequest extends AbstractWMSRequest{
-    
-    private static Logger LOG = Logger.getLogger(MapRequest.class);
-  
     private int imgWidth;
     private int imgHeight;
     private List<String> layerNames;
@@ -262,7 +248,7 @@
         try {
             urlBuf.append( "&LAYERS=" + encode(listToString( layerNames ), 
"UTF-8") );
         } catch (UnsupportedEncodingException e1) {
-            LOG.debug("UTF8 not supported by Java version", e1);
+            Logger.debug("UTF8 not supported by Java version", e1);
         }
         if( transparent ) {
             urlBuf.append( "&TRANSPARENT=TRUE" );
@@ -271,7 +257,7 @@
             try {
                 urlBuf.append( "&FORMAT=" + encode(format, "UTF-8") );
             } catch (UnsupportedEncodingException e) {
-                LOG.debug("UTF8 not supported by Java version", e);
+                Logger.debug("UTF8 not supported by Java version", e);
             }
         }
         if( bbox != null ) {
@@ -286,8 +272,8 @@
         }
         // [UT] some style info is *required*, so add this to be spec conform
         urlBuf.append( "&STYLES=" );
-//        System.out.println(urlBuf.toString());
-        LOG.info(urlBuf.toString());
+
+        Logger.trace(urlBuf.toString());
         return new URL( urlBuf.toString() );
     }
 

Modified: core/trunk/src/com/vividsolutions/wms/MapStyle.java
===================================================================
--- core/trunk/src/com/vividsolutions/wms/MapStyle.java 2016-01-10 15:53:09 UTC 
(rev 4754)
+++ core/trunk/src/com/vividsolutions/wms/MapStyle.java 2016-01-10 16:11:37 UTC 
(rev 4755)
@@ -10,8 +10,10 @@
 import javax.swing.Icon;
 import javax.swing.ImageIcon;
 
-import org.apache.log4j.Logger;
+import com.vividsolutions.jump.workbench.Logger;
 
+
+
 /*
  * Estilo asociado a una capa. Se caracteriza por tener asociado un
  * nombre, un estilo y una leyenda
@@ -20,9 +22,6 @@
  */
 public class MapStyle {
 
-    /** Log */
-    private final static Logger LOGGER = Logger.getLogger(MapStyle.class);
-
     /** Nombre asociado al estilo */
     private String name;
 
@@ -168,7 +167,7 @@
         try {
             selectedUrl = new URL(urlLegend);
         } catch (MalformedURLException e) {
-            LOGGER.error(e.getMessage());
+            Logger.error(e);
         }
 
         if (selectedUrl != null) {
@@ -178,7 +177,7 @@
                 legendIcon = new ImageIcon(image);
                 loadedIcon = true;
             } catch (IOException e) {
-                LOGGER.error(e.getMessage());
+                Logger.error(e);
             }
 
         } else {

Modified: core/trunk/src/com/vividsolutions/wms/Parser.java
===================================================================
--- core/trunk/src/com/vividsolutions/wms/Parser.java   2016-01-10 15:53:09 UTC 
(rev 4754)
+++ core/trunk/src/com/vividsolutions/wms/Parser.java   2016-01-10 16:11:37 UTC 
(rev 4755)
@@ -45,8 +45,8 @@
 import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.LinkedList;
+import java.util.List;
 
-import org.apache.log4j.Logger;
 import org.apache.xerces.parsers.DOMParser;
 import org.w3c.dom.CharacterData;
 import org.w3c.dom.Document;
@@ -61,8 +61,8 @@
 import org.xml.sax.SAXException;
 
 import com.vividsolutions.jump.I18N;
+import com.vividsolutions.jump.workbench.Logger;
 import com.vividsolutions.wms.util.XMLTools;
-import java.util.List;
 
 
 /**
@@ -70,7 +70,7 @@
  * @author Chris Hodgson chodg...@refractions.net
  */
 public class Parser {
-  private static Logger LOG = Logger.getLogger(Parser.class);
+
   /** 
    * Creates a Parser for dealing with WMS XML.
    */
@@ -199,7 +199,7 @@
         }
       } catch( Exception e ) {
           e.printStackTrace();
-        LOG.error( "Exception caught in wmsLayerFromNode(): " + e.toString() );
+        Logger.error( "Exception caught in wmsLayerFromNode(): " + 
e.toString() );
       }
     }
     


------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=267308311&iu=/4140
_______________________________________________
Jump-pilot-devel mailing list
Jump-pilot-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/jump-pilot-devel

Reply via email to