/* * TV-Browser for Android * Copyright (C) 2013 René Mach (rene@tvbrowser.org) * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to use, copy, modify or merge the Software, * furthermore to publish and distribute the Software free of charge without modifications and to * permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package org.tvbrowser.tvbrowser; import java.io.BufferedReader; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; import java.util.Random; import org.tvbrowser.settings.SettingConstants; import org.tvbrowser.utils.IOUtils; /** * Class with informations about a webserver for data update. * <p> * @author René Mach */ public class Mirror implements Comparable<Mirror> { private String mUrl; private int mWeight; private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); public Mirror(String url, int weight) { mUrl = url; mWeight = weight; } public String getUrl() { return mUrl; } public int getWeight() { return mWeight; } /** * Gets the mirror array from the given text. * <p> * @param value The text containing the mirror information. * @return The array with Mirrors. */ public static Mirror[] getMirrorsFor(String value) { ArrayList<Mirror> mirrors = new ArrayList<Mirror>(); String[] mirrorParts = value.split(";"); for(String part : mirrorParts) { if(part.contains("#")) { String[] mirrorValues = part.split("#"); if(mirrorValues.length == 2) { if(!mirrorValues[0].endsWith("/")) { mirrorValues[0] += "/"; } try { mirrors.add(new Mirror(mirrorValues[0], Integer.valueOf(mirrorValues[1]))); }catch(NumberFormatException e) {} } } else { if(!part.endsWith("/")) { part += "/"; } mirrors.add(new Mirror(part, 10)); } } Mirror[] mirrorArr = new Mirror[mirrors.size()]; return mirrors.toArray(mirrorArr); } @Override public int compareTo(Mirror another) { if(mWeight < another.mWeight) { return -1; } else if(mWeight > another.mWeight) { return 1; } return 0; } public static Mirror getMirrorToUseForGroup(Mirror[] mirrors, String group, TvDataUpdateService update, boolean checkOnlyConnection) { ArrayList<Mirror> toChooseFrom = new ArrayList<Mirror>(Arrays.asList(mirrors)); Mirror choosen = null; while(choosen == null && !toChooseFrom.isEmpty()) { int weightSum = 0; for(Mirror mirror : toChooseFrom) { weightSum += mirror.getWeight(); } int limit = new Random().nextInt(weightSum + 1); update.doLog("Mirror weight limit for group '" + group + "': " + limit); final ArrayList<Mirror> mirrorsWithAcceptedWeight = new ArrayList<Mirror>(); for(int i = toChooseFrom.size()-1; i >= 0; i--) { if(toChooseFrom.get(i).getWeight() >= limit) { mirrorsWithAcceptedWeight.add(toChooseFrom.get(i)); } else { update.doLog("NOT accepted miror for group (weigth to low) '" + group + "': " + toChooseFrom.get(i).getUrl()); } } while(choosen == null && !mirrorsWithAcceptedWeight.isEmpty()) { final Mirror test = mirrorsWithAcceptedWeight.remove((int)(Math.random() * mirrorsWithAcceptedWeight.size())); update.doLog("Accepted weight for group '" + group + "': " + test.getWeight() + " URL: " + test.getUrl()); if((!checkOnlyConnection && useMirror(test,group,5000,update)) || IOUtils.isConnectedToServer(test.getUrl(), 5000)) { update.doLog("Accepted miror for group '" + group + "': " + test.getUrl()); choosen = test; } else { toChooseFrom.remove(test); update.doLog("NOT accepted miror for group '" + group + "': " + test.getUrl()); } } } return choosen; } private static boolean useMirror(Mirror mirror, String group, int timeout, TvDataUpdateService update) { boolean success = false; HttpURLConnection connection = null; BufferedReader read = null; try{ URL myUrl = new URL(mirror.getUrl() + group + "_lastupdate"); connection = (HttpURLConnection) myUrl.openConnection(); IOUtils.setConnectionTimeout(connection,timeout); int responseCode = connection.getResponseCode(); update.doLog("HTTP-Response for group: '" + group + "' from URL: " + myUrl); if(responseCode == HttpURLConnection.HTTP_OK) { read = new BufferedReader(new InputStreamReader(connection.getInputStream())); String date = read.readLine(); Date serverDate = DATE_FORMAT.parse(date); update.doLog("Date of data for: '" + group + "' from URL '" + myUrl + "' " + serverDate + " diff to now: " + (((System.currentTimeMillis() - serverDate.getTime()) / 1000 / 60 / 60 / 24))); // only if update date on server is acceptable success = (((System.currentTimeMillis() - serverDate.getTime()) / 1000 / 60 / 60 / 24)) <= SettingConstants.ACCEPTED_DAY_COUNT; } } catch (Exception e) { StackTraceElement[] elements = e.getStackTrace(); StringBuilder message = new StringBuilder(); for(StackTraceElement el : elements) { message.append(el.getFileName()).append(" ").append(el.getLineNumber()).append(" ").append(el.getClassName()).append(" ").append(el.getMethodName()).append("\n"); } update.doLog("Exception for mirror check for '" + group + "' from URL: " + mirror.getUrl() + " ERROR: " + message.toString()); // Handle your exceptions success = false; } finally { IOUtils.close(read); IOUtils.disconnect(connection); } return success; } }