Changeset 4403 in josm


Ignore:
Timestamp:
Sep 7, 2011 3:07:26 PM (21 months 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.