import java.text.*; import java.io.*; import java.util.*; /** * Apuluokka, jolla voi näyttää lokalisoidun poikkeusilmoituksen, joka * riippuu poikkeuksen luokasta. Luokassa käytetään MessageFormat-luokkaa * ja sitä käytettäessä voidaan näyttää viisi merkkijonoa: * {0}: Virheen tai poikkeuksen sisältämä teksti. * {1}: Poikkeuksen tai virheen täydellinen luokkanimi. * {2}: Arvaus, missä tiedostossa poikkeus tapahtui. * {3}: Ko. tiedoston rivinumero. * {4}: Kuluva päivä ja kellonaika. * Ilmoitustekstit etsitään resurssinipusta, jonka perusnimi on "Errors". * Resurssin nimenä käytetään poikkeusolion luokan täydellistä nimeä. * Jos tiettyä poikkeusta vastaavaa resurssia ei ole, kysytään yliluokilta. */ public class LocalizedError { public static void display(Throwable error) { ResourceBundle bundle; // Pyydetään resurssinippu. // Jos sitä ei ole, näytetään ilmoitus lokalisoimatta. try { bundle = ResourceBundle.getBundle("Errors"); } catch (MissingResourceException e) { error.printStackTrace(System.err); return; } // Etsitään ko. nipusta resurssi virheen (tai sen yliluokan nimellä) // Jos resurssia ei ole, näytetään ilmoitus lokalisoimatta. String message = null; Class c = error.getClass(); while((message == null) && (c != Object.class)) { try { message = bundle.getString(c.getName()); } catch (MissingResourceException e) { c = c.getSuperclass(); } } if (message == null) { error.printStackTrace(System.err); return; } // Yritetään päätellä tiedosto ja rivi, jolla poikkeus tapahtui. // Tulostetaan virheen pinovedos merkkijonoon ja tulkitaan merkkijono // niin, että ensimmäinen pinovedoksessa oleva rivinumero tulee // ensimmäisen tai toisen kaksoispisteen jälkeen. Oletetaan, että tämä // kohta on ensimmäinen paikka, jota ohjelmoija itse voi hallita joten // valitaan se paikaksi, jossa poikkeus tapahtui. String filename = ""; int linenum = 0; try { // Merkkijonoon kirjoittava tulosvirta. StringWriter sw = new StringWriter(); PrintWriter out = new PrintWriter(sw); // PrintWriter-olio. error.printStackTrace(out); // Tulostetaan vedos pinosta. // Pyydetään vedos merkkijonona. String trace = sw.toString(); // Etsitään ensimmäinen kaksoispiste. int pos = trace.indexOf(':'); // Jos virheeseen liittyy teksti,etsitään seuraava kaksoispiste. if (error.getMessage() != null) pos = trace.indexOf(':', pos+1); int pos2 = trace.indexOf(')', pos); // Etsitään rivinumeron loppu. // Otetaan rivinumero. linenum = Integer.parseInt(trace.substring(pos+1,pos2)); // Takaisin tiedostonimen alkuun. pos2 = trace.lastIndexOf('(', pos); filename = trace.substring(pos2+1, pos); // Otetaan tiedostonimi. } // Poikkeukset jätetään käsittelemättä. catch (Exception e) { ; } // Luodaan taulukko, johon viedään ilmoituksen vaihtuvat osat. String errmsg = error.getMessage(); Object[] args = { ((errmsg!= null)?errmsg:""), error.getClass().getName(), filename, new Integer(linenum), new Date() }; // Näytetään lopuksi lokalisoitu virheilmoitus käyttäen // MessageFormat.format()-metodia, joka korvaa ilmoituksen vaihtuvat // osat. System.out.println(MessageFormat.format(message, args)); } }