/* ** This file is part of Filius, a network construction and simulation software. ** ** Originally created at the University of Siegen, Institute "Didactics of ** Informatics and E-Learning" by a students' project group: ** members (2006-2007): ** André Asschoff, Johannes Bade, Carsten Dittich, Thomas Gerding, ** Nadja Haßler, Ernst Johannes Klebert, Michell Weyer ** supervisors: ** Stefan Freischlad (maintainer until 2009), Peer Stechert ** Project is maintained since 2010 by Christian Eibl <filius@c.fameibl.de> ** and Stefan Freischlad ** Filius is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 2 of the License, or ** (at your option) version 3. ** ** Filius is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ** PURPOSE. See the GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with Filius. If not, see <http://www.gnu.org/licenses/>. */ package filius.rahmenprogramm; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.RandomAccessFile; import java.io.Serializable; import java.util.HashMap; import java.util.LinkedList; import java.util.Locale; import java.util.Random; import java.util.ResourceBundle; import java.util.StringTokenizer; import java.util.Vector; import javax.swing.JFileChooser; import filius.Main; import filius.gui.nachrichtensicht.LauscherDialog; /** * In dieser Klasse werden die Verwaltungs-Informationen des Rahmenprogramms * verwaltet, die unabhaengig von einem bestimmten Projekt sind. */ public class Information implements Serializable { private static final long serialVersionUID = 1L; /** Zur Implementierung des Singleton */ private static Information information = null; private static WinFolders winFolders = new WinFolders(); public boolean initOk = false; /** * Die MAC-Adressen werden zentral verwaltet, um zu gewaehrleisten, dass * keine Adresse mehrfach vergeben wird. */ private Vector<String> macAdressen; /** * Die maximale Anzahl von Vermittlungsstellen wird zur Berechnung des * Time-Outs fuer eine TCP-Verbindung genutzt. */ private int maxVermittlungsStellen; /** * Pfad zum Verzeichnis, in dem das Programm ausgefuehrt wird (in dem sich * die ausfuehrbare Jar-Datei befindet); <br /> * der Pfad schliesst mit dem Pfad-Trennzeichen (unter UNIX "/") */ private String programmPfad = null; /** * Pfad zum Verzeichnis, in dem die benutzerspezifischen Daten abgelegt * werden; <br /> * der Pfad schliesst mit dem Pfad-Trennzeichen (unter UNIX "/") */ public static String initArbeitsbereichPfad = getHomeDir() // System.getProperty("user.home") + System.getProperty("file.separator"); // actually used working directory, i.e., path to be used after initial // tests private String arbeitsbereichPfad = getHomeDir() // System.getProperty("user.home") + System.getProperty("file.separator") + ".filius" + System.getProperty("file.separator"); /** Lokalisierungsobjekt fuer Standard-Spracheinstellung */ private Locale locale = new Locale("de", "DE"); // private Locale locale = new Locale("en", "GB"); // //////////////////////////// private static String getHomeDir() { if (com.sun.jna.Platform.isWindows()) { try { String path = winFolders.getFolder(0x001C); // CSIDL_LOCAL_APPDATA return path; } catch (Exception e) { e.printStackTrace(); System.err .println("EXCEPTION: error on using Java native access"); return System.getProperty("user.home"); } } else { return System.getProperty("user.home"); } } // //////////////////////////////////// /** * ensure a correct and well functioning path to write all necessary data */ private boolean checkWD(String currPath) { boolean nowrite = true; String directoryPath; java.util.Random rnd = new java.util.Random(); String randomString = Long.toString(rnd.nextLong()); java.io.File testFile = null; do { directoryPath = currPath + ".filius" + System.getProperty("file.separator"); try { testFile = new java.io.File(directoryPath); // // write check, i.e., create random directory and delete it // again testFile.mkdirs(); testFile = new java.io.File(directoryPath + randomString); testFile.createNewFile(); if (!testFile.delete()) { throw new Exception( "EXCEPTION: Error on deleting test file in write-check"); } nowrite = false; } catch (Exception e) { // open dialog to choose another directory javax.swing.JOptionPane .showMessageDialog( null, "Fehler: Verzeichnis ist nicht schreibbar. Filius benötigt aber Schreibrechte.\n" + "Bitte wählen Sie ein Verzeichnis, für das Sie Schreibrechte besitzen.\n\n" + "Error: Directory is not writeable. But Filius needs write permissions.\n" + "Please choose a directory where you have write permissions.", "Fehler / Error", javax.swing.JOptionPane.ERROR_MESSAGE); JFileChooser fc = new JFileChooser(); fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); if (fc.showOpenDialog(new java.awt.Frame()) == JFileChooser.APPROVE_OPTION) { currPath = fc.getSelectedFile().getAbsolutePath() + System.getProperty("file.separator"); } else return false; } } while (nowrite); arbeitsbereichPfad = currPath + ".filius" + System.getProperty("file.separator"); // set correct path return true; } /** * nicht oeffentlich zugaenglicher Konstruktor, wird aus getInformation() * aufgerufen */ private Information() { if (checkWD(initArbeitsbereichPfad)) { reset(); initOk = true; } } private Information(String path) { if (checkWD(path)) { reset(); initOk = true; } } /** Methode zum Zugriff auf Singleton */ public static Information getInformation() { return getInformation((String) null); } public static Information getInformation(String path) { if (information == null) { if (path != null) information = new Information(path); else information = new Information(); } if (information.initOk) return information; else return null; } /** aktuelle Programmversion */ public static String getVersion() { return "1.4.3.1 (14. November 2011)"; } /** * Zugriff auf das sprachabhaengige Objekt zur Verwaltung der Texte. * * @return */ public ResourceBundle holeResourceBundle() { ResourceBundle bundle; bundle = ResourceBundle.getBundle("filius.messages.MessagesBundle", locale); return bundle; } public Locale getLocale() { return locale; } public void setLocale(Locale locale) { this.locale = locale; } /** * Zuruecksetzen aller Einstellungen, die zur Laufzeit von Filius veraendert * wurden und alle Projektspezifischen Daten. */ public void reset() { macAdressen = new Vector<String>(); maxVermittlungsStellen = 48; LauscherDialog.reset(); try { initialisiereVerzeichnisse(); } catch (Exception e) { e.printStackTrace(Main.debug); } SzenarioVerwaltung.loescheVerzeichnisInhalt(getTempPfad()); } /** * Hier werden die Verzeichnisse und die Datei mit den Informationen zu den * eigenen Anwendungen erstellt, wenn sie noch nicht existieren: * <ul> * <li>Arbeitsbereich: Verzeichnis, in dem alle benutzerspezifischen Daten * gespeichert werden</li> * <li>Temp: Verzeichnis, in dem zur Laufzeit temporaere Dateien gespeichert * werden</li> * <li>Anwendungen: Verzeichnis, in dem die eigenen Anwendungen gespeichert * werden mit den Unterordnern software/clientserver/ und * gui/anwendungssicht/</li> * <li>Datei, in der die Einstellungen zu eigenen Anwendungen gespeichert * werden</li> * </ul> */ private void initialisiereVerzeichnisse() throws FileNotFoundException, IOException { String pfad; pfad = getArbeitsbereichPfad(); if (!(new java.io.File(pfad)).exists()) if (!(new java.io.File(pfad)).mkdirs()) Main.debug.println("ERROR (" + this.hashCode() + ") " + getClass() + "\n\t" + pfad + " konnte nicht erzeugt werden"); pfad = getTempPfad(); if (!(new java.io.File(pfad)).exists()) if (!(new java.io.File(pfad)).mkdirs()) Main.debug.println("ERROR (" + this.hashCode() + ") " + getClass() + "\n\t" + pfad + " konnte nicht erzeugt werden"); pfad = getAnwendungenPfad(); if (!(new java.io.File(pfad)).exists()) if (!(new java.io.File(pfad)).mkdirs()) Main.debug.println("ERROR (" + this.hashCode() + ") " + getClass() + "\n\t" + pfad + " konnte nicht erzeugt werden"); pfad = getAnwendungenPfad() + "filius" + System.getProperty("file.separator") + "software" + System.getProperty("file.separator") + "clientserver" + System.getProperty("file.separator"); if (!(new java.io.File(pfad)).exists()) if (!(new java.io.File(pfad)).mkdirs()) Main.debug.println("ERROR (" + this.hashCode() + ") " + getClass() + "\n\t" + pfad + " konnte nicht erzeugt werden"); pfad = getAnwendungenPfad() + "filius" + System.getProperty("file.separator") + "gui" + System.getProperty("file.separator") + "anwendungssicht" + System.getProperty("file.separator"); if (!(new java.io.File(pfad)).exists()) if (!(new java.io.File(pfad)).mkdirs()) Main.debug.println("ERROR (" + this.hashCode() + ") " + getClass() + "\n\t" + pfad + " konnte nicht erzeugt werden"); pfad = getAnwendungenPfad() + "EigeneAnwendungen.txt"; if (!(new java.io.File(pfad)).exists()) (new java.io.File(getAnwendungenPfad() + "EigeneAnwendungen.txt")) .createNewFile(); } /** * Methode zum lesen der Verfuegbaren Programme aus den * Konfigurationsdateien. * * @return * @throws IOException */ public LinkedList<HashMap<String, String>> ladeProgrammListe() throws IOException { LinkedList<HashMap<String, String>> tmpList; RandomAccessFile desktopFile; tmpList = new LinkedList<HashMap<String, String>>(); desktopFile = new RandomAccessFile(holeAnwendungenDateipfad(), "r"); for (String line; (line = desktopFile.readLine()) != null;) { if (!line.trim().startsWith("#") && !line.trim().equals("")) { HashMap<String, String> tmpMap = new HashMap<String, String>(); StringTokenizer st = new StringTokenizer(line, ";"); tmpMap.put("Anwendung", st.nextToken()); tmpMap.put("Klasse", st.nextToken()); tmpMap.put("GUI-Klasse", st.nextToken()); tmpMap.put("gfxFile", st.nextToken()); tmpList.add(tmpMap); } } desktopFile.close(); tmpList.addAll(ladePersoenlicheProgrammListe()); return tmpList; } public LinkedList<HashMap<String, String>> ladePersoenlicheProgrammListe() throws IOException { LinkedList<HashMap<String, String>> tmpList; RandomAccessFile desktopFile = null; tmpList = new LinkedList<HashMap<String, String>>(); try { desktopFile = new RandomAccessFile(Information.getInformation() .getAnwendungenPfad() + "EigeneAnwendungen.txt", "r"); for (String line; (line = desktopFile.readLine()) != null;) { HashMap<String, String> tmpMap = new HashMap<String, String>(); if (!line.trim().equals("")) { StringTokenizer st = new StringTokenizer(line, ";"); tmpMap.put("Anwendung", st.nextToken()); tmpMap.put("Klasse", st.nextToken()); tmpMap.put("GUI-Klasse", st.nextToken()); tmpMap.put("gfxFile", st.nextToken()); tmpList.add(tmpMap); } } } catch (FileNotFoundException e) { } finally { if (desktopFile != null) desktopFile.close(); } return tmpList; } private String holeAnwendungenDateipfad() { StringBuffer pfad = new StringBuffer(); String fs = System.getProperty("file.separator"); File tmpFile; pfad.append(getProgrammPfad()); pfad.append("config" + fs + "anwendungen" + fs + "Desktop"); tmpFile = new File(pfad.toString() + "_" + locale.toString() + ".txt"); if (tmpFile.exists()) { return tmpFile.getAbsolutePath(); } else { return pfad.toString() + ".txt"; } } /** * Pfad zum Verzeichnis, in dem das Programm ausgefuehrt wird (in dem sich * die ausfuehrbare Jar-Datei befindet); <br /> * der Pfad schliesst mit dem Pfad-Trennzeichen (unter UNIX "/") */ public String getProgrammPfad() { if (programmPfad != null) { return programmPfad; } else { String str = System.getProperty("java.class.path"); programmPfad = System.getProperty("user.dir") + System.getProperty("file.separator"); if (str.indexOf("filius.jar") >= 0) { // run from jar file if ((new File(str)).isAbsolute()) programmPfad = ""; // in case of absolute path, delete // "user.dir" entry // da Java beim Aufruf verschiedene Separatoren unterstützt, // wird hier getrennt abgefragt... if (str.indexOf("/") >= 0) { programmPfad += str.substring(0, str.lastIndexOf("/")) + System.getProperty("file.separator"); } else if (str.indexOf("\\") >= 0) { programmPfad += str.substring(0, str.lastIndexOf("\\")) + System.getProperty("file.separator"); } } return programmPfad; } } public String getRelativePathToProgramDir() { String workPath = System.getProperty("user.dir") + File.separator; String progPath = getProgrammPfad(); // Windows system (with drive letters!): if (File.separator.equals("\\")) { if (progPath.substring(1, 3).equals(workPath.substring(1, 3))) { // directories // on // same // drive // --> // remove // drive // letter progPath = progPath.substring(2); workPath = workPath.substring(2); } else { // different drives; --> return absolute path return progPath; } } // ///// // remove first File.separator (first character) progPath = progPath.substring(1); workPath = workPath.substring(1); String relativePath = ""; int slashIdx = -1; boolean finished = false; // if workPath is completely part of progPath and at beginning of it: if (progPath.indexOf(workPath) == 0) { if (progPath.length() <= workPath.length()) progPath = ""; else progPath = progPath.substring(workPath.length()); workPath = ""; } else if (workPath.indexOf(progPath) == 0) { // otherway round if (workPath.length() <= progPath.length()) workPath = ""; else workPath = workPath.substring(progPath.length()); progPath = ""; } // further processing while (!finished) { slashIdx = workPath.indexOf(File.separator); if (slashIdx >= 0) { // subdirectories left to be stepped up via // "../" strings relativePath += ".." + File.separator; if (workPath.length() <= slashIdx + 2) workPath = ""; else workPath = workPath.substring(slashIdx + 1); } else { // only append remaining path to step down (again) finished = true; relativePath += progPath; return relativePath; } } return null; } /** Arbeitsbereich: Verzeichnis, in dem alle benutzerspezifischen */ public String getArbeitsbereichPfad() { return arbeitsbereichPfad; } public void setArbeitsbereichPfad(String otherWD) { StringTokenizer tokenizer = null; String token = null; if (otherWD.indexOf("/") >= 0) { tokenizer = new StringTokenizer(otherWD, "/"); } else if (otherWD.indexOf("\\\\") >= 0) { tokenizer = new StringTokenizer(otherWD, "\\\\"); } if (otherWD.startsWith("/") || otherWD.startsWith("\\\\")) { arbeitsbereichPfad = System.getProperty("file.separator"); } else arbeitsbereichPfad = ""; if (tokenizer != null) { while (tokenizer.hasMoreTokens()) { token = tokenizer.nextToken().trim(); if (!token.isEmpty()) arbeitsbereichPfad += token + System.getProperty("file.separator"); } } else arbeitsbereichPfad = otherWD + System.getProperty("file.separator"); // no // separators, // but // possibly // still // legitimate // String arbeitsbereichPfad += ".filius" + System.getProperty("file.separator"); } /** * Temp: Verzeichnis, in dem zur Laufzeit temporaere Dateien gespeichert * werden */ public String getTempPfad() { return getArbeitsbereichPfad() + "temp" + System.getProperty("file.separator"); } /** * Anwendungen: Verzeichnis, in dem die eigenen Anwendungen gespeichert * werden mit den Unterordnern software/clientserver/ und * gui/anwendungssicht/ */ public String getAnwendungenPfad() { return getArbeitsbereichPfad() + "anwendungen" + System.getProperty("file.separator"); } /** * Automatische Erzeugung einer MAC-Adresse, funktioniert mit * Hexadezimal-Zahlen */ public String holeFreieMACAdresse() { Random r = new Random(); String[] mac; String neueMac; mac = new String[6]; for (int i = 0; i < mac.length; i++) { mac[i] = Integer.toHexString(r.nextInt(255)); if (mac[i].length() == 1) mac[i] = "0" + mac[i]; } neueMac = mac[0] + ":" + mac[1] + ":" + mac[2] + ":" + mac[3] + ":" + mac[4] + ":" + mac[5]; if (macPruefen(neueMac)) { return neueMac; } else { return holeFreieMACAdresse(); } } /** Eintragen einer verwendeten MAC-Adresse */ public void macHinzufuegen(String mac) { macAdressen.addElement(mac); } /** Pruefen, ob es sich um eine verfuegbare, gueltige MAC-Adresse handelt. */ private boolean macPruefen(String mac) { boolean macOK = true; for (int i = 0; i < macAdressen.size(); i++) { if (mac.equals((String) macAdressen.elementAt(i))) macOK = false; } if (mac.equalsIgnoreCase("ff:ff:ff:ff:ff:ff")) { macOK = false; } return macOK; } public int getMaxVermittlungsStellen() { return maxVermittlungsStellen; } public void setMaxVermittlungsStellen(int maxVermittlungsStellen) { this.maxVermittlungsStellen = maxVermittlungsStellen; } }