// License: GPL. For details, see LICENSE file. package org.openstreetmap.josm.plugins.czechaddress.parser; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.plugins.czechaddress.DatabaseLoadException; import org.openstreetmap.josm.plugins.czechaddress.addressdatabase.Database; /** * General superclass for any parser capable of filling the database. * * @author Radomír Černoch, raodmir.cernoch@gmail.com * @see Database */ public abstract class DatabaseParser { /** Directory, where the parser can store cache data. */ protected String storageDir; /** * Sets the storage directory. */ public void setStorageDir(String storageDir) { this.storageDir = storageDir; } /** Target Database, which should be filled by the parser. */ protected Database target = null; /** * Sets the target database, which should be filled by the parser. */ public void setTargetDatabase(Database targetDatabase) { target = targetDatabase; } /** * The ultimate method, which starts filling the database. * * @throws DatabaseLoadException if anything goes wrong... */ public void fillDatabase() throws DatabaseLoadException { assert target != null; if (!(new File(getDatabasePath())).exists()) { Main.info("CzechAddress: Soubor s databází českých adres na disku nenalazen. Pokusím se jej stáhnout."); downloadDatabase(); } parseDatabase(); } /** * The internal method, which does the actual parsing. * * @throws DatabaseLoadException should be thrown if anything gets wrong... */ protected abstract void parseDatabase() throws DatabaseLoadException; /** * Returns a URL, where the database can be dowloaded from. This method * is used in the {@code dowloadDatabase()} method. */ protected abstract String getDatabaseUrl(); /** * Returns a path, where the database can be stored on local disk. */ protected abstract String getDatabasePath(); /** * Opens the database and provides an input stream to its content. * * @throws DatabaseLoadException should be thrown when the input cannot be opened. */ protected abstract InputStream getDatabaseStream() throws DatabaseLoadException; /** * Downloads the database from remote URL. * * The URL is provided by {@code getDatabaseUrl()} method. * * @throws DatabaseLoadException if any error occurs during the download. */ protected void downloadDatabase() throws DatabaseLoadException { try { URL url = new URL(getDatabaseUrl()); HttpURLConnection con = (HttpURLConnection) url.openConnection(); //Set timeout for 30 seconds. con.setReadTimeout(30000); con.connect(); Main.info("CzechAddress: Stahuji: " + url.toString()); Main.info("CzechAddress: Server vrátil: " + con.getResponseMessage()); // Check the status error code from server if (con.getResponseCode() != 200) throw new DatabaseLoadException( "Požadavek na server selhal, číslo chyby: " + String.valueOf(con.getResponseCode())); try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(getDatabasePath()))) { int total = 0, count; byte[] buffer = new byte[1024*512]; while ((count = con.getInputStream().read(buffer)) >= 0) { bos.write(buffer, 0, count); total += count; Main.info("CzechAddress: MVČR database: " + String.valueOf(total/1024) + " kb downloaded."); } } // Look for a detailed error message from the server if (con.getHeaderField("Error") != null) { String er = con.getHeaderField("Error"); throw new DatabaseLoadException("Server vrátil chybu: " + er); } con.disconnect(); } catch (IOException ioexp) { throw new DatabaseLoadException("Chyba při načítání databáze", ioexp); } } }