Ticket #13118: 13118.patch
File 13118.patch, 23.1 KB (added by , 8 years ago) |
---|
-
src/org/openstreetmap/josm/actions/AddImageryLayerAction.java
commit 609bb4918526fa89ac5ddc86e5a2f205cbd5a488 Author: Simon Legner <Simon.Legner@gmail.com> Date: Tue Sep 27 15:39:14 2016 +0200 see #13118 - WMSImagery: retain specified version for URL generation diff --git a/src/org/openstreetmap/josm/actions/AddImageryLayerAction.java b/src/org/openstreetmap/josm/actions/AddImageryLayerAction.java index 32eb835..5a46619 100644
a b 10 10 import java.awt.event.ActionEvent; 11 11 import java.io.IOException; 12 12 import java.net.MalformedURLException; 13 import java.net.URISyntaxException; 13 14 import java.util.HashSet; 14 15 import java.util.List; 15 16 import java.util.Set; … … protected ImageryInfo getWMSLayerInfo() { 131 132 } 132 133 ret.setServerProjections(supportedCrs); 133 134 return ret; 134 } catch (MalformedURLException ex) {135 } catch (MalformedURLException | URISyntaxException ex) { 135 136 if (!GraphicsEnvironment.isHeadless()) { 136 137 JOptionPane.showMessageDialog(Main.parent, tr("Invalid service URL."), 137 138 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); -
src/org/openstreetmap/josm/gui/preferences/imagery/AddWMSLayerPanel.java
diff --git a/src/org/openstreetmap/josm/gui/preferences/imagery/AddWMSLayerPanel.java b/src/org/openstreetmap/josm/gui/preferences/imagery/AddWMSLayerPanel.java index 049b36e..63b39a8 100644
a b 5 5 6 6 import java.io.IOException; 7 7 import java.net.MalformedURLException; 8 import java.net.URISyntaxException; 8 9 import java.net.URL; 9 10 import java.util.List; 10 11 … … public AddWMSLayerPanel() { 76 77 List<String> wmsFormats = wms.getFormats(); 77 78 formats.setModel(new DefaultComboBoxModel<>(wmsFormats.toArray(new String[wmsFormats.size()]))); 78 79 formats.setSelectedItem(wms.getPreferredFormats()); 79 } catch (MalformedURLException ex1) {80 } catch (MalformedURLException | URISyntaxException ex1) { 80 81 Main.error(ex1, false); 81 82 JOptionPane.showMessageDialog(getParent(), tr("Invalid service URL."), 82 83 tr("WMS Error"), JOptionPane.ERROR_MESSAGE); -
src/org/openstreetmap/josm/io/imagery/WMSImagery.java
diff --git a/src/org/openstreetmap/josm/io/imagery/WMSImagery.java b/src/org/openstreetmap/josm/io/imagery/WMSImagery.java index b21afa3..f9fca14 100644
a b 5 5 import java.io.IOException; 6 6 import java.io.StringReader; 7 7 import java.net.MalformedURLException; 8 import java.net.URI; 9 import java.net.URISyntaxException; 8 10 import java.net.URL; 9 11 import java.util.ArrayList; 10 12 import java.util.Collection; … … 13 15 import java.util.Iterator; 14 16 import java.util.List; 15 17 import java.util.Locale; 18 import java.util.Map; 16 19 import java.util.NoSuchElementException; 17 20 import java.util.Set; 18 import java.util.regex.Pattern;19 21 import java.util.stream.Collectors; 20 22 import java.util.stream.Stream; 21 23 import java.util.stream.StreamSupport; … … 29 31 import org.openstreetmap.josm.data.imagery.ImageryInfo; 30 32 import org.openstreetmap.josm.data.projection.Projections; 31 33 import org.openstreetmap.josm.tools.HttpClient; 34 import org.openstreetmap.josm.tools.HttpUrl; 32 35 import org.openstreetmap.josm.tools.Utils; 33 36 import org.w3c.dom.Document; 34 37 import org.w3c.dom.Element; … … public String getIncomingData() { 110 113 } 111 114 112 115 private List<LayerDetails> layers; 113 private URLserviceUrl;116 private HttpUrl serviceUrl; 114 117 private List<String> formats; 115 118 116 119 /** … … public String getIncomingData() { 126 129 * @return the service URL 127 130 */ 128 131 public URL getServiceUrl() { 129 return serviceUrl; 132 try { 133 return serviceUrl == null ? null : serviceUrl.toURL(); 134 } catch (MalformedURLException e) { 135 Main.warn(e); 136 return null; 137 } 130 138 } 131 139 132 140 /** … … public URL getServiceUrl() { 138 146 } 139 147 140 148 /** 141 * Gets the pref fered format for this imagery layer.142 * @return The pref fered format as mime type.149 * Gets the preferred format for this imagery layer. 150 * @return The preferred format as mime type. 143 151 */ 144 152 public String getPreferredFormats() { 145 153 if (formats.contains("image/jpeg")) { … … public String getPreferredFormats() { 153 161 } 154 162 } 155 163 156 String buildRootUrl() {157 if (serviceUrl == null) {158 return null;159 }160 StringBuilder a = new StringBuilder(serviceUrl.getProtocol());161 a.append("://").append(serviceUrl.getHost());162 if (serviceUrl.getPort() != -1) {163 a.append(':').append(serviceUrl.getPort());164 }165 a.append(serviceUrl.getPath()).append('?');166 if (serviceUrl.getQuery() != null) {167 a.append(serviceUrl.getQuery());168 if (!serviceUrl.getQuery().isEmpty() && !serviceUrl.getQuery().endsWith("&")) {169 a.append('&');170 }171 }172 return a.toString();173 }174 175 164 public String buildGetMapUrl(Collection<LayerDetails> selectedLayers) { 176 165 return buildGetMapUrl(selectedLayers, "image/jpeg"); 177 166 } 178 167 179 168 public String buildGetMapUrl(Collection<LayerDetails> selectedLayers, String format) { 180 return buildRootUrl() + "FORMAT=" + format + (imageFormatHasTransparency(format) ? "&TRANSPARENT=TRUE" : "") 181 + "&VERSION=1.1.1&SERVICE=WMS&REQUEST=GetMap&LAYERS=" 182 + selectedLayers.stream().map(x -> x.ident).collect(Collectors.joining(",")) 169 serviceUrl.putQueryParameter("REQUEST", "GetMap"); 170 serviceUrl.putQueryParameter("FORMAT", format); 171 serviceUrl.putQueryParameter("TRANSPARENT", imageFormatHasTransparency(format) ? "TRUE" : ""); 172 serviceUrl.putQueryParameter("LAYERS", selectedLayers.stream().map(x -> x.ident).collect(Collectors.joining(","))); 173 return serviceUrl.toString() 183 174 + "&STYLES=&SRS={proj}&WIDTH={width}&HEIGHT={height}&BBOX={bbox}"; 184 175 } 185 176 186 public void attemptGetCapabilities(String serviceUrlStr) throws IOException, WMSGetCapabilitiesException { 187 URL getCapabilitiesUrl = null; 177 public void attemptGetCapabilities(final String serviceUrlStr) throws IOException, WMSGetCapabilitiesException, URISyntaxException { 188 178 try { 189 if (!Pattern.compile(".*GetCapabilities.*", Pattern.CASE_INSENSITIVE).matcher(serviceUrlStr).matches()) { 179 final URL url = new URL(serviceUrlStr); // causing MalformedURLException on invalid input 180 final HttpUrl getCapabilitiesUrl = new HttpUrl(url.toURI(), false); 181 if (!"GetCapabilities".equals(getCapabilitiesUrl.getQueryParameter("REQUEST"))) { 190 182 // If the url doesn't already have GetCapabilities, add it in 191 getCapabilitiesUrl = new URL(serviceUrlStr); 192 final String getCapabilitiesQuery = "VERSION=1.1.1&SERVICE=WMS&REQUEST=GetCapabilities"; 193 if (getCapabilitiesUrl.getQuery() == null) { 194 getCapabilitiesUrl = new URL(serviceUrlStr + '?' + getCapabilitiesQuery); 195 } else if (!getCapabilitiesUrl.getQuery().isEmpty() && !getCapabilitiesUrl.getQuery().endsWith("&")) { 196 getCapabilitiesUrl = new URL(serviceUrlStr + '&' + getCapabilitiesQuery); 197 } else { 198 getCapabilitiesUrl = new URL(serviceUrlStr + getCapabilitiesQuery); 183 getCapabilitiesUrl.putQueryParameter("REQUEST", "GetCapabilities"); 184 if (!getCapabilitiesUrl.containsQueryParameter("SERVICE")) { 185 getCapabilitiesUrl.putQueryParameter("SERVICE", "WMS"); 186 } 187 if (!getCapabilitiesUrl.containsQueryParameter("VERSION")) { 188 getCapabilitiesUrl.putQueryParameter("VERSION", "1.1.1"); 199 189 } 200 190 } else { 201 191 // Otherwise assume it's a good URL and let the subsequent error 202 192 // handling systems deal with problems 203 getCapabilitiesUrl = new URL(serviceUrlStr);204 193 } 205 serviceUrl = new URL(serviceUrlStr);194 serviceUrl = getCapabilitiesUrl; 206 195 } catch (HeadlessException e) { 207 196 Main.warn(e); 208 197 return; 209 198 } 210 199 211 final String incomingData = HttpClient.create( getCapabilitiesUrl).connect().fetchContent();200 final String incomingData = HttpClient.create(serviceUrl.toURL()).connect().fetchContent(); 212 201 Main.debug("Server response to Capabilities request:"); 213 202 Main.debug(incomingData); 214 203 … … public void attemptGetCapabilities(String serviceUrlStr) throws IOException, WMS 244 233 String baseURL = child.getAttribute("xlink:href"); 245 234 if (baseURL != null && !baseURL.equals(serviceUrlStr)) { 246 235 Main.info("GetCapabilities specifies a different service URL: " + baseURL); 247 serviceUrl = new URL(baseURL); 236 final Map<String, String> parameters = serviceUrl.getQueryParameters(); 237 serviceUrl = new HttpUrl(URI.create(baseURL), false); 238 serviceUrl.putQueryParameters(parameters); 248 239 } 249 240 } 250 241 -
src/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandler.java
diff --git a/src/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandler.java b/src/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandler.java index cd83e6d..afd8f17 100644
a b 19 19 20 20 import org.openstreetmap.josm.Main; 21 21 import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault; 22 import org.openstreetmap.josm.tools.HttpUrl; 22 23 import org.openstreetmap.josm.tools.Utils; 23 24 24 25 /** … … public void setUrl(String url) throws RequestHandlerBadRequestException { 195 196 * @throws URISyntaxException if request URL is invalid 196 197 */ 197 198 protected void parseArgs() throws URISyntaxException { 198 this.args = getRequestParameter(new URI(this.request)); 199 } 200 201 /** 202 * Returns the request parameters. 203 * @param uri URI as string 204 * @return map of request parameters 205 * @see <a href="http://blog.lunatech.com/2009/02/03/what-every-web-developer-must-know-about-url-encoding"> 206 * What every web developer must know about URL encoding</a> 207 */ 208 static Map<String, String> getRequestParameter(URI uri) { 209 Map<String, String> r = new HashMap<>(); 210 if (uri.getRawQuery() == null) { 211 return r; 212 } 213 for (String kv : uri.getRawQuery().split("&")) { 214 final String[] kvs = Utils.decodeUrl(kv).split("=", 2); 215 r.put(kvs[0], kvs.length > 1 ? kvs[1] : null); 216 } 217 return r; 199 this.args = HttpUrl.getQueryParameter(new URI(this.request), true); 218 200 } 219 201 220 202 void checkMandatoryParams() throws RequestHandlerBadRequestException { -
new file src/org/openstreetmap/josm/tools/HttpUrl.java
diff --git a/src/org/openstreetmap/josm/tools/HttpUrl.java b/src/org/openstreetmap/josm/tools/HttpUrl.java new file mode 100644 index 0000000..ec11531
- + 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm.tools; 3 4 import java.net.MalformedURLException; 5 import java.net.URI; 6 import java.net.URISyntaxException; 7 import java.net.URL; 8 import java.util.Collections; 9 import java.util.Comparator; 10 import java.util.Map; 11 import java.util.TreeMap; 12 import java.util.stream.Collectors; 13 14 /** 15 * This class allows building HTTP URLs with query parameters. 16 * @since 11059 17 */ 18 public class HttpUrl { 19 20 private final URI uri; 21 private final Map<String, String> query; 22 23 /** 24 * Creates a new instance from the specified URI 25 * @param uri the URI 26 * @param caseSensitive whether query parameters are considered case sensitive 27 */ 28 public HttpUrl(URI uri, boolean caseSensitive) { 29 this.uri = uri; 30 this.query = getQueryParameter(uri, caseSensitive); 31 } 32 33 /** 34 * Returns the request query parameter. 35 * @param uri the URI 36 * @return map of request parameters 37 * @see <a href="https://www.talisman.org/~erlkonig/misc/lunatech%5ewhat-every-webdev-must-know-about-url-encoding/"> 38 * What every web developer must know about URL encoding</a> 39 */ 40 public static Map<String, String> getQueryParameter(URI uri, boolean caseSensitive) { 41 Map<String, String> r = new TreeMap<>(caseSensitive ? Comparator.<String>naturalOrder() : String.CASE_INSENSITIVE_ORDER); 42 if (uri.getRawQuery() == null) { 43 return r; 44 } 45 for (String kv : uri.getRawQuery().split("&")) { 46 if (kv.isEmpty()) { 47 continue; 48 } 49 final String[] kvs = Utils.decodeUrl(kv).split("=", 2); 50 r.put(kvs[0], kvs.length > 1 ? kvs[1] : null); 51 } 52 return r; 53 } 54 55 /** 56 * Tests whether the query parameter {@code key} is present 57 * @param key the query parameter 58 * @return true if the query parameter {@code key} is present 59 */ 60 public boolean containsQueryParameter(String key) { 61 return query.containsKey(key); 62 } 63 64 /** 65 * Returns the value for the query parameter {@code key} 66 * @param key the query parameter 67 * @return the value for the query parameter 68 */ 69 public String getQueryParameter(String key) { 70 return query.get(key); 71 } 72 73 /** 74 * Returns a map of all query parameters 75 * @return a map of all query parameters 76 */ 77 public Map<String, String> getQueryParameters() { 78 return Collections.unmodifiableMap(query); 79 } 80 81 /** 82 * Sets the the value for the query parameter {@code key} 83 * @param key the query parameter 84 * @param value the value for the query parameter 85 * @return the old value for the query parameter, or {@code null} 86 */ 87 public String putQueryParameter(String key, String value) { 88 return query.put(key, value); 89 } 90 91 /** 92 * Sets all query parameters 93 * @param parameters the query parameters 94 */ 95 public void putQueryParameters(Map<? extends String, ? extends String> parameters) { 96 query.putAll(parameters); 97 } 98 99 /** 100 * Constructs a URI from this. 101 * @return a URI 102 */ 103 public URI toURI() { 104 final String query = this.query.entrySet().stream() 105 .map(entry -> entry.getKey() + "=" + entry.getValue()) 106 .collect(Collectors.joining("&")); 107 try { 108 return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), query, uri.getFragment()); 109 } catch (URISyntaxException ex) { 110 throw new RuntimeException(ex); 111 } 112 } 113 114 /** 115 * Constructs a URL from this. 116 * @return a URL 117 * @throws MalformedURLException If a protocol handler for the URL could not be found, or if some other error occurred while constructing the URL 118 */ 119 public URL toURL() throws MalformedURLException { 120 return toURI().toURL(); 121 } 122 123 @Override 124 public String toString() { 125 return toURI().toString(); 126 } 127 } -
.java
diff --git a/test/unit/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandlerTest.java b/test/unit/org/openstreetmap/josm/tools/HttpUrlTest.java similarity index 55% rename from test/unit/org/openstreetmap/josm/io/remotecontrol/handler/RequestHandlerTest.java rename to test/unit/org/openstreetmap/josm/tools/HttpUrlTest.java index eb342d6..f121a09 100644
old new 1 1 // License: GPL. For details, see LICENSE file. 2 package org.openstreetmap.josm. io.remotecontrol.handler;2 package org.openstreetmap.josm.tools; 3 3 4 4 import static org.junit.Assert.assertEquals; 5 import static org.junit.Assert.assertTrue; 5 6 7 import java.net.URI; 8 import java.net.URL; 6 9 import java.util.Collections; 7 10 import java.util.HashMap; 8 11 import java.util.Map; 9 12 10 13 import org.junit.Test; 11 import org.openstreetmap.josm.io.remotecontrol.PermissionPrefWithDefault;12 import org.openstreetmap.josm.io.remotecontrol.handler.RequestHandler.RequestHandlerBadRequestException;13 14 14 15 /** 15 * Unit tests of {@link RequestHandler} class.16 * Unit tests of {@link HttpUrl} class. 16 17 */ 17 public class RequestHandlerTest {18 public class HttpUrlTest { 18 19 19 Map<String, String> getRequestParameter(String url) throws RequestHandlerBadRequestException { 20 final RequestHandler req = new RequestHandler() { 21 @Override 22 protected void validateRequest() throws RequestHandlerBadRequestException { 23 } 24 25 @Override 26 protected void handleRequest() throws RequestHandlerErrorException, RequestHandlerBadRequestException { 27 } 28 29 @Override 30 public String getPermissionMessage() { 31 return null; 32 } 33 34 @Override 35 public PermissionPrefWithDefault getPermissionPref() { 36 return null; 37 } 20 private static Map<String, String> getRequestParameter(String url) { 21 return HttpUrl.getQueryParameter(URI.create(url), true); 22 } 38 23 39 @Override 40 public String[] getMandatoryParams() { 41 return new String[0]; 42 } 43 }; 44 req.setUrl(url); 45 return req.args; 24 /** 25 * Test request parameter - case 1 26 */ 27 @Test 28 public void testRequestParameter0() { 29 final Map<String, String> expected = new HashMap<>(); 30 assertEquals(expected, getRequestParameter("http://example.com/")); 31 assertEquals(expected, getRequestParameter("http://example.com/?")); 32 assertEquals(expected, getRequestParameter("http://example.com/#foobar")); 46 33 } 47 34 48 35 /** 49 36 * Test request parameter - case 1 50 * @throws RequestHandlerBadRequestException never51 37 */ 52 38 @Test 53 public void testRequestParameter1() throws RequestHandlerBadRequestException{39 public void testRequestParameter1() { 54 40 final Map<String, String> expected = new HashMap<>(); 55 41 expected.put("query", "a"); 56 42 expected.put("b", "=c"); … … public void testRequestParameter1() throws RequestHandlerBadRequestException { 59 45 60 46 /** 61 47 * Test request parameter - case 2 62 * @throws RequestHandlerBadRequestException never63 48 */ 64 49 @Test 65 public void testRequestParameter2() throws RequestHandlerBadRequestException{50 public void testRequestParameter2() { 66 51 assertEquals(Collections.singletonMap("query", "a&b==c"), 67 52 getRequestParameter("http://example.com/?query=a%26b==c")); 68 53 } 69 54 70 55 /** 71 56 * Test request parameter - case 3 72 * @throws RequestHandlerBadRequestException never73 57 */ 74 58 @Test 75 public void testRequestParameter3() throws RequestHandlerBadRequestException{59 public void testRequestParameter3() { 76 60 assertEquals(Collections.singleton("blue+light blue"), 77 61 getRequestParameter("http://example.com/blue+light%20blue?blue%2Blight+blue").keySet()); 78 62 } 79 63 80 64 /** 81 65 * Test request parameter - case 4 82 * @see <a href="http ://blog.lunatech.com/2009/02/03/what-every-web-developer-must-know-about-url-encoding">66 * @see <a href="https://www.talisman.org/~erlkonig/misc/lunatech%5ewhat-every-webdev-must-know-about-url-encoding/"> 83 67 * What every web developer must know about URL encoding</a> 84 * @throws RequestHandlerBadRequestException never85 68 */ 86 69 @Test 87 public void testRequestParameter4() throws RequestHandlerBadRequestException{70 public void testRequestParameter4() { 88 71 assertEquals(Collections.singletonMap("/?:@-._~!$'()* ,;", "/?:@-._~!$'()* ,;=="), getRequestParameter( 89 72 // CHECKSTYLE.OFF: LineLength 90 73 "http://example.com/:@-._~!$&'()*+,=;:@-._~!$&'()*+,=:@-._~!$&'()*+,==?/?:@-._~!$'()*+,;=/?:@-._~!$'()*+,;==#/?:@-._~!$&'()*+,;=")); … … public void testRequestParameter4() throws RequestHandlerBadRequestException { 93 76 94 77 /** 95 78 * Test request parameter - case 5 96 * @throws RequestHandlerBadRequestException never97 79 */ 98 80 @Test 99 public void testRequestParameter5() throws RequestHandlerBadRequestException{81 public void testRequestParameter5() { 100 82 final Map<String, String> expected = new HashMap<>(); 101 83 expected.put("space", " "); 102 84 expected.put("tab", "\t"); … … public void testRequestParameter5() throws RequestHandlerBadRequestException { 105 87 106 88 /** 107 89 * Test request parameter - case 6 108 * @throws RequestHandlerBadRequestException never109 90 */ 110 91 @Test 111 public void testRequestParameter6() throws RequestHandlerBadRequestException{92 public void testRequestParameter6() { 112 93 final Map<String, String> expected = new HashMap<>(); 113 94 expected.put("addtags", "wikipedia:de=Weiße_Gasse|maxspeed=5"); 114 95 expected.put("select", "way23071688,way23076176,way23076177,"); … … public void testRequestParameter6() throws RequestHandlerBadRequestException { 124 105 125 106 /** 126 107 * Test request parameter - invalid case 127 * @throws RequestHandlerBadRequestException always128 108 */ 129 @Test(expected = RequestHandlerBadRequestException.class)130 public void testRequestParameterInvalid() throws RequestHandlerBadRequestException{109 @Test(expected = IllegalArgumentException.class) 110 public void testRequestParameterInvalid() { 131 111 getRequestParameter("http://localhost:8111/load_and_zoom"+ 132 112 "?addtags=wikipedia:de=Wei%C3%9Fe_Gasse|maxspeed=5"+ 133 113 "&select=way23071688,way23076176,way23076177,"+ 134 114 "&left=13.739727546842&right=13.740890970188&top=51.049987191025&bottom=51.048466954325"); 135 115 } 116 117 /** 118 * Test request parameter changing 119 */ 120 @Test 121 public void testSettingQueryParameter() throws Exception { 122 final HttpUrl url = new HttpUrl(URI.create("https://www.wms.com/guest?VERSION=1.3&SERVICE=WMS&REQUEST=GetCapabilities"), true); 123 assertEquals("https://www.wms.com/guest?REQUEST=GetCapabilities&SERVICE=WMS&VERSION=1.3", url.toString()); 124 assertTrue(url.containsQueryParameter("REQUEST")); 125 assertEquals("GetCapabilities", url.getQueryParameter("REQUEST")); 126 url.putQueryParameter("REQUEST", "GetMap"); 127 assertEquals("https://www.wms.com/guest?REQUEST=GetMap&SERVICE=WMS&VERSION=1.3", url.toString()); 128 assertEquals("{REQUEST=GetMap, SERVICE=WMS, VERSION=1.3}", url.getQueryParameters().toString()); 129 } 130 131 @Test 132 public void testUrlUnchanged() throws Exception { 133 final URL url1 = new URL("http://example.com/:@-._~!$&'()*+,=;:@-._~!$&'()*+,=:@-._~!$&'()*+,==?/?" + 134 ":@-._~!$'()*%20,;=/?:@-._~!$'()*%20,;==#/?:@-._~!$&'()*+,;="); 135 final URL uri2 = new HttpUrl(url1.toURI(), true).toURL(); 136 assertEquals(url1, uri2); 137 } 136 138 }