Ticket #6137: ImageProvider.rev4398.patch

File ImageProvider.rev4398.patch, 15.0 KB (added by cmuelle8, 15 years ago)

updated patch (using digestutils to build img urls)

  • src/org/openstreetmap/josm/tools/ImageProvider.java

     
    33
    44import static org.openstreetmap.josm.tools.I18n.tr;
    55
    6 import com.kitfox.svg.SVGDiagram;
    7 import com.kitfox.svg.SVGException;
    8 import com.kitfox.svg.SVGUniverse;
    9 
    106import java.awt.Component;
    117import java.awt.Cursor;
    128import java.awt.Dimension;
     
    2016import java.awt.Toolkit;
    2117import java.awt.Transparency;
    2218import java.awt.image.BufferedImage;
     19import java.io.ByteArrayInputStream;
    2320import java.io.File;
    2421import java.io.IOException;
    2522import java.io.InputStream;
     
    3633import javax.swing.Icon;
    3734import javax.swing.ImageIcon;
    3835
     36import org.apache.commons.codec.digest.DigestUtils;
    3937import org.openstreetmap.josm.Main;
    4038import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
    4139import org.openstreetmap.josm.io.MirroredInputStream;
    4240import org.openstreetmap.josm.plugins.PluginHandler;
     41import org.xml.sax.Attributes;
     42import org.xml.sax.EntityResolver;
     43import org.xml.sax.InputSource;
     44import org.xml.sax.SAXException;
     45import org.xml.sax.XMLReader;
     46import org.xml.sax.helpers.DefaultHandler;
     47import org.xml.sax.helpers.XMLReaderFactory;
    4348
     49import com.kitfox.svg.SVGDiagram;
     50import com.kitfox.svg.SVGException;
     51import com.kitfox.svg.SVGUniverse;
     52
    4453/**
    4554 * Helper class to support the application with images.
    4655 * @author imi
     
    7988        if (icon == null) {
    8089            String ext = name.indexOf('.') != -1 ? "" : ".???";
    8190            throw new NullPointerException(tr(
    82             "Fatal: failed to locate image ''{0}''. This is a serious configuration problem. JOSM will stop working.",
    83             name+ext));
     91                    "Fatal: failed to locate image ''{0}''. This is a serious configuration problem. JOSM will stop working.",
     92                    name+ext));
    8493        }
    8594        return icon;
    8695    }
     
    116125    public static ImageIcon getIfAvailable(Collection<String> dirs, String id, String subdir, String name, File archive, boolean sanitize) {
    117126        return getIfAvailable(dirs, id, subdir, name, archive, null, sanitize);
    118127    }
    119    
     128
    120129    /**
    121130     * The full path of the image is either a url (starting with http://)
    122131     * or something like
     
    128137     *                  it will try both extensions.
    129138     * @param archive   A zip file where the image is located (may be null).
    130139     * @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 
     140     *                  original size of the image should be returned. The width
    132141     *                  part of the dimension can be -1. Then it will scale the width
    133142     *                  in the same way as the height. (And the other way around.)
    134143     * @param sanitize  If the image should be repainted to a new BufferedImage to work
    135144     *                  around certain issues.
    136145     */
    137146    public static ImageIcon getIfAvailable(Collection<String> dirs, String id, String subdir, String name, File archive, Dimension dim, boolean sanitize) {
    138         ImageResource ir = getIfAvailableImpl(dirs, id, subdir, name, archive);
    139         if (ir == null)
    140             return null;
    141         return ir.getImageIcon(dim == null ? ImageResource.DEFAULT_DIMENSION : dim, sanitize);
     147        ImageIcon icon = new ImageIcon();
     148        if (name != null && name.startsWith("wiki://")) {
     149            getIfAvailableWikiImpl(icon, dirs, id, name, dim, sanitize);
     150        } else {
     151            ImageResource ir = getIfAvailableImpl(dirs, id, subdir, name, archive);
     152            if (ir == null)
     153                return null;
     154            else {
     155                icon = ir.getImageIcon(dim == null ? ImageResource.DEFAULT_DIMENSION : dim, sanitize);
     156            }
     157        }
     158        return icon;
    142159    }
    143160
     161    private static void getIfAvailableWikiImpl(final ImageIcon icon, Collection<String> dirs, String id, final String name, Dimension dim, final boolean sanitize) {
     162        ImageResource ir = cache.get(name);
     163        if (ir != null) {
     164            icon.setImage(ir.getImageIcon(dim == null ? ImageResource.DEFAULT_DIMENSION : dim, sanitize).getImage());
     165        } else {
     166            // do not return null, since we will loose control over the icon object else
     167            icon.setImage(getIfAvailable(dirs, id, null, "misc/no_icon.png", null, sanitize).getImage());
     168
     169            Main.worker.execute(new Runnable(){
     170                private boolean fetchImpl(String url) {
     171                    try {
     172                        MirroredInputStream is = new MirroredInputStream(url, new File(Main.pref.getPreferencesDir(),
     173                        "images").toString());
     174
     175                        Image img = Toolkit.getDefaultToolkit().createImage(is.getFile().toURI().toURL());
     176                        if (sanitize) {
     177                            img = sanitize(img);
     178                        }
     179                        cache.put(name, new ImageResource(img, sanitize));
     180
     181                        // finally, update the icon image that up to now displayed "no_icon"
     182                        icon.setImage(img);
     183                        return true;
     184                    } catch (IOException e) {
     185                        System.out.println("INFO: fetching " + url + "failed");
     186                        return false;
     187                    }
     188                }
     189
     190                private String getImgUrlFromInfoPage(final String base, final String fn) {
     191                    try {
     192                        final XMLReader parser = XMLReaderFactory.createXMLReader();
     193                        parser.setContentHandler(new DefaultHandler() {
     194                            @Override
     195                            public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
     196                                System.out.println();
     197                                if (localName.equalsIgnoreCase("img")) {
     198                                    String val = atts.getValue("src");
     199                                    if (val.endsWith(fn))
     200                                        throw new SAXException(val);  // parsing done, quit early
     201                                }
     202                            }
     203                        });
     204
     205                        parser.setEntityResolver(new EntityResolver() {
     206                            public InputSource resolveEntity (String publicId, String systemId) {
     207                                return new InputSource(new ByteArrayInputStream(new byte[0]));
     208                            }
     209                        });
     210
     211                        parser.parse(new InputSource(new MirroredInputStream(
     212                                base + fn,
     213                                new File(Main.pref.getPreferencesDir(), "images").toString()
     214                        )));
     215                    } catch (Exception e) {
     216                        if (!(e instanceof SAXException)) {
     217                            System.out.println("INFO: parsing " + base + fn + "failed");
     218                        } else
     219                            return e.getMessage();
     220                    }
     221
     222                    return "";
     223                }
     224
     225                public void run() {
     226                    final String[] baseurls = {
     227                            Main.pref.get("url.osm-wiki-images", "http://wiki.openstreetmap.org/w/images/"),
     228                            Main.pref.get("url.commons-wiki-images", "http://upload.wikimedia.org/wikipedia/commons/"),
     229                            Main.pref.get("url.osm-wiki-infopage", "http://wiki.openstreetmap.org/wiki/File:"),
     230                    };
     231                    final String fn = name.substring(name.lastIndexOf('/') + 1);
     232                    final String fn_md5 = DigestUtils.md5Hex(fn);
     233
     234                    for (String b : baseurls) {
     235                        if ( fetchImpl(b.endsWith(":")
     236                                ? (getImgUrlFromInfoPage(b, fn))
     237                                        : (b + fn_md5.substring(0,1)+"/" + fn_md5.substring(0,2)+"/" + fn))
     238                        ) {
     239                            break;
     240                        }
     241                    }
     242                }
     243            });
     244        }
     245    }
     246
    144247    private static ImageResource getIfAvailableImpl(Collection<String> dirs, String id, String subdir, String name, File archive) {
    145248        if (name == null)
    146249            return null;
     
    192295                if (ir != null) return ir;
    193296
    194297                switch (place) {
    195                     case ARCHIVE:
    196                         if (archive != null) {
    197                             ir = getIfAvailableZip(full_name, archive, type);
    198                             if (ir != null) {
    199                                 cache.put(cache_name, ir);
    200                                 return ir;
    201                             }
    202                         }
    203                         break;
    204                     case LOCAL:
    205                         // getImageUrl() does a ton of "stat()" calls and gets expensive
    206                         // and redundant when you have a whole ton of objects. So,
    207                         // index the cache by the name of the icon we're looking for
    208                         // and don't bother to create a URL unless we're actually
    209                         // creating the image.
    210                         URL path = getImageUrl(full_name, dirs);
    211                         if (path == null)
    212                             continue;
    213                         ir = getIfAvailableLocalURL(path, type);
     298                case ARCHIVE:
     299                    if (archive != null) {
     300                        ir = getIfAvailableZip(full_name, archive, type);
    214301                        if (ir != null) {
    215302                            cache.put(cache_name, ir);
    216303                            return ir;
    217304                        }
    218                         break;
     305                    }
     306                    break;
     307                case LOCAL:
     308                    // getImageUrl() does a ton of "stat()" calls and gets expensive
     309                    // and redundant when you have a whole ton of objects. So,
     310                    // index the cache by the name of the icon we're looking for
     311                    // and don't bother to create a URL unless we're actually
     312                    // creating the image.
     313                    URL path = getImageUrl(full_name, dirs);
     314                    if (path == null) {
     315                        continue;
     316                    }
     317                    ir = getIfAvailableLocalURL(path, type);
     318                    if (ir != null) {
     319                        cache.put(cache_name, ir);
     320                        return ir;
     321                    }
     322                    break;
    219323                }
    220324            }
    221325        }
     
    227331            MirroredInputStream is = new MirroredInputStream(url,
    228332                    new File(Main.pref.getPreferencesDir(), "images").toString());
    229333            switch (type) {
    230                 case SVG:
    231                     URI uri = getSvgUniverse().loadSVG(is, is.getFile().toURI().toURL().toString());
    232                     SVGDiagram svg = getSvgUniverse().getDiagram(uri);
    233                     return svg == null ? null : new ImageResource(svg);
    234                 case OTHER:
    235                     Image img = Toolkit.getDefaultToolkit().createImage(is.getFile().toURI().toURL());
    236                     return img == null ? null : new ImageResource(img, false);
    237                 default:
    238                     throw new AssertionError();
     334            case SVG:
     335                URI uri = getSvgUniverse().loadSVG(is, is.getFile().toURI().toURL().toString());
     336                SVGDiagram svg = getSvgUniverse().getDiagram(uri);
     337                return svg == null ? null : new ImageResource(svg);
     338            case OTHER:
     339                Image img = Toolkit.getDefaultToolkit().createImage(is.getFile().toURI().toURL());
     340                return img == null ? null : new ImageResource(img, false);
     341            default:
     342                throw new AssertionError();
    239343            }
    240344        } catch (IOException e) {
    241345            return null;
     
    257361                try {
    258362                    is = zipFile.getInputStream(entry);
    259363                    switch (type) {
    260                         case SVG:
    261                             URI uri = getSvgUniverse().loadSVG(is, full_name);
    262                             SVGDiagram svg = getSvgUniverse().getDiagram(uri);
    263                             return svg == null ? null : new ImageResource(svg);
    264                         case OTHER:
    265                             while(size > 0)
    266                             {
    267                                 int l = is.read(buf, offs, size);
    268                                 offs += l;
    269                                 size -= l;
    270                             }
    271                             Image img = Toolkit.getDefaultToolkit().createImage(buf);
    272                             return img == null ? null : new ImageResource(img, false);
    273                         default:
    274                             throw new AssertionError();
     364                    case SVG:
     365                        URI uri = getSvgUniverse().loadSVG(is, full_name);
     366                        SVGDiagram svg = getSvgUniverse().getDiagram(uri);
     367                        return svg == null ? null : new ImageResource(svg);
     368                    case OTHER:
     369                        while(size > 0)
     370                        {
     371                            int l = is.read(buf, offs, size);
     372                            offs += l;
     373                            size -= l;
     374                        }
     375                        Image img = Toolkit.getDefaultToolkit().createImage(buf);
     376                        return img == null ? null : new ImageResource(img, false);
     377                    default:
     378                        throw new AssertionError();
    275379                    }
    276380                } finally {
    277381                    if (is != null) {
     
    294398
    295399    private static ImageResource getIfAvailableLocalURL(URL path, ImageType type) {
    296400        switch (type) {
    297             case SVG:
    298                 URI uri = getSvgUniverse().loadSVG(path);
    299                 SVGDiagram svg = getSvgUniverse().getDiagram(uri);
    300                 return svg == null ? null : new ImageResource(svg);
    301             case OTHER:
    302                 Image img = Toolkit.getDefaultToolkit().createImage(path);
    303                 return img == null ? null : new ImageResource(img, false);
    304             default:
    305                 throw new AssertionError();
     401        case SVG:
     402            URI uri = getSvgUniverse().loadSVG(path);
     403            SVGDiagram svg = getSvgUniverse().getDiagram(uri);
     404            return svg == null ? null : new ImageResource(svg);
     405        case OTHER:
     406            Image img = Toolkit.getDefaultToolkit().createImage(path);
     407            return img == null ? null : new ImageResource(img, false);
     408        default:
     409            throw new AssertionError();
    306410        }
    307411    }
    308412