Changeset 13358 in josm


Ignore:
Timestamp:
2018-01-26T23:21:57+01:00 (3 months ago)
Author:
Don-vip
Message:

fix #15830 - Support (and autodetect) WMS 1.3.0

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java

    r13230 r13358  
    1717import java.util.concurrent.TimeUnit;
    1818import java.util.regex.Matcher;
    19 import java.util.regex.Pattern;
    2019
    2120import org.apache.commons.jcs.access.behavior.ICacheAccess;
     
    5251    protected static final long ABSOLUTE_EXPIRE_TIME_LIMIT = TimeUnit.DAYS.toMillis(365);
    5352
    54     // Pattern to detect Tomcat error message. Be careful with change of format:
    55     // CHECKSTYLE.OFF: LineLength
    56     // https://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/ErrorReportValve.java?r1=1740707&r2=1779641&pathrev=1779641&diff_format=h
    57     // CHECKSTYLE.ON: LineLength
    58     protected static final Pattern TOMCAT_ERR_MESSAGE = Pattern.compile(
    59         ".*<p><b>[^<]+</b>[^<]+</p><p><b>[^<]+</b> (?:<u>)?([^<]*)(?:</u>)?</p><p><b>[^<]+</b> (?:<u>)?[^<]*(?:</u>)?</p>.*",
    60         Pattern.CASE_INSENSITIVE);
    61 
    6253    /**
    6354     * maximum download threads that will be started
     
    370361                        String data = urlConn.fetchContent();
    371362                        if (!data.isEmpty()) {
    372                             Matcher m = TOMCAT_ERR_MESSAGE.matcher(data);
     363                            Matcher m = HttpClient.getTomcatErrorMatcher(data);
    373364                            if (m.matches()) {
    374365                                attributes.setErrorMessage(m.group(1).replace("'", "''"));
  • trunk/src/org/openstreetmap/josm/io/imagery/WMSImagery.java

    r13346 r13358  
    1818import java.util.NoSuchElementException;
    1919import java.util.Set;
     20import java.util.regex.Matcher;
    2021import java.util.regex.Pattern;
    2122import java.util.stream.Collectors;
     
    121122    private URL serviceUrl;
    122123    private List<String> formats;
     124    private String version = "1.1.1";
    123125
    124126    /**
     
    136138    public URL getServiceUrl() {
    137139        return serviceUrl;
     140    }
     141
     142    /**
     143     * Returns the WMS version used.
     144     * @return the WMS version used (1.1.1 or 1.3.0)
     145     * @since 13358
     146     */
     147    public String getVersion() {
     148        return version;
    138149    }
    139150
     
    198209    public String buildGetMapUrl(Collection<LayerDetails> selectedLayers, String format) {
    199210        return buildRootUrl() + "FORMAT=" + format + (imageFormatHasTransparency(format) ? "&TRANSPARENT=TRUE" : "")
    200                 + "&VERSION=1.1.1&SERVICE=WMS&REQUEST=GetMap&LAYERS="
     211                + "&VERSION=" + version + "&SERVICE=WMS&REQUEST=GetMap&LAYERS="
    201212                + selectedLayers.stream().map(x -> x.ident).collect(Collectors.joining(","))
    202                 + "&STYLES=&SRS={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}";
     213                + "&STYLES=&" + ("1.3.0".equals(version) ? "CRS" : "SRS") + "={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}";
    203214    }
    204215
     
    238249    }
    239250
     251    /**
     252     * Attempts WMS GetCapabilities with version 1.1.1 first, then 1.3.0 in case of specific errors.
     253     * @param serviceUrlStr WMS service URL
     254     * @param getCapabilitiesUrl GetCapabilities URL
     255     * @throws IOException if any I/O error occurs
     256     * @throws WMSGetCapabilitiesException if any HTTP or parsing error occurs
     257     */
    240258    private void doAttemptGetCapabilities(String serviceUrlStr, URL getCapabilitiesUrl)
    241259            throws IOException, WMSGetCapabilitiesException {
     260        final String url = getCapabilitiesUrl.toExternalForm();
    242261        final Response response = HttpClient.create(getCapabilitiesUrl).connect();
    243262
     263        // Is the HTTP connection successul ?
    244264        if (response.getResponseCode() >= 400) {
    245             throw new WMSGetCapabilitiesException(response.getResponseMessage(), response.fetchContent());
     265            // HTTP error for servers handling only WMS 1.3.0 ?
     266            String errorMessage = response.getResponseMessage();
     267            String errorContent = response.fetchContent();
     268            Matcher tomcat = HttpClient.getTomcatErrorMatcher(errorContent);
     269            boolean messageAbout130 = errorMessage != null && errorMessage.contains("1.3.0");
     270            boolean contentAbout130 = errorContent != null && tomcat != null && tomcat.matches() && tomcat.group(1).contains("1.3.0");
     271            if (url.contains("VERSION=1.1.1") && (messageAbout130 || contentAbout130)) {
     272                doAttemptGetCapabilities130(serviceUrlStr, url);
     273                return;
     274            }
     275            throw new WMSGetCapabilitiesException(errorMessage, errorContent);
    246276        }
    247277
    248278        try {
     279            // Parse XML capabilities sent by the server
    249280            parseCapabilities(serviceUrlStr, response.getContent());
    250281        } catch (WMSGetCapabilitiesException e) {
    251             String url = getCapabilitiesUrl.toExternalForm();
    252282            // ServiceException for servers handling only WMS 1.3.0 ?
    253283            if (e.getCause() == null && url.contains("VERSION=1.1.1")) {
    254                 doAttemptGetCapabilities(serviceUrlStr, new URL(url.replace("VERSION=1.1.1", "VERSION=1.3.0")));
    255                 if (serviceUrl.toExternalForm().contains("VERSION=1.1.1")) {
    256                     serviceUrl = new URL(serviceUrl.toExternalForm().replace("VERSION=1.1.1", "VERSION=1.3.0"));
    257                 }
     284                doAttemptGetCapabilities130(serviceUrlStr, url);
    258285            } else {
    259286                throw e;
    260287            }
    261288        }
     289    }
     290
     291    /**
     292     * Attempts WMS GetCapabilities with version 1.3.0.
     293     * @param serviceUrlStr WMS service URL
     294     * @param url GetCapabilities URL
     295     * @throws IOException if any I/O error occurs
     296     * @throws WMSGetCapabilitiesException if any HTTP or parsing error occurs
     297     * @throws MalformedURLException in case of invalid URL
     298     */
     299    private void doAttemptGetCapabilities130(String serviceUrlStr, final String url)
     300            throws IOException, WMSGetCapabilitiesException, MalformedURLException {
     301        doAttemptGetCapabilities(serviceUrlStr, new URL(url.replace("VERSION=1.1.1", "VERSION=1.3.0")));
     302        if (serviceUrl.toExternalForm().contains("VERSION=1.1.1")) {
     303            serviceUrl = new URL(serviceUrl.toExternalForm().replace("VERSION=1.1.1", "VERSION=1.3.0"));
     304        }
     305        version = "1.3.0";
    262306    }
    263307
  • trunk/src/org/openstreetmap/josm/tools/HttpClient.java

    r13179 r13358  
    6161    private boolean finishOnCloseOutput = true;
    6262
     63    // Pattern to detect Tomcat error message. Be careful with change of format:
     64    // CHECKSTYLE.OFF: LineLength
     65    // https://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/valves/ErrorReportValve.java?r1=1740707&r2=1779641&pathrev=1779641&diff_format=h
     66    // CHECKSTYLE.ON: LineLength
     67    private static final Pattern TOMCAT_ERR_MESSAGE = Pattern.compile(
     68        ".*<p><b>[^<]+</b>[^<]+</p><p><b>[^<]+</b> (?:<u>)?([^<]*)(?:</u>)?</p><p><b>[^<]+</b> (?:<u>)?[^<]*(?:</u>)?</p>.*",
     69        Pattern.CASE_INSENSITIVE);
     70
    6371    static {
    6472        CookieHandler.setDefault(new CookieManager());
     
    687695        }
    688696    }
     697
     698    /**
     699     * Returns a {@link Matcher} against predefined Tomcat error messages.
     700     * If it matches, error message can be extracted from {@code group(1)}.
     701     * @param data HTML contents to check
     702     * @return a {@link Matcher} against predefined Tomcat error messages
     703     * @since 13358
     704     */
     705    public static Matcher getTomcatErrorMatcher(String data) {
     706        return data != null ? TOMCAT_ERR_MESSAGE.matcher(data) : null;
     707    }
    689708}
  • trunk/test/functional/org/openstreetmap/josm/tools/HttpClientTest.java

    r12807 r13358  
    55import static org.hamcrest.CoreMatchers.is;
    66import static org.hamcrest.CoreMatchers.nullValue;
     7import static org.junit.Assert.assertEquals;
    78import static org.junit.Assert.assertThat;
     9import static org.junit.Assert.assertTrue;
    810
    911import java.io.BufferedReader;
     
    1517import java.util.logging.Handler;
    1618import java.util.logging.LogRecord;
     19import java.util.regex.Matcher;
    1720
    1821import javax.json.JsonObject;
     
    298301        }
    299302    }
     303
     304    /**
     305     * Test that error message sent by Tomcat can be parsed.
     306     */
     307    @Test
     308    public void testTomcatErrorMessage() {
     309        Matcher m = HttpClient.getTomcatErrorMatcher(
     310            "<html><head><title>Apache Tomcat/DGFiP - Rapport d''erreur</title><style><!--"+
     311                "H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} "+
     312                "H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} "+
     313                "H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} "+
     314                "BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} "+
     315                "B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} "+
     316                "P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}"+
     317                "A {color : black;}A.name {color : black;}HR {color : #525D76;}"+
     318            "--></style> </head><body><h1>Etat HTTP 400 - La commune demandée n'existe pas ou n'est pas accessible.</h1>"+
     319            "<HR size=\"1\" noshade=\"noshade\">"+
     320            "<p><b>type</b> Rapport d''état</p><p><b>message</b> <u>La commune demandée n'existe pas ou n'est pas accessible.</u></p>"+
     321            "<p><b>description</b> <u>La requête envoyée par le client était syntaxiquement incorrecte.</u></p>"+
     322            "<HR size=\"1\" noshade=\"noshade\"><h3>Apache Tomcat/DGFiP</h3></body></html>");
     323        assertTrue(m.matches());
     324        assertEquals("La commune demandée n'existe pas ou n'est pas accessible.", m.group(1));
     325    }
    300326}
  • trunk/test/unit/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJobTest.java

    r13230 r13358  
    44import static org.junit.Assert.assertEquals;
    55import static org.junit.Assert.assertFalse;
    6 import static org.junit.Assert.assertTrue;
    76
    87import java.io.IOException;
     
    109import java.net.URL;
    1110import java.nio.charset.StandardCharsets;
    12 import java.util.regex.Matcher;
    1311
    1412import org.apache.commons.jcs.access.behavior.ICacheAccess;
     
    173171        return JCSCacheManager.getCache("test");
    174172    }
    175 
    176     /**
    177      * Test that error message sent by Tomcat can be parsed.
    178      */
    179     @Test
    180     public void testTomcatErrorMessage() {
    181         Matcher m = JCSCachedTileLoaderJob.TOMCAT_ERR_MESSAGE.matcher(
    182             "<html><head><title>Apache Tomcat/DGFiP - Rapport d''erreur</title><style><!--"+
    183                 "H1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} "+
    184                 "H2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} "+
    185                 "H3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} "+
    186                 "BODY {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} "+
    187                 "B {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} "+
    188                 "P {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;}"+
    189                 "A {color : black;}A.name {color : black;}HR {color : #525D76;}"+
    190             "--></style> </head><body><h1>Etat HTTP 400 - La commune demandée n'existe pas ou n'est pas accessible.</h1>"+
    191             "<HR size=\"1\" noshade=\"noshade\">"+
    192             "<p><b>type</b> Rapport d''état</p><p><b>message</b> <u>La commune demandée n'existe pas ou n'est pas accessible.</u></p>"+
    193             "<p><b>description</b> <u>La requête envoyée par le client était syntaxiquement incorrecte.</u></p>"+
    194             "<HR size=\"1\" noshade=\"noshade\"><h3>Apache Tomcat/DGFiP</h3></body></html>");
    195         assertTrue(m.matches());
    196         assertEquals("La commune demandée n'existe pas ou n'est pas accessible.", m.group(1));
    197     }
    198173}
Note: See TracChangeset for help on using the changeset viewer.