source: josm/trunk/src/org/openstreetmap/josm/io/imagery/WMSGrabber.java@ 5874

Last change on this file since 5874 was 5874, checked in by Don-vip, 11 years ago

see #8570, #7406 - I/O refactorization:

  • Move different file copy functions to Utils.copyFile (to be replaced later by Files.copy when switching to Java 7)
  • Replace all Utils.close(XXX) by Utils.close(Closeable) -> impacted plugins: commandline, mirrored_download, opendata, piclayer
  • Add new Utils.close(ZipFile)
  • Use of Utils.close almost everywhere
  • Javadoc fixes
  • Property svn:eol-style set to native
File size: 8.5 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.io.imagery;
3
4import java.awt.image.BufferedImage;
5import java.io.BufferedReader;
6import java.io.ByteArrayInputStream;
7import java.io.ByteArrayOutputStream;
8import java.io.IOException;
9import java.io.InputStream;
10import java.io.InputStreamReader;
11import java.net.HttpURLConnection;
12import java.net.MalformedURLException;
13import java.net.URL;
14import java.net.URLConnection;
15import java.text.DecimalFormat;
16import java.text.DecimalFormatSymbols;
17import java.text.NumberFormat;
18import java.util.HashMap;
19import java.util.Locale;
20import java.util.Map;
21import java.util.Map.Entry;
22import java.util.regex.Matcher;
23import java.util.regex.Pattern;
24
25import javax.imageio.ImageIO;
26
27import org.openstreetmap.josm.Main;
28import org.openstreetmap.josm.data.Version;
29import org.openstreetmap.josm.data.coor.EastNorth;
30import org.openstreetmap.josm.data.coor.LatLon;
31import org.openstreetmap.josm.data.imagery.GeorefImage.State;
32import org.openstreetmap.josm.data.imagery.ImageryInfo;
33import org.openstreetmap.josm.gui.MapView;
34import org.openstreetmap.josm.gui.layer.WMSLayer;
35import org.openstreetmap.josm.io.OsmTransferException;
36import org.openstreetmap.josm.io.ProgressInputStream;
37import org.openstreetmap.josm.tools.Utils;
38
39
40public class WMSGrabber extends Grabber {
41
42 protected String baseURL;
43 private ImageryInfo info;
44 private Map<String, String> props = new HashMap<String, String>();
45
46 public WMSGrabber(MapView mv, WMSLayer layer, boolean localOnly) {
47 super(mv, layer, localOnly);
48 this.info = layer.getInfo();
49 this.baseURL = info.getUrl();
50 if(layer.getInfo().getCookies() != null && !layer.getInfo().getCookies().equals("")) {
51 props.put("Cookie", layer.getInfo().getCookies());
52 }
53 Pattern pattern = Pattern.compile("\\{header\\(([^,]+),([^}]+)\\)\\}");
54 StringBuffer output = new StringBuffer();
55 Matcher matcher = pattern.matcher(this.baseURL);
56 while (matcher.find()) {
57 props.put(matcher.group(1),matcher.group(2));
58 matcher.appendReplacement(output, "");
59 }
60 matcher.appendTail(output);
61 this.baseURL = output.toString();
62 }
63
64 @Override
65 void fetch(WMSRequest request, int attempt) throws Exception{
66 URL url = null;
67 try {
68 url = getURL(
69 b.minEast, b.minNorth,
70 b.maxEast, b.maxNorth,
71 width(), height());
72 request.finish(State.IMAGE, grab(request, url, attempt));
73
74 } catch(Exception e) {
75 e.printStackTrace();
76 throw new Exception(e.getMessage() + "\nImage couldn't be fetched: " + (url != null ? url.toString() : ""));
77 }
78 }
79
80 public static final NumberFormat latLonFormat = new DecimalFormat("###0.0000000",
81 new DecimalFormatSymbols(Locale.US));
82
83 protected URL getURL(double w, double s,double e,double n,
84 int wi, int ht) throws MalformedURLException {
85 String myProj = Main.getProjection().toCode();
86 if (!info.getServerProjections().contains(myProj) && "EPSG:3857".equals(Main.getProjection().toCode())) {
87 LatLon sw = Main.getProjection().eastNorth2latlon(new EastNorth(w, s));
88 LatLon ne = Main.getProjection().eastNorth2latlon(new EastNorth(e, n));
89 myProj = "EPSG:4326";
90 s = sw.lat();
91 w = sw.lon();
92 n = ne.lat();
93 e = ne.lon();
94 }
95 if (myProj.equals("EPSG:4326") && !info.getServerProjections().contains(myProj) && info.getServerProjections().contains("CRS:84")) {
96 myProj = "CRS:84";
97 }
98
99 // Bounding box coordinates have to be switched for WMS 1.3.0 EPSG:4326.
100 //
101 // Background:
102 //
103 // bbox=x_min,y_min,x_max,y_max
104 //
105 // SRS=... is WMS 1.1.1
106 // CRS=... is WMS 1.3.0
107 //
108 // The difference:
109 // For SRS x is east-west and y is north-south
110 // For CRS x and y are as specified by the EPSG
111 // E.g. [1] lists lat as first coordinate axis and lot as second, so it is switched for EPSG:4326.
112 // For most other EPSG code there seems to be no difference.
113 // [1] http://www.epsg-registry.org/report.htm?type=selection&entity=urn:ogc:def:crs:EPSG::4326&reportDetail=short&style=urn:uuid:report-style:default-with-code&style_name=OGP%20Default%20With%20Code&title=EPSG:4326
114 boolean switchLatLon = false;
115 if (baseURL.toLowerCase().contains("crs=epsg:4326")) {
116 switchLatLon = true;
117 } else if (baseURL.toLowerCase().contains("crs=") && myProj.equals("EPSG:4326")) {
118 switchLatLon = true;
119 }
120 String bbox;
121 if (switchLatLon) {
122 bbox = String.format("%s,%s,%s,%s", latLonFormat.format(s), latLonFormat.format(w), latLonFormat.format(n), latLonFormat.format(e));
123 } else {
124 bbox = String.format("%s,%s,%s,%s", latLonFormat.format(w), latLonFormat.format(s), latLonFormat.format(e), latLonFormat.format(n));
125 }
126 return new URL(baseURL.replaceAll("\\{proj(\\([^})]+\\))?\\}", myProj)
127 .replaceAll("\\{bbox\\}", bbox)
128 .replaceAll("\\{w\\}", latLonFormat.format(w))
129 .replaceAll("\\{s\\}", latLonFormat.format(s))
130 .replaceAll("\\{e\\}", latLonFormat.format(e))
131 .replaceAll("\\{n\\}", latLonFormat.format(n))
132 .replaceAll("\\{width\\}", String.valueOf(wi))
133 .replaceAll("\\{height\\}", String.valueOf(ht))
134 .replace(" ", "%20"));
135 }
136
137 @Override
138 public boolean loadFromCache(WMSRequest request) {
139 BufferedImage cached = layer.cache.getExactMatch(Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth);
140
141 if (cached != null) {
142 request.finish(State.IMAGE, cached);
143 return true;
144 } else if (request.isAllowPartialCacheMatch()) {
145 BufferedImage partialMatch = layer.cache.getPartialMatch(Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth);
146 if (partialMatch != null) {
147 request.finish(State.PARTLY_IN_CACHE, partialMatch);
148 return true;
149 }
150 }
151
152 if((!request.isReal() && !layer.hasAutoDownload())){
153 request.finish(State.NOT_IN_CACHE, null);
154 return true;
155 }
156
157 return false;
158 }
159
160 protected BufferedImage grab(WMSRequest request, URL url, int attempt) throws IOException, OsmTransferException {
161 System.out.println("Grabbing WMS " + (attempt > 1? "(attempt " + attempt + ") ":"") + url);
162
163 HttpURLConnection conn = Utils.openHttpConnection(url);
164 for(Entry<String, String> e : props.entrySet()) {
165 conn.setRequestProperty(e.getKey(), e.getValue());
166 }
167 conn.setConnectTimeout(Main.pref.getInteger("socket.timeout.connect",15) * 1000);
168 conn.setReadTimeout(Main.pref.getInteger("socket.timeout.read", 30) * 1000);
169
170 String contentType = conn.getHeaderField("Content-Type");
171 if( conn.getResponseCode() != 200
172 || contentType != null && !contentType.startsWith("image") )
173 throw new IOException(readException(conn));
174
175 ByteArrayOutputStream baos = new ByteArrayOutputStream();
176 InputStream is = new ProgressInputStream(conn, null);
177 try {
178 Utils.copyStream(is, baos);
179 } finally {
180 Utils.close(is);
181 }
182
183 ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
184 BufferedImage img = layer.normalizeImage(ImageIO.read(bais));
185 bais.reset();
186 layer.cache.saveToCache(layer.isOverlapEnabled()?img:null, bais, Main.getProjection(), request.getPixelPerDegree(), b.minEast, b.minNorth);
187 return img;
188 }
189
190 protected String readException(URLConnection conn) throws IOException {
191 StringBuilder exception = new StringBuilder();
192 InputStream in = conn.getInputStream();
193 BufferedReader br = new BufferedReader(new InputStreamReader(in));
194 try {
195 String line = null;
196 while( (line = br.readLine()) != null) {
197 // filter non-ASCII characters and control characters
198 exception.append(line.replaceAll("[^\\p{Print}]", ""));
199 exception.append('\n');
200 }
201 return exception.toString();
202 } finally {
203 Utils.close(br);
204 }
205 }
206}
Note: See TracBrowser for help on using the repository browser.