/** * Title: * Description: * Copyright: Copyright (c) 2002 * Company: * @author * @version 1.0 */ import java.util.*; import java.io.*; import java.net.*; public class DataReader extends Thread{ Kilpailu kilp; // Kilpailu-olio, jolle tiedot lähetetään String id; // appletilta saatu tunnus, jonka avulla tietoja haetaan OLiveResults olr; // isäntä-appletti, tarvitaan publicIP:n hakemiseen int demowait; // ominaisuus, joka kertoo kuinka tiheään teitoja vastaanotetaan int port; // mihin sokettityhteys avataan (määritelty myöhemmin staattisena) private String host; // mihin sokettityhteys avataan (määritelty myöhemmin staattisena) private String publicIP=null; // oma IP, palvelin haluaa tietää private String myhost; // oma host, palvelin haluaa tietää private boolean socketopen=false; // onko soketti auki private Socket socket; // käytettävä soketti, kaikki metodit käyttävät samaa (paitsi getPublicIP, joka toimii URL-HTTP -pohjalta) private BufferedReader in2; // soketista otettava BufferedReader private PrintStream out; // soketista otettava PrintStream private String myemail; // oma e-mail, palvelin haluaa tietää private String mygsm; // oma gsm, palvelin haluaa tietää private int viime = 0; // kuinka monta riviä tulossanomia on luettu private int lines = 0; // montako riviä luettu ko. yrityksellä //(jos tehdään silmukka joka lukee uudelleen tiedot alusta, lähetetään niitä vasta kun viime on saavutettu) private String uusin = "0"; // suurin vastaanotettu aikaleima, tietoa ei lähetetä, jos aikaleima on pienempi kuin uusin // uusillakin riveillä voi tulla samoja tietoja uudestaan jolloin aikaleima on pienempi) // (jos sama tieto tulee uudella aikaleimalla, tämä kontrolliodaan Kilpailu-oliossa) int status = 0; // kuinka monta riviä tämänhetkinen kanta sisältää private String statusaika = "0"; // tämänhetkisen kannan aikaleima, päivitetään näyttö vasta, kun tulee suurempi aikaleima tai rivejä on luettu yli status kpl private boolean paivitetty=false; // kertoo, onko näyttöä jo päivitetty, jos on niin kaikki tiedot lähtee kisaaData -metodille parametrilla ipaivitys = true int pollaus = 60; // oletusarvo pollausaikavälille // otetaan viitteet tarvittaviin olioihin public DataReader(Kilpailu ikilp, String iid, String imyemail, String imygsm, OLiveResults iolr, int idemowait) { kilp = ikilp; id = iid; myemail = imyemail; mygsm= imygsm; olr =iolr; demowait = idemowait; } // kaikkien sokettiyhteyksien alussa suoritettavat rutiinit, jos ei // onnistu, niin heittää poikkeuksen, joka käsitellään ao. metodissa private void kattely(String output) throws Exception { if (!socketopen) { //kilp.monitor("avataan yhteyttä..."); socket = new Socket("www.suunnistus.info", 9004); in2 = new BufferedReader( new InputStreamReader(socket.getInputStream())); out = new PrintStream(socket.getOutputStream()); socketopen=true; } String str; out.println(id + " " + myhost + " " + publicIP + " " +myemail + " " + mygsm ); if(!(str = in2.readLine()).startsWith("OK")) { System.out.println(str); throw new ProtocolException(); } out.println(output); if(!(str = in2.readLine()).startsWith("OK")) throw new ProtocolException(); if ((str = in2.readLine()).startsWith("ERR")) throw new ProtocolException(); } public void suljeSoketti() { try {if (in2 != null) {in2.close();}} catch(Exception e) {} try {if (out != null) {out.close();}} catch(Exception e) {} try {if (socket != null) {socket.close();}} catch(Exception e) {} socketopen = false; } //varsinainen DataReader-olion toimintarunko public void run() { //jos ei saada publicIPta, ei soketitkaan aukea if(!getPublicIP()) { kilp.monitor("yhteyden avaaminen ei onnistu (1)"); return; } myhost=olr.getCodeBase().getHost(); if(myhost.equals("")) myhost="JB4"; //yritetään lukea lähtölistat ja Status (kuinka iso kanta), jos ei onnistus, niin ei haittaa vaan jatketaan kilp.monitor("yritetään ladata lähtölistoja"); lueLahtolistat(); //käytetty debuggaukseen //kilp.naytaSarjaLista(); //paivitetty=true; lueStatus(10); if(status<1) { kilp.naytaSarjaLista(); paivitetty = true; kilp.monitor("odotetaan uusia tietoja"); } String str=""; //tätä silmukkaa toistetaan säikeen elinajan, pois pääsee vain interruptedExceptinilla // tai 5 kertaa peräkkäin epäonnistuneella kättelyllä // eli jos yhteys katkeaa lukemisen aikana, tulee IOException, joka otetaan lopussa kiinni // ja aloitetaan kättely uudestaan eka: while(true) { lines = 0; //yritetään 5 kertaa kättelyä for(int i=0;i<5;i++) { try { kilp.monitor("avataan yhteyttä tuloksille"); kattely("DB SHOWALL OPEN"); break; } catch (InterruptedException ex) { suljeSoketti(); return; } catch (Exception ex) { suljeSoketti(); System.out.println("epäonnistunut kättely:"+i); ex.printStackTrace(); // 5 sekunnnin tauko kättely-yritysten välillä for(int j =5;j>0;j--) { kilp.monitor("ei saada yhteyttä... uusi yritys "+j+"..." ); try{sleep(1000);}catch(Exception ex1) {ex1.printStackTrace();suljeSoketti();return;} } } } //jos 5 yritystä ei tuottaneet tulosta if(!socketopen) { kilp.monitor("yhteyden muodostaminen epäonnistui... aloita valikosta uudelleen"); return; } kilp.monitor("luetaan tähänastisia tietoja"); if(paivitetty) kilp.monitor("odotetaan uusia tietoja"); try { toka: while (!this.isInterrupted()) { str = in2.readLine(); if(str.startsWith("ATT")) { try {pollaus = Integer.parseInt(str.substring(4));} catch (Exception ex) {ex.printStackTrace();} suljeSoketti(); siirryPollausMoodiin(); return; } lines++; if(lines>viime){ if(str!=null){ if(!str.startsWith("#") && str.length()>20) if(analysoiData(str,(paivitetty || lines>status)) && !paivitetty) {kilp.naytaSarjaLista(); paivitetty = true; kilp.monitor("odotetaan uusia tietoja");} if (str.startsWith("OK") ) break; // loppu ??? viime = lines; } try { //double a = Math.random()*1000*demowait; //int b = (int)a; int b=100; if(!paivitetty) b=0; yield(); Thread.sleep(b); } catch(InterruptedException _ex) { suljeSoketti(); socketopen = false; break eka; } } } suljeSoketti(); kilp.monitor("yhteyden avaaminen ei onnistu (3)"); System.out.println(str); } catch (Exception e) { suljeSoketti(); kilp.monitor("yhteys katkennut"); e.printStackTrace(); } } suljeSoketti(); } public boolean getPublicIP() { URL base = olr.getDocumentBase(); //String path = base.getProtocol()+"://"+base.getHost()+"/cgi-bin/textdb/myip"; String path = "http://www.suunnistus.info/cgi-bin/textdb/myip"; BufferedReader in = null; try { URL url = new URL(path); in = new BufferedReader( new InputStreamReader( url.openStream() )); String line; while ((line = in.readLine()) != null) { publicIP=line; } if(in!=null) in.close(); return true; } catch(MalformedURLException e) { return false; } catch(IOException ee) { try {if(in!=null) in.close();} catch (Exception e){} return false; } finally { //suljetaan virta try { if (in!= null) in.close(); } catch(IOException ioe) {} } } // palauttaa tiedon pitääkö näyttö päivitää // param istatus, kertoo pitääkö kutsuvan metodin mielestä näyttö päivittää // = true jos lines > status tai on jo päivittety // tämä metodi voi palauttaa istauksesta huolimatta true, jos aikaleima ylittää statusajan private boolean analysoiData(String data, boolean istatus) { data = korvaa(data,";;","; ;"); try{ StringTokenizer st1 = new StringTokenizer(data,";"); st1.nextToken(); String aikaleima = st1.nextToken(); //testataan, onko aikaleima vanhempi kuin uusin //samaa asiaa testataan rivimäärilläkin, siis tuplavarmistus if(aikaleima.compareTo(uusin)<0) return istatus && !paivitetty; // tässä päivitetään jos lines>status muttei ole vielä päivitetty // jos on jo päivitetty, ei kannata päivittää, kun tietoakaan ei lisätä uusin = aikaleima; String sarja = st1.nextToken(); String matka = st1.nextToken(); int nro = Integer.parseInt(st1.nextToken()); String nimi = st1.nextToken() + " " + st1.nextToken(); String seura = st1.nextToken(); String aika= st1.nextToken(); int aikasek = Integer.parseInt(st1.nextToken()); kilp.lisaaData(aikaleima,sarja,matka,nro,nimi,seura,aika,aikasek,(istatus || aikaleima.compareTo(statusaika)>0)); return(istatus || aikaleima.compareTo(statusaika)>0); } catch(Exception e) { e.printStackTrace(); System.out.println("ongelmarivi:\n"+data); return istatus; } } private static String korvaa(String aSearch, String aFind, String aReplace) { String result = aSearch; if (result != null && result.length() > 0) { int a = 0; int b = 0; while (true) { a = result.indexOf(aFind, b); if (a != -1) { result = result.substring(0, a) + aReplace + result.substring(a + aFind.length()); b = a + aReplace.length(); } else break; } } return result; } private void lueStatus(int varmuusvara) { String str; try { kattely("DB STATUS"); } catch (Exception ex) { suljeSoketti(); ex.printStackTrace(); return; } try { str = in2.readLine(); StringTokenizer st1 = new StringTokenizer(str,";"); if(st1.countTokens()==8) { statusaika =""; for(int i=0;i<6;i++) statusaika += st1.nextToken(); st1.nextToken(); // luetaan status, joka kertoo montako riviä kannassa on juuri nyt, näytön päivitys teh- // dään vasta, kun status kpl rivejä on luettu // -10 varmuuden vuoksi try{status=Integer.parseInt(st1.nextToken())-varmuusvara;}catch(Exception ex){} } suljeSoketti(); } catch (Exception e) { suljeSoketti(); //kilp.monitor("yhteys katkennut"); e.printStackTrace(); } } private void siirryPollausMoodiin() { String str; kilp.monitor("siirrytään pollausmoodiin "+pollaus); //luetaan nykyiset statustiedot int aikStatus = status; String aikStatusaika = statusaika; boolean onnistuiko = false; if(!paivitetty) { kilp.naytaSarjaLista(); paivitetty = true; kilp.monitor("odotetaan uusia tietoja"); } //toistetaan säikeen loppuun asti eka: while(!this.isInterrupted()) { for(int i = pollaus;i>0;i--) { kilp.monitor("pollausmoodi...tietojen lukuun "+i); try { yield(); Thread.sleep(1000); } catch(InterruptedException _ex) { suljeSoketti(); socketopen = false; break eka; } } aikStatus = (status<0?0:status); aikStatusaika = statusaika; lueStatus(0); kilp.monitor("luetaan tietoja..."); //jos on muutoksia if(status>aikStatus || statusaika.compareTo(aikStatusaika)>0 || (!onnistuiko && status>lines)) { //System.out.println("st"+status+" as"+aikStatus+" l"+lines); try { kilp.monitor("avataan yhteyttä tuloksille"); kattely("DB "+ (onnistuiko?aikStatus+"":(lines20) analysoiData(str,true); } catch (Exception ex) { suljeSoketti(); socketopen = false; break toka; } } suljeSoketti(); } } } suljeSoketti(); return; } private void lueLahtolistat() { String str; Vector sarjat = new Vector(); try { kattely("START LISTCLASS"); } catch (Exception ex) { suljeSoketti(); ex.printStackTrace(); return; } try { while((str = in2.readLine())!=null && !str.startsWith("OK")) { if(str.equals("ONELIST")) { try {if (in2 != null) {in2.close(); out.close();}} catch(IOException ioe) {} socketopen = false; haeONELIST(); return; } else { StringTokenizer st1 = new StringTokenizer(str,";"); if(!str.startsWith("#") && st1.hasMoreTokens()) sarjat.addElement(st1.nextToken()); } } suljeSoketti(); } catch (Exception e) { suljeSoketti(); kilp.monitor("yhteys katkennut"); e.printStackTrace(); } for(int i=0;i6) { sarja = rivi.substring(6).trim(); while(sarja.endsWith(";")) sarja = sarja.substring(0,sarja.length()-1); if (sarja.indexOf(';')>0) { matka = sarja.substring(sarja.indexOf(';')+1); sarja = sarja.substring(0,sarja.indexOf(';')); } else matka = ""; } data = ""; } else if (rivi.length()>10) data += rivi +"\n"; } if(!sarja.equals("") && !data.equals("")) { kilp.teeSarja(sarja,matka,data); kilp.monitor(sarja); } suljeSoketti(); } catch (Exception e) { suljeSoketti(); kilp.monitor("virhe lähtölistojen luvussa"); e.printStackTrace(); } } private void haeSarjanlista(String isarja) { String str; Vector sarjat = new Vector(); try { kattely("START "+isarja); } catch (Exception ex) { suljeSoketti(); ex.printStackTrace(); return; } try { kilp.monitor("ladataan lähtölistoja"); String sarja = isarja; String matka =""; String rivi = in2.readLine(); if(rivi.startsWith("#") && rivi.indexOf(';')>0); { sarja = rivi.substring(rivi.indexOf(';')+1).trim(); while(sarja.endsWith(";")) sarja = sarja.substring(0,sarja.length()-1); if (sarja.indexOf(';')>0) { matka = sarja.substring(sarja.indexOf(';')+1); sarja = sarja.substring(0,sarja.indexOf(';')); } else matka = ""; } String data = ""; while((rivi=in2.readLine()) != null) if (rivi.length()>10) data += rivi +"\n"; if(!sarja.equals("") && !data.equals("")) { kilp.teeSarja(sarja,matka,data); kilp.monitor(sarja); } suljeSoketti(); } catch (Exception e) { suljeSoketti(); kilp.monitor("virhe lähtölistojen luvussa"); e.printStackTrace(); } } }