001package org.intellimate.izou.system;
002
003import org.intellimate.izou.main.Main;
004import org.intellimate.izou.system.file.ReloadableFile;
005import org.intellimate.izou.util.IzouModule;
006
007import java.io.*;
008import java.net.InetAddress;
009import java.net.UnknownHostException;
010import java.util.Enumeration;
011import java.util.Properties;
012
013/**
014 * The SystemInitializer does any system wide initialization before Izou is started. An example of this would be setting
015 * system properties relevant to izou etc.
016 */
017public class SystemInitializer extends IzouModule implements ReloadableFile {
018    /**
019     * The name of the Izou properties file
020     */
021    public static final String IZOU_PROPERTIES_FILE_NAME = "izou.properties";
022
023    private static final String IZOU_CONFIGURED = "izou.configured";
024
025    private Properties properties;
026    private File propertiesFile;
027
028    /**
029     * Creates a new SystemInitializer object
030     */
031    public SystemInitializer(Main main) {
032        super(main);
033        properties = new Properties();
034    }
035
036    /**
037     * Initializes the system by calling all init methods
038     */
039    public void initSystem() {
040        createIzouPropertiesFile();
041        setSystemProperties();
042        reloadFile(null);
043
044        try {
045            if (System.getProperty(IZOU_CONFIGURED).equals("false")) {
046                fatal("Izou not completely configured, please configure Izou and launch again.");
047                System.exit(0);
048            }
049        } catch (NullPointerException e) {
050            fatal("Izou not completely configured, please configure Izou by editing izou.properties in the " +
051                    "properties folder and launch again.");
052            System.exit(0);
053        }
054    }
055
056    /**
057     * This method registers the SystemInitializer with the Properties manager, but this can only be done once the
058     * properties manager has been created, thus this method is called later.
059     */
060    public void registerWithPropertiesManager() {
061        try {
062            main.getFileManager().registerFileDir(propertiesFile.getParentFile().toPath(),
063                    propertiesFile.getName(), this);
064        } catch (IOException e) {
065            error("Unable to register ");
066        }
067    }
068
069    /**
070     * Creates the propreties file for Izou. This is the file that has to be configured before Izou can run and it
071     * contains some basic configuartion for Izou.
072     */
073    private void createIzouPropertiesFile() {
074        String propertiesPath = getMain().getFileSystemManager().getPropertiesLocation() + File.separator
075                + IZOU_PROPERTIES_FILE_NAME;
076
077        propertiesFile = new File(propertiesPath);
078        if (!propertiesFile.exists()) try {
079            propertiesFile.createNewFile();
080
081            PrintWriter writer = new PrintWriter(propertiesFile.getAbsolutePath(), "UTF-8");
082            writer.println("# --------------------");
083            writer.println("# Izou Properties File");
084            writer.println("# --------------------");
085            writer.println("#");
086            writer.println("# This file has some general configuration options that have to be configured before");
087            writer.println("# Izou can run successfully. For example, you should give the device Izou is running on");
088            writer.println("# a static IP and enter it here.");
089            writer.println("#");
090            writer.println("#");
091            writer.println("# Enter the IP address of the device Izou is running on below, and make sure it is static");
092            writer.println("# (does not change).");
093            writer.println("ip-address = ");
094            writer.close();
095        } catch (IOException e) {
096            error("Error while trying to create the new Properties file", e);
097        }
098    }
099
100    /**
101     * Sets all system properties relevant for Izou
102     */
103    private void setSystemProperties() {
104        setLocalHostProperty();
105    }
106
107    /**
108     * Gets the local host if it can, and sets it as a system property
109     */
110    private void setLocalHostProperty() {
111        String hostName = "unkown";
112        try {
113            hostName = InetAddress.getLocalHost().getHostName();
114        } catch (UnknownHostException e) {
115            error("Unable to resolve hostname, setting hostname as 'unkown'");
116        }
117
118        System.setProperty("host.name", hostName);
119    }
120
121    /**
122     * Reload the properties from the properties file into the system properties
123     */
124    private void reloadProperties() {
125        Properties temp = new Properties();
126        BufferedReader bufferedReader = null;
127        try {
128            bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(propertiesFile), "UTF8"));
129            temp.load(bufferedReader);
130            this.properties = temp;
131        } catch (IOException e) {
132            error("Error while trying to load the Properties-File: "
133                    + propertiesFile.getAbsolutePath(), e);
134        } finally {
135            if (bufferedReader != null) {
136                try {
137                    bufferedReader.close();
138                } catch (IOException e) {
139                    error("Unable to close input stream", e);
140                }
141            }
142        }
143    }
144
145    @Override
146    public void reloadFile(String eventType) {
147        Enumeration propertyNames = properties.propertyNames();
148        while (propertyNames.hasMoreElements()) {
149            String key = (String) propertyNames.nextElement();
150            String value = properties.getProperty(key);
151
152            System.getProperties().remove(value);
153        }
154
155        reloadProperties();
156        propertyNames = properties.propertyNames();
157
158        boolean configured = false;
159
160        while (propertyNames.hasMoreElements()) {
161            String key = (String) propertyNames.nextElement();
162            String value = properties.getProperty(key);
163
164            if (key.equals(IZOU_CONFIGURED)) {
165                continue;
166            }
167
168            if (!value.equals("")) {
169                configured = true;
170            }
171
172            System.setProperty(key, value);
173        }
174
175        if (configured) {
176            System.setProperty(IZOU_CONFIGURED, "true");
177        } else {
178            System.setProperty(IZOU_CONFIGURED, "false");
179        }
180    }
181}