Changeset 8418 in josm


Ignore:
Timestamp:
2015-05-23T00:46:21+02:00 (9 years ago)
Author:
wiktorn
Message:

Add posibility to display HTTP headers in Show Tile Info dialog. Closes #11456

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/data/maps.xsd

    r8350 r8418  
    681681                                                        <!-- tile size provided by imagery source. Default - 256 -->
    682682                                                        <xs:element name="tile-size" minOccurs="0" maxOccurs="1" type="xs:positiveInteger" />
     683                                                        <!--  HTTP headers that contain valuable informatin and that will be shown on "Shown Tile Info" dialog -->
     684                                                        <xs:element name="metadata-header" minOccurs="0" maxOccurs="unbounded">
     685                                                                <xs:complexType>
     686                                                                        <xs:attribute name="header-name" type="xs:string" />
     687                                                                        <xs:attribute name="metadata-key" type="xs:string" />
     688                                                                </xs:complexType>
     689                                                        </xs:element>
    683690                                                </xs:choice>
    684691                                        </xs:sequence>
  • trunk/src/org/openstreetmap/josm/data/cache/CacheEntryAttributes.java

    r8389 r8418  
    22package org.openstreetmap.josm.data.cache;
    33
    4 import java.util.HashMap;
     4import java.util.Arrays;
     5import java.util.Collections;
     6import java.util.HashSet;
    57import java.util.Map;
     8import java.util.Map.Entry;
     9import java.util.Set;
     10import java.util.concurrent.ConcurrentHashMap;
    611
    712import org.apache.commons.jcs.engine.ElementAttributes;
     13import org.openstreetmap.josm.Main;
    814
    915/**
     
    1521public class CacheEntryAttributes extends ElementAttributes {
    1622    private static final long serialVersionUID = 1L; //version
    17     private final Map<String, String> attrs = new HashMap<String, String>();
     23    private final Map<String, String> attrs = new ConcurrentHashMap<String, String>(RESERVED_KEYS.size());
    1824    private static final String NO_TILE_AT_ZOOM = "noTileAtZoom";
    1925    private static final String ETAG = "Etag";
     
    2127    private static final String EXPIRATION_TIME = "expirationTime";
    2228    private static final String HTTP_RESPONSE_CODE = "httpResponceCode";
     29    // this contains all of the above
     30    private static final Set<String> RESERVED_KEYS = new HashSet<>(Arrays.asList(new String[]{
     31        NO_TILE_AT_ZOOM,
     32        ETAG,
     33        LAST_MODIFICATION,
     34        EXPIRATION_TIME,
     35        HTTP_RESPONSE_CODE
     36    }));
    2337
    2438    /**
     
    2842        super();
    2943        attrs.put(NO_TILE_AT_ZOOM, "false");
    30         attrs.put(ETAG, null);
    3144        attrs.put(LAST_MODIFICATION, "0");
    3245        attrs.put(EXPIRATION_TIME, "0");
     
    4457    }
    4558    public void setEtag(String etag) {
    46         attrs.put(ETAG, etag);
     59        if(etag != null) {
     60            attrs.put(ETAG, etag);
     61        }
    4762    }
    4863
     
    8297    }
    8398
     99    /**
     100     * Sets the metadata about cache entry. As it stores all data together, with other attributes
     101     * in common map, some keys might not be stored.
     102     *
     103     * @param map metadata to save
     104     */
     105    public void setMetadata(Map<String, String> map) {
     106        for (Entry<String, String> e: map.entrySet()) {
     107            if (RESERVED_KEYS.contains(e.getKey())) {
     108                Main.info("Metadata key configuration contains key {0} which is reserved for internal use");
     109            } else {
     110                attrs.put(e.getKey(), e.getValue());
     111            }
     112        }
     113    }
     114
     115    /**
     116     * Returns an unmodifiable Map containing all metadata. Unmodifiable prevents access to metadata within attributes.
     117     * @return unmodifiable Map with cache element metadata
     118     */
     119    public Map<String, String> getMetadata() {
     120        return Collections.unmodifiableMap(attrs);
     121    }
    84122}
  • trunk/src/org/openstreetmap/josm/data/cache/HostLimitQueue.java

    r8403 r8418  
    3030
    3131public class HostLimitQueue extends LinkedBlockingDeque<Runnable> {
     32    private static final long serialVersionUID = 1L;
    3233
    33     private Map<String, Semaphore> hostSemaphores = new ConcurrentHashMap<>();
    34     private int hostLimit;
     34    private final Map<String, Semaphore> hostSemaphores = new ConcurrentHashMap<>();
     35    private final int hostLimit;
    3536
    3637    /**
     
    9192
    9293    private  Semaphore getSemaphore(JCSCachedTileLoaderJob<?, ?> job) {
    93         String host = ((JCSCachedTileLoaderJob<?, ?>)job).getUrl().getHost();
     94        String host = job.getUrl().getHost();
    9495        Semaphore limit = hostSemaphores.get(host);
    9596        if (limit == null) {
     
    112113                limit.acquire();
    113114                jcsJob.setFinishedTask(new Runnable() {
     115                    @Override
    114116                    public void run() {
    115117                        releaseSemaphore(jcsJob);
     
    128130            if (ret) {
    129131                job.setFinishedTask(new Runnable() {
     132                    @Override
    130133                    public void run() {
    131134                        releaseSemaphore(job);
  • trunk/src/org/openstreetmap/josm/data/imagery/ImageryInfo.java

    r8404 r8418  
    198198    /** icon used in menu */
    199199    private String icon;
    200     // when adding a field, also adapt the ImageryInfo(ImageryInfo) constructor
    201     private Map<String, String> noTileHeaders;
     200    // when adding a field, also adapt the ImageryInfo(ImageryInfo) constructor, equals method, and ImageryPreferenceEntry
    202201
    203202    /**
     
    228227        @pref Map<String, String> noTileHeaders;
    229228        @pref int tileSize = OsmMercator.DEFAUL_TILE_SIZE;
     229        @pref Map<String, String> metadataHeaders;
    230230
    231231        /**
     
    285285            }
    286286
     287            if (i.metadataHeaders != null && !i.metadataHeaders.isEmpty()) {
     288                metadataHeaders = i.metadataHeaders;
     289            }
     290
    287291            tileSize = i.getTileSize();
    288292        }
     
    408412        }
    409413        setTileSize(e.tileSize);
     414        metadataHeaders = e.metadataHeaders;
    410415    }
    411416
     
    436441        this.icon = i.icon;
    437442        this.description = i.description;
     443        this.noTileHeaders = i.noTileHeaders;
     444        this.metadataHeaders = i.metadataHeaders;
    438445    }
    439446
     
    465472            return false;
    466473        }
    467         if (!Objects.equals(this.name, other.name)) {
    468             return false;
    469         }
    470         if (!Objects.equals(this.id, other.id)) {
    471             return false;
    472         }
    473         if (!Objects.equals(this.url, other.url)) {
    474             return false;
    475         }
    476         if (!Objects.equals(this.cookies, other.cookies)) {
    477             return false;
    478         }
    479         if (!Objects.equals(this.eulaAcceptanceRequired, other.eulaAcceptanceRequired)) {
    480             return false;
    481         }
    482         if (this.imageryType != other.imageryType) {
    483             return false;
    484         }
    485         if (this.defaultMaxZoom != other.defaultMaxZoom) {
    486             return false;
    487         }
    488         if (this.defaultMinZoom != other.defaultMinZoom) {
    489             return false;
    490         }
    491         if (!Objects.equals(this.bounds, other.bounds)) {
    492             return false;
    493         }
    494         if (!Objects.equals(this.serverProjections, other.serverProjections)) {
    495             return false;
    496         }
    497         if (!Objects.equals(this.attributionText, other.attributionText)) {
    498             return false;
    499         }
    500         if (!Objects.equals(this.attributionLinkURL, other.attributionLinkURL)) {
    501             return false;
    502         }
    503         if (!Objects.equals(this.attributionImage, other.attributionImage)) {
    504             return false;
    505         }
    506         if (!Objects.equals(this.attributionImageURL, other.attributionImageURL)) {
    507             return false;
    508         }
    509         if (!Objects.equals(this.termsOfUseText, other.termsOfUseText)) {
    510             return false;
    511         }
    512         if (!Objects.equals(this.termsOfUseURL, other.termsOfUseURL)) {
    513             return false;
    514         }
    515         if (!Objects.equals(this.countryCode, other.countryCode)) {
    516             return false;
    517         }
    518         if (!Objects.equals(this.icon, other.icon)) {
    519             return false;
    520         }
    521         if (!Objects.equals(this.description, other.description)) {
    522             return false;
    523         }
    524         return true;
     474
     475        return
     476                Objects.equals(this.name, other.name) &&
     477                Objects.equals(this.id, other.id) &&
     478                Objects.equals(this.url, other.url) &&
     479                Objects.equals(this.cookies, other.cookies) &&
     480                Objects.equals(this.eulaAcceptanceRequired, other.eulaAcceptanceRequired) &&
     481                Objects.equals(this.imageryType, other.imageryType) &&
     482                Objects.equals(this.defaultMaxZoom, other.defaultMaxZoom) &&
     483                Objects.equals(this.defaultMinZoom, other.defaultMinZoom) &&
     484                Objects.equals(this.bounds, other.bounds) &&
     485                Objects.equals(this.serverProjections, other.serverProjections) &&
     486                Objects.equals(this.attributionText, other.attributionText) &&
     487                Objects.equals(this.attributionLinkURL, other.attributionLinkURL) &&
     488                Objects.equals(this.attributionImageURL, other.attributionImageURL) &&
     489                Objects.equals(this.attributionImage, other.attributionImage) &&
     490                Objects.equals(this.termsOfUseText, other.termsOfUseText) &&
     491                Objects.equals(this.termsOfUseURL, other.termsOfUseURL) &&
     492                Objects.equals(this.countryCode, other.countryCode) &&
     493                Objects.equals(this.icon, other.icon) &&
     494                Objects.equals(this.description, other.description) &&
     495                Objects.equals(this.noTileHeaders, other.noTileHeaders) &&
     496                Objects.equals(this.metadataHeaders, other.metadataHeaders);
    525497    }
    526498
     
    10581030        return noTileHeaders;
    10591031    }
     1032
     1033    public void setMetadataHeaders(Map<String, String> metadataHeaders) {
     1034        this.metadataHeaders = metadataHeaders;
     1035    }
    10601036}
  • trunk/src/org/openstreetmap/josm/data/imagery/ImageryLayerInfo.java

    r8349 r8418  
    150150        for (ImageryInfo def : defaultLayers) {
    151151            // 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 || def.getTileSize() > 0) {
     152            if (def.getNoTileHeaders() != null || def.getTileSize() > 0 || def.getMetadataHeaders() != null ) {
    153153                for (ImageryInfo i: layers) {
    154154                    if (isSimilar(def,  i)) {
     
    158158                        if (def.getTileSize() > 0) {
    159159                            i.setTileSize(def.getTileSize());
     160                        }
     161                        if (def.getMetadataHeaders() != null && def.getMetadataHeaders().size() > 0) {
     162                            i.setMetadataHeaders(def.getMetadataHeaders());
    160163                        }
    161164                        changed = true;
  • trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoaderJob.java

    r8403 r8418  
    1010import java.util.List;
    1111import java.util.Map;
     12import java.util.Map.Entry;
    1213import java.util.Set;
    1314import java.util.concurrent.ConcurrentHashMap;
     
    133134    @Override
    134135    protected boolean cacheAsEmpty(Map<String, List<String>> headers, int statusCode, byte[] content) {
     136        // cacheAsEmpty is called for every successful download, so we can put
     137        // metadata handling here
     138        attributes.setMetadata(tile.getTileSource().getMetadata(headers));
    135139        if (tile.getTileSource().isNoTileAtZoom(headers, statusCode, content)) {
    136140            attributes.setNoTileAtZoom(true);
     
    166170            if(!tile.isLoaded()) { //if someone else already loaded tile, skip all the handling
    167171                tile.finishLoading(); // whatever happened set that loading has finished
     172                // set tile metadata
     173                if (this.attributes != null) {
     174                    for (Entry<String, String> e: this.attributes.getMetadata().entrySet()) {
     175                        tile.putValue(e.getKey(), e.getValue());
     176                    }
     177                }
     178
    168179                switch(result){
    169180                case SUCCESS:
     
    214225        if (isObjectLoadable()) {
    215226            try {
     227                // set tile metadata
     228                if (this.attributes != null) {
     229                    for (Entry<String, String> e: this.attributes.getMetadata().entrySet()) {
     230                        tile.putValue(e.getKey(), e.getValue());
     231                    }
     232                }
     233
    216234                if (data != null && data.getImage() != null) {
    217235                    tile.setImage(data.getImage());
  • trunk/src/org/openstreetmap/josm/gui/layer/TMSLayer.java

    r8403 r8418  
    88import java.awt.Graphics;
    99import java.awt.Graphics2D;
     10import java.awt.GridBagLayout;
    1011import java.awt.Image;
    1112import java.awt.Point;
     
    2021import java.io.StringReader;
    2122import java.net.URL;
     23import java.text.SimpleDateFormat;
    2224import java.util.ArrayList;
    2325import java.util.Collections;
    2426import java.util.Comparator;
     27import java.util.Date;
    2528import java.util.HashMap;
    2629import java.util.LinkedList;
    2730import java.util.List;
    2831import java.util.Map;
     32import java.util.Map.Entry;
    2933import java.util.Scanner;
    3034import java.util.concurrent.Callable;
     
    3438import javax.swing.AbstractAction;
    3539import javax.swing.Action;
     40import javax.swing.BorderFactory;
    3641import javax.swing.JCheckBoxMenuItem;
     42import javax.swing.JLabel;
    3743import javax.swing.JMenuItem;
    3844import javax.swing.JOptionPane;
     45import javax.swing.JPanel;
    3946import javax.swing.JPopupMenu;
     47import javax.swing.JTextField;
    4048
    4149import org.openstreetmap.gui.jmapviewer.AttributionSupport;
     
    8088import org.openstreetmap.josm.io.UTFInputStreamReader;
    8189import org.openstreetmap.josm.tools.CheckParameterUtil;
     90import org.openstreetmap.josm.tools.GBC;
    8291import org.openstreetmap.josm.tools.Utils;
    8392import org.xml.sax.InputSource;
     
    533542        tileOptionMenu.add(new JMenuItem(new AbstractAction(
    534543                tr("Show Tile Info")) {
     544            private String getSizeString(int size) {
     545                StringBuilder ret = new StringBuilder();
     546                return ret.append(size).append("x").append(size).toString();
     547            }
     548
     549            private JTextField createTextField(String text) {
     550                JTextField ret = new JTextField(text);
     551                ret.setEditable(false);
     552                ret.setBorder(BorderFactory.createEmptyBorder());
     553                return ret;
     554            }
    535555            @Override
    536556            public void actionPerformed(ActionEvent ae) {
    537557                if (clickedTile != null) {
    538558                    ExtendedDialog ed = new ExtendedDialog(Main.parent, tr("Tile Info"), new String[]{tr("OK")});
     559                    JPanel panel = new JPanel(new GridBagLayout());
     560                    Rectangle displaySize = tileToRect(clickedTile);
     561                    String url = "";
     562                    try {
     563                        url = clickedTile.getUrl();
     564                    } catch (IOException e) {
     565                        // silence exceptions
     566                    }
     567
     568                    String[][] content = {
     569                            {"Tile name", clickedTile.getKey()},
     570                            {"Tile url", url},
     571                            {"Tile size", getSizeString(clickedTile.getTileSource().getTileSize()) },
     572                            {"Tile display size", new StringBuilder().append(displaySize.width).append("x").append(displaySize.height).toString()},
     573                    };
     574
     575                    for (String[] entry: content) {
     576                        panel.add(new JLabel(tr(entry[0]) + ":"), GBC.std());
     577                        panel.add(GBC.glue(5,0), GBC.std());
     578                        panel.add(createTextField(entry[1]), GBC.eol().fill(GBC.HORIZONTAL));
     579                    }
     580
     581                    for (Entry<String, String> e: clickedTile.getMetadata().entrySet()) {
     582                        panel.add(new JLabel(tr("Metadata ") + tr(e.getKey()) + ":"), GBC.std());
     583                        panel.add(GBC.glue(5,0), GBC.std());
     584                        String value = e.getValue();
     585                        if ("lastModification".equals(e.getKey()) || "expirationTime".equals(e.getKey())) {
     586                            value = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(Long.parseLong(value)));
     587                        }
     588                        panel.add(createTextField(value), GBC.eol().fill(GBC.HORIZONTAL));
     589
     590                    }
    539591                    ed.setIcon(JOptionPane.INFORMATION_MESSAGE);
    540                     StringBuilder content = new StringBuilder();
    541                     content.append("Tile name: ").append(clickedTile.getKey()).append('\n');
    542                     try {
    543                         content.append("Tile url: ").append(clickedTile.getUrl()).append('\n');
    544                     } catch (IOException e) {
    545                     }
    546                     content.append("Tile size: ").append(clickedTile.getTileSource().getTileSize()).append('x').append(clickedTile.getTileSource().getTileSize()).append('\n');
    547                     Rectangle displaySize = tileToRect(clickedTile);
    548                     content.append("Tile display size: ").append(displaySize.width).append('x').append(displaySize.height).append('\n');
    549                     ed.setContent(content.toString());
     592                    ed.setContent(panel);
    550593                    ed.showDialog();
    551594                }
  • trunk/src/org/openstreetmap/josm/io/imagery/ImageryReader.java

    r8390 r8418  
    4242        SHAPE,
    4343        NO_TILE,
     44        METADATA,
    4445        UNKNOWN,            // element is not recognized in the current context
    4546    }
     
    8889        private List<String> projections;
    8990        private Map<String, String> noTileHeaders;
     91        private Map<String, String> metadataHeaders;
    9092
    9193        @Override
     
    117119                    skipEntry = false;
    118120                    newState = State.ENTRY;
     121                    noTileHeaders = new HashMap<>();
     122                    metadataHeaders = new HashMap<>();
    119123                }
    120124                break;
     
    157161                    newState = State.PROJECTIONS;
    158162                } else if ("no-tile-header".equals(qName)) {
    159                     noTileHeaders = new HashMap<>();
    160163                    noTileHeaders.put(atts.getValue("name"), atts.getValue("value"));
    161164                    newState = State.NO_TILE;
     165                } else if ("metadata-header".equals(qName)) {
     166                    metadataHeaders.put(atts.getValue("header-name"), atts.getValue("metadata-key"));
     167                    newState = State.METADATA;
    162168                }
    163169                break;
     
    196202                skipEntry = true;
    197203            }
    198             return;
    199204        }
    200205
     
    211216            case ENTRY:
    212217                if ("entry".equals(qName)) {
     218                    entry.setNoTileHeaders(noTileHeaders);
     219                    noTileHeaders = null;
     220                    entry.setMetadataHeaders(metadataHeaders);
     221                    metadataHeaders = null;
     222
    213223                    if (!skipEntry) {
    214224                        entries.add(entry);
     
    332342                break;
    333343            case NO_TILE:
    334                 entry.setNoTileHeaders(noTileHeaders);
    335                 noTileHeaders = null;
    336344                break;
    337345
Note: See TracChangeset for help on using the changeset viewer.