From 07138f324063fb0166266e41fa0e135095c7435d Mon Sep 17 00:00:00 2001 From: Emux Date: Tue, 5 Sep 2017 13:29:22 +0300 Subject: [PATCH] Mapsforge themes compatibility improvements #100, fix #392 --- .../android/filepicker/ValidRenderTheme.java | 5 ++- .../android/test/MapsforgeStyleActivity.java | 4 +-- .../android/theme/AssetsRenderTheme.java | 31 ++++++++-------- .../org/oscim/theme/StreamRenderTheme.java | 10 +++++- vtm/src/org/oscim/theme/ThemeLoader.java | 2 +- vtm/src/org/oscim/theme/ThemeUtils.java | 35 +++++++------------ 6 files changed, 42 insertions(+), 45 deletions(-) diff --git a/vtm-android-example/src/org/oscim/android/filepicker/ValidRenderTheme.java b/vtm-android-example/src/org/oscim/android/filepicker/ValidRenderTheme.java index 87df685e7..8b33a5fae 100644 --- a/vtm-android-example/src/org/oscim/android/filepicker/ValidRenderTheme.java +++ b/vtm-android-example/src/org/oscim/android/filepicker/ValidRenderTheme.java @@ -1,6 +1,6 @@ /* * Copyright 2010, 2011, 2012 mapsforge.org - * Copyright 2016 devemux86 + * Copyright 2016-2017 devemux86 * Copyright 2017 Longri * * This program is free software: you can redistribute it and/or modify it under the @@ -27,7 +27,6 @@ import org.xml.sax.helpers.DefaultHandler; import java.io.File; -import java.io.FileInputStream; import javax.xml.parsers.SAXParserFactory; @@ -43,7 +42,7 @@ public boolean accept(File file) { try { ThemeFile theme = new ExternalRenderTheme(file.getAbsolutePath()); DefaultHandler renderThemeHandler; - if (ThemeUtils.isMapsforgeTheme(new FileInputStream(file))) + if (ThemeUtils.isMapsforgeTheme(theme)) renderThemeHandler = new XmlMapsforgeThemeBuilder(theme); else renderThemeHandler = new XmlThemeBuilder(theme); diff --git a/vtm-android-example/src/org/oscim/android/test/MapsforgeStyleActivity.java b/vtm-android-example/src/org/oscim/android/test/MapsforgeStyleActivity.java index 9dff4f0a7..0c3a6c30d 100644 --- a/vtm-android-example/src/org/oscim/android/test/MapsforgeStyleActivity.java +++ b/vtm-android-example/src/org/oscim/android/test/MapsforgeStyleActivity.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 devemux86 + * Copyright 2016-2017 devemux86 * * This program is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free Software @@ -58,7 +58,7 @@ public boolean onOptionsItemSelected(MenuItem item) { @Override protected void loadTheme(final String styleId) { - mMap.setTheme(new AssetsRenderTheme(this, "", "vtm/stylemenu.xml", new XmlRenderThemeMenuCallback() { + mMap.setTheme(new AssetsRenderTheme(getAssets(), "", "vtm/stylemenu.xml", new XmlRenderThemeMenuCallback() { @Override public Set getCategories(XmlRenderThemeStyleMenu renderThemeStyleMenu) { // Use the selected style or the default diff --git a/vtm-android/src/org/oscim/android/theme/AssetsRenderTheme.java b/vtm-android/src/org/oscim/android/theme/AssetsRenderTheme.java index 5e4642e59..d1c61a8a4 100644 --- a/vtm-android/src/org/oscim/android/theme/AssetsRenderTheme.java +++ b/vtm-android/src/org/oscim/android/theme/AssetsRenderTheme.java @@ -15,7 +15,7 @@ */ package org.oscim.android.theme; -import android.content.Context; +import android.content.res.AssetManager; import android.text.TextUtils; import org.oscim.theme.IRenderTheme.ThemeException; @@ -33,36 +33,33 @@ public class AssetsRenderTheme implements ThemeFile { private static final long serialVersionUID = 1L; - private final InputStream mInputStream; + private final AssetManager mAssetManager; + private final String mFileName; private XmlRenderThemeMenuCallback mMenuCallback; private final String mRelativePathPrefix; /** - * @param context the Android context. + * @param assetManager the Android asset manager. * @param relativePathPrefix the prefix for all relative resource paths. * @param fileName the path to the XML render theme file. * @throws ThemeException if an error occurs while reading the render theme XML. */ - public AssetsRenderTheme(Context context, String relativePathPrefix, String fileName) throws ThemeException { - this(context, relativePathPrefix, fileName, null); + public AssetsRenderTheme(AssetManager assetManager, String relativePathPrefix, String fileName) throws ThemeException { + this(assetManager, relativePathPrefix, fileName, null); } /** - * @param context the Android context. + * @param assetManager the Android asset manager. * @param relativePathPrefix the prefix for all relative resource paths. * @param fileName the path to the XML render theme file. * @param menuCallback the interface callback to create a settings menu on the fly. * @throws ThemeException if an error occurs while reading the render theme XML. */ - public AssetsRenderTheme(Context context, String relativePathPrefix, String fileName, XmlRenderThemeMenuCallback menuCallback) throws ThemeException { + public AssetsRenderTheme(AssetManager assetManager, String relativePathPrefix, String fileName, XmlRenderThemeMenuCallback menuCallback) throws ThemeException { + mAssetManager = assetManager; mRelativePathPrefix = relativePathPrefix; + mFileName = fileName; mMenuCallback = menuCallback; - - try { - mInputStream = context.getAssets().open((TextUtils.isEmpty(mRelativePathPrefix) ? "" : mRelativePathPrefix) + fileName); - } catch (IOException e) { - throw new ThemeException(e.getMessage()); - } } @Override @@ -73,7 +70,7 @@ public boolean equals(Object obj) { return false; } AssetsRenderTheme other = (AssetsRenderTheme) obj; - if (mInputStream != other.mInputStream) { + if (getRenderThemeAsStream() != other.getRenderThemeAsStream()) { return false; } if (!Utils.equals(mRelativePathPrefix, other.mRelativePathPrefix)) { @@ -94,7 +91,11 @@ public String getRelativePathPrefix() { @Override public InputStream getRenderThemeAsStream() throws ThemeException { - return mInputStream; + try { + return mAssetManager.open((TextUtils.isEmpty(mRelativePathPrefix) ? "" : mRelativePathPrefix) + mFileName); + } catch (IOException e) { + throw new ThemeException(e.getMessage()); + } } @Override diff --git a/vtm/src/org/oscim/theme/StreamRenderTheme.java b/vtm/src/org/oscim/theme/StreamRenderTheme.java index c9a591f8d..6bf3660ad 100644 --- a/vtm/src/org/oscim/theme/StreamRenderTheme.java +++ b/vtm/src/org/oscim/theme/StreamRenderTheme.java @@ -17,6 +17,8 @@ import org.oscim.theme.IRenderTheme.ThemeException; import org.oscim.utils.Utils; +import java.io.BufferedInputStream; +import java.io.IOException; import java.io.InputStream; /** @@ -45,7 +47,8 @@ public StreamRenderTheme(String relativePathPrefix, InputStream inputStream) { */ public StreamRenderTheme(String relativePathPrefix, InputStream inputStream, XmlRenderThemeMenuCallback menuCallback) { mRelativePathPrefix = relativePathPrefix; - mInputStream = inputStream; + mInputStream = new BufferedInputStream(inputStream); + mInputStream.mark(0); mMenuCallback = menuCallback; } @@ -78,6 +81,11 @@ public String getRelativePathPrefix() { @Override public InputStream getRenderThemeAsStream() throws ThemeException { + try { + mInputStream.reset(); + } catch (IOException e) { + throw new ThemeException(e.getMessage()); + } return mInputStream; } diff --git a/vtm/src/org/oscim/theme/ThemeLoader.java b/vtm/src/org/oscim/theme/ThemeLoader.java index a999d98d6..adcafee5a 100644 --- a/vtm/src/org/oscim/theme/ThemeLoader.java +++ b/vtm/src/org/oscim/theme/ThemeLoader.java @@ -48,7 +48,7 @@ public static IRenderTheme load(ThemeFile theme) throws ThemeException { public static IRenderTheme load(ThemeFile theme, ThemeCallback themeCallback) throws ThemeException { IRenderTheme t; - if (ThemeUtils.isMapsforgeTheme(theme.getRenderThemeAsStream())) + if (ThemeUtils.isMapsforgeTheme(theme)) t = USE_ATLAS ? XmlMapsforgeAtlasThemeBuilder.read(theme, themeCallback) : XmlMapsforgeThemeBuilder.read(theme, themeCallback); else t = USE_ATLAS ? XmlAtlasThemeBuilder.read(theme, themeCallback) : XmlThemeBuilder.read(theme, themeCallback); diff --git a/vtm/src/org/oscim/theme/ThemeUtils.java b/vtm/src/org/oscim/theme/ThemeUtils.java index e5b9d5d1e..849e9ccdb 100644 --- a/vtm/src/org/oscim/theme/ThemeUtils.java +++ b/vtm/src/org/oscim/theme/ThemeUtils.java @@ -15,20 +15,15 @@ */ package org.oscim.theme; -import org.oscim.utils.IOUtils; +import org.oscim.backend.XMLReaderAdapter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.xml.sax.Attributes; -import org.xml.sax.InputSource; import org.xml.sax.SAXException; -import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; -import java.io.InputStream; import java.util.concurrent.atomic.AtomicBoolean; -import javax.xml.parsers.SAXParserFactory; - /** * A utility class with theme specific helper methods. */ @@ -37,25 +32,21 @@ public final class ThemeUtils { private static final Logger log = LoggerFactory.getLogger(ThemeUtils.class); /** - * Check if the given InputStream is a Mapsforge render theme. + * Check if the given theme is a Mapsforge one. */ - public static boolean isMapsforgeTheme(InputStream is) { + public static boolean isMapsforgeTheme(ThemeFile theme) { try { final AtomicBoolean isMapsforgeTheme = new AtomicBoolean(false); - SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setNamespaceAware(true); - XMLReader xmlReader = factory.newSAXParser().getXMLReader(); - xmlReader.setContentHandler(new DefaultHandler() { - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { - if (localName.equals("rendertheme")) { - isMapsforgeTheme.set(uri.equals("http://mapsforge.org/renderTheme")); - // We have all info, break parsing - throw new SAXTerminationException(); - } - } - }); try { - xmlReader.parse(new InputSource(is)); + new XMLReaderAdapter().parse(new DefaultHandler() { + public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + if (localName.equals("rendertheme")) { + isMapsforgeTheme.set(uri.equals("http://mapsforge.org/renderTheme")); + // We have all info, break parsing + throw new SAXTerminationException(); + } + } + }, theme.getRenderThemeAsStream()); } catch (SAXTerminationException e) { // Do nothing } @@ -63,8 +54,6 @@ public void startElement(String uri, String localName, String qName, Attributes } catch (Exception e) { log.error(e.getMessage(), e); return false; - } finally { - IOUtils.closeQuietly(is); } }