diff --git a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java index a4780c6c2c..89ac033e38 100644 --- a/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java +++ b/OsmAnd/src/net/osmand/plus/SQLiteTileSource.java @@ -3,6 +3,7 @@ package net.osmand.plus; import android.database.sqlite.SQLiteDiskIOException; import android.graphics.Bitmap; import android.graphics.BitmapFactory; +import android.os.Build; import android.widget.Toast; import net.osmand.IndexConstants; @@ -24,6 +25,8 @@ import java.nio.ByteBuffer; import java.text.MessageFormat; import java.util.Arrays; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import bsh.Interpreter; @@ -52,9 +55,11 @@ public class SQLiteTileSource implements ITileSource { boolean tileSizeSpecified = false; private OsmandApplication ctx; private boolean onlyReadonlyAvailable = false; - - - + + private static final Pattern RND_PATTERN = + Pattern.compile(".*(\\{rnd:([0-9a-zA-Z-_~:\\/?#\\[\\]@!$&'\\(\\)*+,;=]+)\\}).*"); + + public SQLiteTileSource(OsmandApplication ctx, File f, List toFindUrl){ this.ctx = ctx; this.file = f; @@ -112,26 +117,49 @@ public class SQLiteTileSource implements ITileSource { if (zoom > maxZoom) return null; SQLiteConnection db = getDatabase(); - if(db == null || db.isReadOnly() || urlTemplate == null){ + if (db == null || db.isReadOnly() || urlTemplate == null) { return null; } - if(TileSourceManager.RULE_BEANSHELL.equalsIgnoreCase(rule)){ - try { - if(bshInterpreter == null){ - bshInterpreter = new Interpreter(); - bshInterpreter.eval(urlTemplate); + String urlTemplate = this.urlTemplate; + try { + Matcher matcher = RND_PATTERN.matcher(urlTemplate); + if (matcher.matches()) { + int i = 0; + String rndString = matcher.group(1); + String valuesString = matcher.group(2); + if (!Algorithms.isEmpty(valuesString)) { + String[] valuesArray = valuesString.split(","); + if (valuesArray.length > 0) { + i = ((x + y) % valuesArray.length); + } } - return (String) bshInterpreter.eval("getTileUrl("+zoom+","+x+","+y+");"); - } catch (bsh.EvalError e) { - LOG.debug("getUrlToLoad Error" + e.getMessage()); - Toast.makeText(ctx, e.getMessage(), Toast.LENGTH_LONG).show(); - LOG.error(e.getMessage(), e); - return null; + urlTemplate = urlTemplate.replace(rndString, i + ""); + return MessageFormat.format(urlTemplate, zoom + "", x + "", y + ""); + + } else if (TileSourceManager.RULE_BEANSHELL.equalsIgnoreCase(rule)) { + if (Build.VERSION.SDK_INT >= 28) { + Toast.makeText(ctx, "Beanshell is not supported on Android 9+ anymore. Use {rnd:1,2,3,a,b,c} pattern instead.", Toast.LENGTH_LONG).show(); + return null; + } + try { + if (bshInterpreter == null) { + bshInterpreter = new Interpreter(); + bshInterpreter.eval(urlTemplate); + } + return (String) bshInterpreter.eval("getTileUrl(" + zoom + "," + x + "," + y + ");"); + } catch (bsh.EvalError e) { + LOG.debug("getUrlToLoad Error" + e.getMessage()); + Toast.makeText(ctx, e.getMessage(), Toast.LENGTH_LONG).show(); + LOG.error(e.getMessage(), e); + return null; + } + } else { + return MessageFormat.format(urlTemplate, zoom + "", x + "", y + ""); } - } - else { - return MessageFormat.format(urlTemplate, zoom+"", x+"", y+""); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$ + } catch (IllegalArgumentException e) { + LOG.error("Cannot build url for template: " + urlTemplate, e); + return null; } }