Changeset 4403 in josm


Ignore:
Timestamp:
2011-09-07T15:07:26+02:00 (9 years ago)
Author:
bastiK
Message:

applied #6137 - provide osm wiki image retrieval in ImageProvider (based on patch by cmuelle8)

Location:
trunk/src/org/openstreetmap/josm/tools
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/tools/ImageProvider.java

    r4271 r4403  
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
    5 
    6 import com.kitfox.svg.SVGDiagram;
    7 import com.kitfox.svg.SVGException;
    8 import com.kitfox.svg.SVGUniverse;
    95
    106import java.awt.Component;
     
    2117import java.awt.Transparency;
    2218import java.awt.image.BufferedImage;
     19import java.io.ByteArrayInputStream;
    2320import java.io.File;
    2421import java.io.IOException;
     
    3330import java.util.zip.ZipEntry;
    3431import java.util.zip.ZipFile;
    35 
    3632import javax.swing.Icon;
    3733import javax.swing.ImageIcon;
     
    4137import org.openstreetmap.josm.io.MirroredInputStream;
    4238import org.openstreetmap.josm.plugins.PluginHandler;
     39import org.openstreetmap.josm.tools.Utils;
     40import org.xml.sax.Attributes;
     41import org.xml.sax.EntityResolver;
     42import org.xml.sax.InputSource;
     43import org.xml.sax.SAXException;
     44import org.xml.sax.XMLReader;
     45import org.xml.sax.helpers.DefaultHandler;
     46import org.xml.sax.helpers.XMLReaderFactory;
     47
     48import com.kitfox.svg.SVGDiagram;
     49import com.kitfox.svg.SVGException;
     50import com.kitfox.svg.SVGUniverse;
    4351
    4452/**
     
    8088            String ext = name.indexOf('.') != -1 ? "" : ".???";
    8189            throw new NullPointerException(tr(
    82             "Fatal: failed to locate image ''{0}''. This is a serious configuration problem. JOSM will stop working.",
    83             name+ext));
     90                    "Fatal: failed to locate image ''{0}''. This is a serious configuration problem. JOSM will stop working.",
     91                    name+ext));
    8492        }
    8593        return icon;
     
    117125        return getIfAvailable(dirs, id, subdir, name, archive, null, sanitize);
    118126    }
    119    
     127
    120128    /**
    121129     * The full path of the image is either a url (starting with http://)
     
    129137     * @param archive   A zip file where the image is located (may be null).
    130138     * @param dim       The dimensions of the image if it should be scaled. null if the
    131      *                  original size of the image should be returned. The width 
     139     *                  original size of the image should be returned. The width
    132140     *                  part of the dimension can be -1. Then it will scale the width
    133141     *                  in the same way as the height. (And the other way around.)
     
    154162            if (ir != null) {
    155163                cache.put(url, ir);
     164            }
     165            return ir;
     166        } else if (name.startsWith("wiki://")) {
     167            ImageResource ir = cache.get(name);
     168            if (ir != null) return ir;
     169            ir = getIfAvailableWiki(name, type);
     170            if (ir != null) {
     171                cache.put(name, ir);
    156172            }
    157173            return ir;
     
    209225                        // creating the image.
    210226                        URL path = getImageUrl(full_name, dirs);
    211                         if (path == null)
     227                        if (path == null) {
    212228                            continue;
     229                        }
    213230                        ir = getIfAvailableLocalURL(path, type);
    214231                        if (ir != null) {
     
    241258            return null;
    242259        }
     260    }
     261
     262    private static ImageResource getIfAvailableWiki(String name, ImageType type) {
     263        final Collection<String> defaultBaseUrls = Arrays.asList(
     264                "http://wiki.openstreetmap.org/w/images/",
     265                "http://upload.wikimedia.org/wikipedia/commons/",
     266                "http://wiki.openstreetmap.org/wiki/File:"
     267        );
     268        final Collection<String> baseUrls = Main.pref.getCollection("image-provider.wiki.urls", defaultBaseUrls);
     269
     270        final String fn = name.substring(name.lastIndexOf('/') + 1);
     271
     272        ImageResource result = null;
     273        for (String b : baseUrls) {
     274            String url;
     275            if (b.endsWith(":")) {
     276                url = getImgUrlFromWikiInfoPage(b, fn);
     277                if (url == null) {
     278                    continue;
     279                }
     280            } else {
     281                final String fn_md5 = Utils.md5Hex(fn);
     282                url = b + fn_md5.substring(0,1) + "/" + fn_md5.substring(0,2) + "/" + fn;
     283            }
     284            result = getIfAvailableHttp(url, type);
     285            if (result != null) {
     286                break;
     287            }
     288        }
     289        return result;
    243290    }
    244291
     
    379426    }
    380427
     428    /**
     429     * Reads the wiki page on a certain file in html format in order to find the real image URL.
     430     */
     431    private static String getImgUrlFromWikiInfoPage(final String base, final String fn) {
     432
     433        /** Quit parsing, when a certain condition is met */
     434        class SAXReturnException extends SAXException {
     435            private String result;
     436
     437            public SAXReturnException(String result) {
     438                this.result = result;
     439            }
     440
     441            public String getResult() {
     442                return result;
     443            }
     444        }
     445
     446        try {
     447            final XMLReader parser = XMLReaderFactory.createXMLReader();
     448            parser.setContentHandler(new DefaultHandler() {
     449                @Override
     450                public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
     451                    System.out.println();
     452                    if (localName.equalsIgnoreCase("img")) {
     453                        String val = atts.getValue("src");
     454                        if (val.endsWith(fn))
     455                            throw new SAXReturnException(val);  // parsing done, quit early
     456                    }
     457                }
     458            });
     459
     460            parser.setEntityResolver(new EntityResolver() {
     461                public InputSource resolveEntity (String publicId, String systemId) {
     462                    return new InputSource(new ByteArrayInputStream(new byte[0]));
     463                }
     464            });
     465
     466            parser.parse(new InputSource(new MirroredInputStream(
     467                    base + fn,
     468                    new File(Main.pref.getPreferencesDir(), "images").toString()
     469            )));
     470        } catch (SAXReturnException r) {
     471            return r.getResult();
     472        } catch (Exception e) {
     473            System.out.println("INFO: parsing " + base + fn + " failed:\n" + e);
     474            return null;
     475        }
     476        System.out.println("INFO: parsing " + base + fn + " failed: Unexpected content.");
     477        return null;
     478    }
     479
    381480    public static Cursor getCursor(String name, String overlay) {
    382481        ImageIcon img = get("cursor", name);
  • trunk/src/org/openstreetmap/josm/tools/Utils.java

    r4380 r4403  
    1515import java.io.OutputStream;
    1616import java.io.Reader;
     17import java.io.UnsupportedEncodingException;
     18import java.security.MessageDigest;
     19import java.security.NoSuchAlgorithmException;
    1720import java.text.MessageFormat;
    1821import java.util.Collection;
     
    312315        return null;
    313316    }
     317
     318    /**
     319     * Calculate MD5 hash of a string and output in hexadecimal format.
     320     * Output has length 32 with characters in range [0-9a-f]
     321     */
     322    public static String md5Hex(String data) {
     323        byte[] byteData = null;
     324        try {
     325            byteData = data.getBytes("UTF-8");
     326        } catch (UnsupportedEncodingException e) {
     327            throw new RuntimeException();
     328        }
     329        MessageDigest md = null;
     330        try {
     331            md = MessageDigest.getInstance("MD5");
     332        } catch (NoSuchAlgorithmException e) {
     333            throw new RuntimeException();
     334        }
     335        byte[] byteDigest = md.digest(byteData);
     336        return toHexString(byteDigest);
     337    }
     338
     339    /**
     340     * Converts a byte array to a string of hexadecimal characters. Preserves leading zeros, so the
     341     * size of the output string is always twice the number of input bytes.
     342     */
     343    public static String toHexString(byte[] bytes) {
     344        char[] hexArray = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
     345        char[] hexChars = new char[bytes.length * 2];
     346        for (int j=0; j<bytes.length; j++) {
     347            int v = bytes[j] & 0xFF;
     348            hexChars[j*2] = hexArray[v/16];
     349            hexChars[j*2 + 1] = hexArray[v%16];
     350        }
     351        return new String(hexChars);
     352    }
    314353}
Note: See TracChangeset for help on using the changeset viewer.