package sushi.weather.importer; import java.io.BufferedOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.net.SocketException; import java.util.ArrayList; import java.util.HashSet; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import sushi.FileUtils; import sushi.event.SushiEvent; import sushi.event.SushiEventType; import sushi.xml.importer.XMLParser; import sushi.xml.importer.XMLParsingException; import sushi.xml.importer.XSDParser; /** * Importer for Weather warnings from Deutscher Wetterdienst */ public class DWDImporter { static String server = "ftp-outgoing2.dwd.de"; static int port = 21; static String user = "IMSERT YOUR USERNAME"; static String pass = "INSERT YOUR PW"; private FTPClient ftpClient; private File downloadFolder; private File[] localFiles; // files in this list are not up to date and can be removed private HashSet<String> filesToDeleteAfterSync; // files in this list are new and need to be processed as events private HashSet<String> newFiles; public static void main(String[] args) throws IOException, XMLParsingException { // remote stuff DWDImporter importer = new DWDImporter(); // importer.downloadFilesFromFTPPathForLocation(remoteFolderPD, downloadFolder.getCanonicalPath(), "GDSX"); System.out.println("new weatherevents: " + importer. getNewWeatherEvents()); System.out.println("downloaded!"); importer.disconnect(); } /** * generates events from dwd ftp server * generate just events for the newest, unseen events * downloads just warnings from areas mentioned in syncAllWeatherWarningsExampleUseCase() */ public ArrayList<SushiEvent> getNewWeatherEvents() throws XMLParsingException, IOException{ this.init(); //to setup connection and reset lists and stuff syncAllWeatherWarningsExampleUseCase(); ArrayList<SushiEvent> events = new ArrayList<SushiEvent>(); for (File file: downloadFolder.listFiles()){ // only the new files are processed into events if (newFiles.contains(file.getName())) { events.add(XMLParser.generateEventFromXML(file.getCanonicalPath(), getXSDFilePath())); } } deleteOutDatedFiles(); return events; } /** * disconnects a running connection * setup fields for sync usage */ private void init() throws SocketException, IOException{ disconnect(); ftpClient = new FTPClient(); ftpClient.connect(server, port); ftpClient.login(user, pass); ftpClient.enterLocalPassiveMode(); ftpClient.setFileType(FTP.BINARY_FILE_TYPE); // create folder downloadFolder = new File(System.getProperty("user.dir")+"/bin/weatherXML/"); downloadFolder.mkdirs(); localFiles = downloadFolder.listFiles(); filesToDeleteAfterSync = new HashSet<String>(); for (File file : localFiles){ filesToDeleteAfterSync.add(file.getName()); } newFiles = new HashSet<String>(); } /** * returns the Eventtype generated from the XSD (located in getXSDFilePath()) */ public SushiEventType getWeatherEventtype() throws XMLParsingException{ SushiEventType weatherEventtype = SushiEventType.findBySchemaName("legend_warnings_CAP"); if (weatherEventtype != null){ return weatherEventtype; } else { return XSDParser.generateEventTypeFromXSD(getXSDFilePath(), FileUtils.getFileNameWithoutExtension(getXSDFilePath())); } } /** * call this after you are finished to close connection */ public void disconnect() throws IOException{ if (ftpClient != null && ftpClient.isConnected()) { ftpClient.logout(); ftpClient.disconnect(); } } /** * sync local downloadfolder with Warnings from Example Usecase, * delete local data which isn't any longer on ftp, * do not reload existing files which are local and on ftp, * import new files, * returns a list of new files */ private void syncAllWeatherWarningsExampleUseCase() throws IOException{ // Hansestadt Hamburg syncFilesFromFTPPathForLocation("gds/specials/warnings/xml/HA/", "HHXX"); // Kreis Herzogtum Lauenburg syncFilesFromFTPPathForLocation("gds/specials/warnings/xml/HA/", "RZXX"); // LK Ludwigslust-Parchim - West syncFilesFromFTPPathForLocation("gds/specials/warnings/xml/PD/", "LPWX"); // Prignitz syncFilesFromFTPPathForLocation("gds/specials/warnings/xml/PD/", "PRXX"); // Kreis Ostprignitz-Ruppin syncFilesFromFTPPathForLocation("gds/specials/warnings/xml/PD/", "OPRX"); // Oberhavel syncFilesFromFTPPathForLocation("gds/specials/warnings/xml/PD/", "OHVX"); // Berlin syncFilesFromFTPPathForLocation("gds/specials/warnings/xml/PD/", "BXXX"); } /** * syncs the local dwd folder with the remote ftp server, * deletes local data which no longer exist on ftp, * does nothing with files which are local and on ftp, * downloads new files, * @return list of new files */ private void syncFilesFromFTPPathForLocation(String ftpPathFolder, String dwdLocationAbreviation) throws IOException{ // list files on the ftp server on in the given folder location FTPFile[] remoteFiles = ftpClient.listFiles(ftpPathFolder); for (FTPFile remoteFile : remoteFiles){ // check if the file is for the given location and not already downloaded if (nameMatch(remoteFile.getName(), dwdLocationAbreviation) && !filesToDeleteAfterSync.contains(remoteFile.getName())){ // file representation of the file on the local system File downloadfile = new File(downloadFolder.getCanonicalPath() + "/" + remoteFile.getName()); OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(downloadfile)); // download the actual file ftpClient.retrieveFile(ftpPathFolder + remoteFile.getName(), outputStream); outputStream.close(); System.out.println("downloaded warnings from: " + remoteFile.getName()); // save file to new file list newFiles.add(remoteFile.getName()); } else if (nameMatch(remoteFile.getName(), dwdLocationAbreviation)) { // remote file is already on local folder and do not have to get deleted filesToDeleteAfterSync.remove(remoteFile.getName()); } } } /** * * @return XSD File for Validation */ public String getXSDFilePath(){ return System.getProperty("user.dir")+"/src/main/resources/legend_warnings_CAP.xsd"; } /** * * @param fileName Filename on the FTP server like Z_CAP_C_EDZW_20130430115427_OMEDES_WWHA81_HHXX.xml * @param locationAbreviation DWD Abreviation for the location. like 'HHXX' for Hansestadt Hamburg */ private boolean nameMatch(String fileName, String locationAbreviation){ return fileName.matches("^.+" + locationAbreviation +"\\.xml$"); } private void deleteOutDatedFiles(){ // clean folder for (File localFile: downloadFolder.listFiles()){ if (filesToDeleteAfterSync.contains(localFile.getName())){ System.out.println("deleted weather event file " + localFile.getName()); localFile.delete(); } } } }