Changeset 8344 in josm for trunk


Ignore:
Timestamp:
2015-05-10T13:27:54+02:00 (4 years ago)
Author:
bastiK
Message:

applied #10454 - Mapbox "empty" tile (imagery with zoom level > 17) (patch by wiktorn)

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/data/maps.xsd

    r8063 r8344  
    671671                                                                </xs:complexType>
    672672                                                        </xs:element>
     673                                                        <xs:element name="no-tile-header" minOccurs="0" maxOccurs="unbounded">
     674                                                                <xs:complexType>
     675                                                                        <xs:attribute name="name" type="xs:string" />
     676                                                                        <xs:attribute name="value" type="xs:string" />
     677                                                                </xs:complexType>
     678                                                        </xs:element>
    673679                                                </xs:choice>
    674680                                        </xs:sequence>
  • trunk/src/org/openstreetmap/josm/data/Preferences.java

    r8339 r8344  
    1414import java.io.PrintWriter;
    1515import java.io.Reader;
     16import java.io.StringReader;
     17import java.io.StringWriter;
    1618import java.lang.annotation.Retention;
    1719import java.lang.annotation.RetentionPolicy;
     
    2224import java.util.Collection;
    2325import java.util.Collections;
     26import java.util.HashMap;
    2427import java.util.HashSet;
    2528import java.util.Iterator;
     
    3841import java.util.regex.Pattern;
    3942
     43import javax.json.Json;
     44import javax.json.JsonObject;
     45import javax.json.JsonObjectBuilder;
     46import javax.json.JsonReader;
     47import javax.json.JsonValue;
     48import javax.json.JsonWriter;
    4049import javax.swing.JOptionPane;
    4150import javax.swing.UIManager;
     
    12661275    }
    12671276
     1277    @SuppressWarnings("rawtypes")
     1278    private static String mapToJson(Map map) {
     1279        StringWriter stringWriter = new StringWriter();
     1280        try (JsonWriter writer = Json.createWriter(stringWriter)) {
     1281            JsonObjectBuilder object = Json.createObjectBuilder();
     1282            for(Object o: map.entrySet()) {
     1283                Entry e = (Entry) o;
     1284                object.add(e.getKey().toString(), e.getValue().toString());
     1285            }
     1286            writer.writeObject(object.build());
     1287        }
     1288        return stringWriter.toString();
     1289    }
     1290
     1291    @SuppressWarnings({ "rawtypes", "unchecked" })
     1292    private static Map mapFromJson(String s) {
     1293        Map ret = null;
     1294        try (JsonReader reader = Json.createReader(new StringReader(s))) {
     1295            JsonObject object = reader.readObject();
     1296            ret = new HashMap(object.size());
     1297            for (Entry<String, JsonValue> e: object.entrySet()) {
     1298                ret.put(e.getKey(), e.getValue().toString());
     1299            }
     1300        }
     1301        return ret;
     1302    }
     1303
    12681304    public static <T> Map<String,String> serializeStruct(T struct, Class<T> klass) {
    12691305        T structPrototype;
     
    12851321                if (fieldValue != null) {
    12861322                    if (f.getAnnotation(writeExplicitly.class) != null || !Objects.equals(fieldValue, defaultFieldValue)) {
    1287                         hash.put(f.getName().replace("_", "-"), fieldValue.toString());
     1323                        String key = f.getName().replace("_", "-");
     1324                        if (fieldValue instanceof Map) {
     1325                            hash.put(key, mapToJson((Map) fieldValue));
     1326                        } else {
     1327                            hash.put(key, fieldValue.toString());
     1328                        }
    12881329                    }
    12891330                }
     
    13321373            } else  if (f.getType() == String.class) {
    13331374                value = key_value.getValue();
    1334             } else
     1375            } else if (f.getType().isAssignableFrom(Map.class)) {
     1376                value = mapFromJson(key_value.getValue());
     1377            }
     1378            else
    13351379                throw new RuntimeException("unsupported preference primitive type");
    13361380
  • trunk/src/org/openstreetmap/josm/data/cache/BufferedImageCacheEntry.java

    r8168 r8344  
    4343                return img;
    4444            byte[] content = getContent();
    45             if (content != null) {
     45            if (content != null && content.length > 0) {
    4646                img = ImageIO.read(new ByteArrayInputStream(content));
    4747
  • trunk/src/org/openstreetmap/josm/data/cache/ICachedLoaderListener.java

    r8176 r8344  
    2020     *
    2121     * @param data
     22     * @param attributes
    2223     * @param result
    2324     */
    24     public void loadingFinished(CacheEntry data, LoadResult result);
     25    public void loadingFinished(CacheEntry data, CacheEntryAttributes attributes, LoadResult result);
    2526
    2627}
  • trunk/src/org/openstreetmap/josm/data/cache/JCSCachedTileLoaderJob.java

    r8326 r8344  
    1010import java.net.URLConnection;
    1111import java.util.HashSet;
     12import java.util.List;
    1213import java.util.Map;
    1314import java.util.Random;
     
    224225     * @return cache object as empty, regardless of what remote resource has returned (ex. based on headers)
    225226     */
    226     protected boolean cacheAsEmpty() {
     227    protected boolean cacheAsEmpty(Map<String, List<String>> headers, int statusCode, byte[] content) {
    227228        return false;
    228229    }
     
    280281        try {
    281282            for (ICachedLoaderListener l: listeners) {
    282                 l.loadingFinished(cacheData, result);
     283                l.loadingFinished(cacheData, attributes, result);
    283284            }
    284285        } catch (Exception e) {
     
    286287            Main.warn(e);
    287288            for (ICachedLoaderListener l: listeners) {
    288                 l.loadingFinished(cacheData, LoadResult.FAILURE);
     289                l.loadingFinished(cacheData, attributes, LoadResult.FAILURE);
    289290            }
    290291
     
    329330                return true;
    330331            }
    331             URLConnection urlConn = getURLConnection();
     332            HttpURLConnection urlConn = getURLConnection();
    332333
    333334            if (isObjectLoadable()  &&
     
    338339                urlConn.addRequestProperty("If-None-Match", attributes.getEtag());
    339340            }
    340             if (urlConn instanceof HttpURLConnection && ((HttpURLConnection)urlConn).getResponseCode() == 304) {
     341            if (urlConn.getResponseCode() == 304) {
    341342                // If isModifiedSince or If-None-Match has been set
    342343                // and the server answers with a HTTP 304 = "Not Modified"
     
    359360
    360361            for (int i = 0; i < 5; ++i) {
    361                 if (urlConn instanceof HttpURLConnection && ((HttpURLConnection)urlConn).getResponseCode() == 503) {
     362                if (urlConn.getResponseCode() == 503) {
    362363                    Thread.sleep(5000+(new Random()).nextInt(5000));
    363364                    continue;
     
    365366                byte[] raw = read(urlConn);
    366367
    367                 if (!cacheAsEmpty() && raw != null && raw.length > 0) {
     368                if (!cacheAsEmpty(urlConn.getHeaderFields(), urlConn.getResponseCode(), raw) &&
     369                        raw != null && raw.length > 0) {
    368370                    cacheData = createCacheEntry(raw);
    369371                    cache.put(getCacheKey(), cacheData, attributes);
     
    400402    private CacheEntryAttributes parseHeaders(URLConnection urlConn) {
    401403        CacheEntryAttributes ret = new CacheEntryAttributes();
    402         ret.setNoTileAtZoom("no-tile".equals(urlConn.getHeaderField("X-VE-Tile-Info")));
    403404
    404405        Long lng = urlConn.getExpiration();
  • trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java

    r8093 r8344  
    1010import java.util.Collections;
    1111import java.util.List;
     12import java.util.Map;
    1213import java.util.Objects;
    1314import java.util.TreeSet;
     
    2122import org.openstreetmap.gui.jmapviewer.tilesources.AbstractTileSource;
    2223import org.openstreetmap.gui.jmapviewer.tilesources.OsmTileSource.Mapnik;
     24import org.openstreetmap.gui.jmapviewer.tilesources.TileSourceInfo;
    2325import org.openstreetmap.josm.Main;
    2426import org.openstreetmap.josm.data.Bounds;
     
    3537 * @author Frederik Ramm
    3638 */
    37 public class ImageryInfo implements Comparable<ImageryInfo>, Attributed {
     39public class ImageryInfo extends TileSourceInfo implements Comparable<ImageryInfo>, Attributed {
    3840
    3941    /**
     
    5355        /** A WMS endpoint entry only stores the WMS server info, without layer, which are chosen later by the user. **/
    5456        WMS_ENDPOINT("wms_endpoint");
     57
    5558
    5659        private final String typeString;
     
    151154    }
    152155
    153     /** name of the imagery entry (gets translated by josm usually) */
    154     private String name;
     156
    155157    /** original name of the imagery entry in case of translation call, for multiple languages English when possible */
    156158    private String origName;
    157159    /** (original) language of the translated name entry */
    158160    private String langName;
    159     /** id for this imagery entry, optional at the moment */
    160     private String id;
    161     /** URL of the imagery service */
    162     private String url = null;
    163161    /** whether this is a entry activated by default or not */
    164162    private boolean defaultEntry = false;
     
    199197    private String icon;
    200198    // when adding a field, also adapt the ImageryInfo(ImageryInfo) constructor
     199    private Map<String, String> noTileHeaders;
    201200
    202201    /**
     
    225224        @pref String icon;
    226225        @pref String description;
     226        @pref Map<String, String> noTileHeaders;
    227227
    228228        /**
     
    278278                projections = val.toString();
    279279            }
     280            if (i.noTileHeaders != null && !i.noTileHeaders.isEmpty()) {
     281                noTileHeaders = i.noTileHeaders;
     282            }
    280283        }
    281284
     
    295298     */
    296299    public ImageryInfo() {
     300        super();
    297301    }
    298302
     
    302306     */
    303307    public ImageryInfo(String name) {
    304         this.name=name;
     308        super(name);
    305309    }
    306310
     
    311315     */
    312316    public ImageryInfo(String name, String url) {
    313         this.name=name;
     317        this(name);
    314318        setExtendedUrl(url);
    315319    }
     
    322326     */
    323327    public ImageryInfo(String name, String url, String eulaAcceptanceRequired) {
    324         this.name=name;
     328        this(name);
    325329        setExtendedUrl(url);
    326330        this.eulaAcceptanceRequired = eulaAcceptanceRequired;
     
    337341     */
    338342    public ImageryInfo(String name, String url, String type, String eulaAcceptanceRequired, String cookies) {
    339         this.name=name;
     343        this(name);
    340344        setExtendedUrl(url);
    341345        ImageryType t = ImageryType.fromString(type);
     
    347351            throw new IllegalArgumentException("unknown type: "+type);
    348352        }
     353    }
     354
     355    public ImageryInfo(String name, String url, String type, String eulaAcceptanceRequired, String cookies, String id) {
     356        this(name, url, type, eulaAcceptanceRequired, cookies);
     357        setId(id);
    349358    }
    350359
     
    390399        countryCode = e.country_code;
    391400        icon = e.icon;
     401        if (e.noTileHeaders != null) {
     402            noTileHeaders = e.noTileHeaders;
     403        }
    392404    }
    393405
     
    688700     * @return The entry name
    689701     */
     702    @Override
    690703    public String getName() {
    691704        return this.name;
     
    759772     * @return The entry URL
    760773     */
     774    @Override
    761775    public String getUrl() {
    762776        return this.url;
     
    791805     * @return the cookie data part
    792806     */
     807    @Override
    793808    public String getCookies() {
    794809        return this.cookies;
     
    803818     * @return The maximum zoom level
    804819     */
     820    @Override
    805821    public int getMaxZoom() {
    806822        return this.defaultMaxZoom;
     
    811827     * @return The minimum zoom level
    812828     */
     829    @Override
    813830    public int getMinZoom() {
    814831        return this.defaultMinZoom;
     
    10261043        return capabilities != null && capabilities.isOnImageryBlacklist(this.url);
    10271044    }
     1045
     1046    public void setNoTileHeaders(Map<String, String> noTileHeaders) {
     1047       this.noTileHeaders = noTileHeaders;
     1048    }
     1049
     1050    @Override
     1051    public Map<String, String> getNoTileHeaders() {
     1052        return noTileHeaders;
     1053    }
    10281054}
  • trunk/src/org/openstreetmap/josm/data/imagery/ImageryLayerInfo.java

    r8130 r8344  
    149149        Collection<String> newKnownDefaults = new TreeSet<>(knownDefaults);
    150150        for (ImageryInfo def : defaultLayers) {
     151            // temporary migration code, so all user preferences will get updated with new settings from JOSM site (can be removed ~Dez. 2015)
     152            if (def.getNoTileHeaders() != null) {
     153                for (ImageryInfo i: layers) {
     154                    if (isSimilar(def,  i)) {
     155                        i.setNoTileHeaders(def.getNoTileHeaders());
     156                        changed = true;
     157                    }
     158                }
     159            }
     160
    151161            if (def.isDefaultEntry()) {
    152162                boolean isKnownDefault = false;
  • trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJob.java

    r8326 r8344  
    66import java.net.URL;
    77import java.util.HashSet;
     8import java.util.List;
    89import java.util.Map;
    910import java.util.Set;
     
    2728import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
    2829import org.openstreetmap.josm.data.cache.CacheEntry;
     30import org.openstreetmap.josm.data.cache.CacheEntryAttributes;
    2931import org.openstreetmap.josm.data.cache.ICachedLoaderListener;
    3032import org.openstreetmap.josm.data.cache.JCSCachedTileLoaderJob;
     
    194196            byte[] content = cacheData.getContent();
    195197            try {
    196                 return content != null  || cacheData.getImage() != null || cacheAsEmpty();
     198                return content != null  || cacheData.getImage() != null || isNoTileAtZoom();
    197199            } catch (IOException e) {
    198200                log.log(Level.WARNING, "JCS TMS - error loading from cache for tile {0}: {1}", new Object[] {tile.getKey(), e.getMessage()});
     
    203205
    204206    private boolean isNoTileAtZoom() {
     207        if (attributes == null) {
     208            log.warning("Cache attributes are null");
     209        }
    205210        return attributes != null && attributes.isNoTileAtZoom();
    206211    }
    207212
    208213    @Override
    209     protected boolean cacheAsEmpty() {
    210         return isNoTileAtZoom();
     214    protected boolean cacheAsEmpty(Map<String, List<String>> headers, int statusCode, byte[] content) {
     215        if (tile.getTileSource().isNoTileAtZoom(headers, statusCode, content)) {
     216            attributes.setNoTileAtZoom(true);
     217            return true;
     218        }
     219        return false;
    211220    }
    212221
     
    242251
    243252    @Override
    244     public void loadingFinished(CacheEntry object, LoadResult result) {
     253    public void loadingFinished(CacheEntry object, CacheEntryAttributes attributes, LoadResult result) {
     254        this.attributes = attributes; // as we might get notification from other object than our selfs, pass attributes along
    245255        Set<TileLoaderListener> listeners;
    246256        synchronized (inProgress) {
     
    316326    @Override
    317327    protected boolean handleNotFound() {
    318         tile.setError("No tile at this zoom level");
    319         tile.putValue("tile-info", "no-tile");
    320         return true;
     328        if (tile.getSource().isNoTileAtZoom(null, 404, null)) {
     329            tile.setError("No tile at this zoom level");
     330            tile.putValue("tile-info", "no-tile");
     331            return true;
     332        }
     333        return false;
    321334    }
    322335
  • trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java

    r8318 r8344  
    278278    private static class CachedAttributionBingAerialTileSource extends BingAerialTileSource {
    279279
    280         public CachedAttributionBingAerialTileSource(String id) {
    281             super(id);
     280        public CachedAttributionBingAerialTileSource(ImageryInfo info) {
     281            super(info);
    282282        }
    283283
     
    337337        if (info.getImageryType() == ImageryType.TMS) {
    338338            checkUrl(info.getUrl());
    339             TMSTileSource t = new TemplatedTMSTileSource(info.getName(), info.getUrl(), info.getId(), info.getMinZoom(), info.getMaxZoom(),
    340                     info.getCookies());
     339            TMSTileSource t = new TemplatedTMSTileSource(info);
    341340            info.setAttribution(t);
    342341            return t;
    343         } else if (info.getImageryType() == ImageryType.BING)
    344             return new CachedAttributionBingAerialTileSource(info.getId());
    345         else if (info.getImageryType() == ImageryType.SCANEX) {
    346             return new ScanexTileSource(info.getName(), info.getUrl(), info.getId(), info.getMaxZoom());
     342        } else if (info.getImageryType() == ImageryType.BING) {
     343            //return new CachedAttributionBingAerialTileSource(info.getId());
     344            return new CachedAttributionBingAerialTileSource(info);
     345        } else if (info.getImageryType() == ImageryType.SCANEX) {
     346            //return new ScanexTileSource(info.getName(), info.getUrl(), info.getId(), info.getMaxZoom());
     347            return new ScanexTileSource(info);
    347348        }
    348349        return null;
  • trunk/src/org/openstreetmap/josm/io/imagery/ImageryReader.java

    r8287 r8344  
    66import java.util.ArrayList;
    77import java.util.Arrays;
     8import java.util.HashMap;
    89import java.util.List;
     10import java.util.Map;
    911import java.util.Objects;
    1012import java.util.Stack;
     
    3941        BOUNDS,
    4042        SHAPE,
     43        NO_TILE,
    4144        UNKNOWN,            // element is not recognized in the current context
    4245    }
     
    8487        private String lang;
    8588        private List<String> projections;
     89        private Map<String, String> noTileHeaders;
    8690
    8791        @Override
     
    9599            bounds = null;
    96100            projections = null;
     101            noTileHeaders = null;
    97102        }
    98103
     
    150155                    projections = new ArrayList<>();
    151156                    newState = State.PROJECTIONS;
     157                } else if ("no-tile-header".equals(qName)) {
     158                    noTileHeaders = new HashMap<>();
     159                    noTileHeaders.put(atts.getValue("name"), atts.getValue("value"));
     160                    newState = State.NO_TILE;
    152161                }
    153162                break;
     
    308317                projections = null;
    309318                break;
     319            case NO_TILE:
     320                entry.setNoTileHeaders(noTileHeaders);
     321                noTileHeaders = null;
     322                break;
     323
    310324            }
    311325        }
Note: See TracChangeset for help on using the changeset viewer.