package hu.ppke.itk.itkStock.server;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.PrintWriter;
import org.jdom2.Attribute;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.Namespace;
import org.jdom2.input.SAXBuilder;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
/**
* A settings singleton for the server.<br>
* If any setting changes, the settings file will be reparsed entirely.
*
*/
public enum ServerSettings {
INSTANCE;
private int dbPort;
private String dbHost;
private String dbName;
private String dbUser;
private String dbPass;
/**
* Consturctor<br>
* Invokes load method to get the settings from the 'ServerConfig.xml' file<br>
* If file not present, generates default values to default 'ServerConfig.xml' file
*/
private ServerSettings()
{
load();
}
/**
* This method loads the configuration file, if not present, generates one with default values.
*/
private void load()
{
try {
parseFile("ServerConfig.xml");
} catch (JDOMException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
System.err.println("File not found!\nGenerating default values to \'ServerConfig.xml\'");
generateDefualt();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* This method parses XML config file with given nodes. Only the given nodes will be parsed, <br>
* they have to be in a specific order defined in the XML Scheme. Although it does not matter for <br>
* the parser.<br>
*
* @param filename The name of the file to be parsed
* @throws JDOMException
* @throws IOException
*/
private void parseFile(String filename) throws JDOMException, IOException
{
SAXBuilder builder = new SAXBuilder(/*XMLReaders.XSDVALIDATING*/);
Document doc = builder.build(filename);
Element root = doc.getRootElement();
dbPort = xmlGetPort(root);
dbHost = xmlGetDbHost(root);
dbName = xmlGetDbName(root);
dbUser = xmlGetDbUser(root);
dbPass = xmlGetDbPass(root);
}
/**
* This method generates the default values for each option.<br>
* The default values will be parsed to an XML file, and reopened for reloading configuration.
*/
private void generateDefualt()
{
System.out.println("Generating default values...");
Element root = makeRoot();
//TODO generate default values to config file
root.addContent(new Element("connection")
.addContent(new Element("port").setText("3306")));
root.addContent(new Element("db")
.addContent(new Element("dbHost").setText("localhost"))
.addContent(new Element("dbName").setText("itkStock"))
.addContent(new Element("dbUser").setText("itkStock"))
.addContent(new Element("dbPass").setText("itkStock"))
);
makeFile(root);
System.out.println("Default configuration generated. Reloading...");
try {
parseFile("ServerConfig.xml");
} catch (JDOMException | IOException e) {
e.printStackTrace();
}
}
/**
* Makes a new configuration file. This method invokes when change has been made to any of the data
*/
private void reparseConfig()
{
//TODO remove this, following line debug only
System.out.println("reparsing configuration file...");
Element root = makeRoot();
root.addContent(new Element("connection")
.addContent(new Element("port").setText(Integer.toString(dbPort))));
root.addContent(new Element("db")
.addContent(new Element("dbHost").setText(dbHost))
.addContent(new Element("dbName").setText(dbName))
.addContent(new Element("dbUser").setText(dbUser))
.addContent(new Element("dbPass").setText(dbPass))
);
makeFile(root);
}
/**
* Makes the default root element for the configuration. This adds the namespace and the XML-Scheme as well.
* @return The root configuration element
*/
private Element makeRoot()
{
Element root = new Element("server_config", "xsi", "http://www.w3.org/2001/XMLSchema-instance");
root.setAttribute(new Attribute("noNamespaceSchemaLocation",
"ServerConfig.xsd", Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance")));
return root;
}
/**
* Makes the configuration XML file from root element
* @param root The root element of the document
*/
private void makeFile(Element root)
{
Document doc = new Document();
doc.addContent(root);
XMLOutputter out = new XMLOutputter(Format.getPrettyFormat());
try {
File f = new File("ServerConfig.xml");
PrintWriter pw = new PrintWriter(f);
out.output(doc, pw);
out.output(doc, System.out); //TODO debug only line
} catch (IOException e1) {
e1.printStackTrace();
}
}
//xml data-getter methods
private int xmlGetPort(Element root)
{
return Integer.parseInt(root.getChild("connection")
.getChild("port").getText());
}
private String xmlGetDbHost(Element root)
{
return root.getChild("db").getChildText("dbHost");
}
private String xmlGetDbName(Element root)
{
return root.getChild("db").getChildText("dbName");
}
private String xmlGetDbUser(Element root)
{
return root.getChild("db").getChildText("dbUser");
}
private String xmlGetDbPass(Element root)
{
return root.getChild("db").getChildText("dbPass");
}
//setter methods
public void setPort(int dbPort) {
this.dbPort = dbPort;
reparseConfig();
}
public void setDbHost(String dbHost) {
this.dbHost = dbHost;
reparseConfig();
}
public void setDbName(String dbName) {
this.dbName = dbName;
reparseConfig();
}
public void setDbUser(String dbUser) {
this.dbUser = dbUser;
reparseConfig();
}
public void setDbPass(String dbPass) {
this.dbPass = dbPass;
reparseConfig();
}
//getter methods
public String getDbUrl () {
return "jdbc:mysql://" + dbHost + ":" + dbPort + "/" + dbName;
}
public int getPort() {
return dbPort;
}
public String getDbHost() {
return dbHost;
}
public String getDbName() {
return dbName;
}
public String getDbUser() {
return dbUser;
}
public String getDbPass() {
return dbPass;
}
//toString method, debug purpose only
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("==ServerConfig==\n");
sb.append("port: ").append(Integer.toString(dbPort));
sb.append("\ndbHost: ").append(dbHost);
sb.append(", dbName: ").append(dbName);
sb.append("\ndbUser: ").append(dbUser);
sb.append(", dbPass: ").append(dbPass);
sb.append("\n").append(getDbUrl());
sb.append("\n================");
return sb.toString();
}
}