/*
* Main.java
*
* Created on March 26, 2007, 2:47 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
package org.atomojo.app;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.text.DateFormat;
import java.util.Date;
import java.util.Map;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import org.atomojo.app.db.ConfigurationException;
import org.atomojo.app.db.DB;
import org.infoset.xml.XMLException;
import org.infoset.xml.util.WriterItemDestination;
/**
*
* @author alex
*/
public class Main implements Runnable {
static String fineLog =
"handlers= java.util.logging.ConsoleHandler\n"+
".level= FINE\n"+
"java.util.logging.ConsoleHandler.level = FINE\n"+
"java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter\n";
;
static String finerLog =
"handlers= java.util.logging.ConsoleHandler\n"+
".level= FINER\n"+
"java.util.logging.ConsoleHandler.level = FINER\n"+
"java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter\n";
;
static String finestLog =
"handlers= java.util.logging.ConsoleHandler\n"+
".level= FINEST\n"+
"java.util.logging.ConsoleHandler.level = FINEST\n"+
"java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter\n";
;
static String defaultStorageClass = "org.atomojo.app.storage.file.FileStorageFactory";
static {
String value = System.getProperty("org.atomojo.app.storage.class");
if (value!=null) {
defaultStorageClass = value;
}
}
boolean create;
File dir;
String [] args;
Map<String,DB> dbList;
WebComponent web;
ServerConfiguration conf;
Level logLevel;
Logger log;
int argIndex;
String storageClassName = null;
class DebugHandler extends Handler {
public void publish(LogRecord record) {
if (record.getLevel().intValue()<=Level.FINE.intValue()) {
DateFormat format = DateFormat.getDateTimeInstance();
String dateTime = format.format(new Date(record.getMillis()));
System.err.println(dateTime+" "+record.getSourceClassName()+" "+record.getSourceMethodName());
System.err.println(record.getLevel()+": "+record.getMessage());
}
}
public void flush() {
}
public void close() {
}
}
/** Creates a new instance of Main */
public Main(String [] args) {
this.argIndex = 0;
this.logLevel = Level.INFO;
while (argIndex<args.length && args[argIndex].charAt(0)=='-') {
String name = args[argIndex].substring(1);
argIndex++;
if (argIndex==args.length) {
throw new RuntimeException("The argument "+args[argIndex]+" requires an argument.");
}
if (name.equals("l") || name.equals("-level")) {
if (args[argIndex].equals("info")) {
logLevel = Level.INFO;
} else if (args[argIndex].equals("fine")) {
logLevel = Level.FINE;
} else if (args[argIndex].equals("finer")) {
logLevel = Level.FINER;
} else if (args[argIndex].equals("finest")) {
logLevel = Level.FINEST;
} else if (args[argIndex].equals("config")) {
logLevel = Level.CONFIG;
}
} else if (name.equals("c") || name.equals("-class")) {
storageClassName = args[argIndex];
}
argIndex++;
}
int argCount = args.length-argIndex;
if (argCount!=1 && argCount!=4) {
throw new RuntimeException("The number of arguments is wrong.");
}
this.dir = new File(args[argIndex]);
if (!dir.exists()) {
throw new RuntimeException("The directory "+dir.getAbsolutePath()+" does not exist.");
}
if (!dir.canWrite()) {
throw new RuntimeException("Cannot write to the directory "+dir.getAbsolutePath());
}
this.args = args;
this.dbList = null;
this.conf = null;
this.web = null;
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
if (args.length<1) {
System.err.println("atomapp {options} dir { hostname ipaddress port }");
System.exit(1);
}
try {
Main main = new Main(args);
try {
main.init();
main.run();
} catch (Exception ex) {
ex.printStackTrace();
}
} catch (RuntimeException ex) {
System.err.println(ex.getMessage());
}
}
StorageFactory getStorageFactory()
throws Exception
{
final Class<StorageFactory> storageClass = (Class<StorageFactory>)this.getClass().forName(storageClassName);
return storageClass.newInstance();
}
public void init()
throws ConfigurationException,IOException,XMLException
{
System.out.println("Configuring...");
System.out.println("Setting log level to "+logLevel);
log = Logger.getLogger(WebComponent.LOG_NAME);
log.setLevel(logLevel);
log = Logger.getLogger("org.atomojo");
log.setLevel(logLevel);
log.addHandler(new DebugHandler());
if (logLevel==Level.FINE) {
try {
LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(fineLog.getBytes()));
} catch (java.io.IOException ex) {
ex.printStackTrace();
}
} else if (logLevel==Level.FINER) {
try {
LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(finerLog.getBytes()));
} catch (java.io.IOException ex) {
ex.printStackTrace();
}
} else if (logLevel==Level.FINEST) {
try {
LogManager.getLogManager().readConfiguration(new ByteArrayInputStream(finestLog.getBytes()));
} catch (java.io.IOException ex) {
ex.printStackTrace();
}
}
dbList = DB.getDatabases(log,dir);
conf = new ServerConfiguration();
File serverConfFile = new File(dir,"server.conf");
if (serverConfFile.exists()) {
create = false;
conf.setLogDirectory(new File(dir,"logs"));
conf.load(serverConfFile.toURI());
initStorageClass();
try {
web = new WebComponent(dir,dbList,getStorageFactory(),conf);
} catch (Exception ex) {
throw new ConfigurationException("Cannot load storage "+storageClassName,ex);
}
} else {
create = true;
}
}
protected void initStorageClass() {
if (storageClassName==null) {
storageClassName = conf.getStorageClassName();
}
if (storageClassName==null) {
storageClassName = defaultStorageClass;
}
log.info("Using storage class "+storageClassName);
}
public void run() {
try {
if (create) {
if (dbList.isEmpty()) {
Logger log = Logger.getLogger(WebComponent.LOG_NAME);
DB db = DB.createDB(log,dir,"data");
dbList.put(db.getName(),db);
try {
DB.writeList(dir,dbList);
} catch (Exception ex) {
ex.printStackTrace();
return;
}
}
int argCount = args.length-argIndex;
String hostname = argCount>1 ? args[argIndex+1] : "*";
String ipAddress = argCount>1 ? args[argIndex+2] : "*";
int port = argCount>1 ? Integer.parseInt(args[argIndex+3]) : 8080;
File logDir = new File(dir,"logs");
ServerConfiguration.Host host = new ServerConfiguration.Host(conf,"data",hostname,null,port,false,false,new File(logDir,hostname.equals("*") ? "any.log" : hostname+".log"));
conf.getInterfaces().add(new ServerConfiguration.Interface(ipAddress,port,true));
conf.getHosts().put(host.getName(),host);
File keystoreFile = new File(dir,"keystore");
conf.setKeystoreFile(keystoreFile);
conf.setKeystorePassword("atomojo");
conf.setKeyPassword("atomojo");
conf.setLogDirectory(logDir);
conf.setTempDirectory(dir);
if (storageClassName!=null) {
conf.setStorageClassName(storageClassName);
}
File serverConfFile = new File(dir,"server.conf");
Writer out = new OutputStreamWriter(new FileOutputStream(serverConfFile),"UTF-8");
WriterItemDestination dest = new WriterItemDestination(out,"UTF-8");
conf.store(serverConfFile.toURI(),dest);
out.flush();
out.close();
if (!keystoreFile.exists()) {
copyResource("/org/atomojo/app/db/conf/keystore",keystoreFile);
}
initStorageClass();
web = new WebComponent(dir,dbList,getStorageFactory(),conf);
}
System.out.println("Connecting to databases...");
// Connect to all databases
for (DB db : dbList.values()) {
System.out.println("Connecting to DB "+db.getName());
db.connect();
}
System.out.println("Starting server...");
web.start();
System.out.println("Started.");
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void stop()
throws Exception
{
web.stop();
}
public static void copyResource(String resourcePath,File outFile)
throws IOException
{
InputStream in = Main.class.getResourceAsStream(resourcePath);
if (in==null) {
throw new IOException("Cannot open resource "+resourcePath);
}
FileOutputStream out = new FileOutputStream(outFile);
byte [] buffer = new byte[8192];
int len;
while ((len=in.read(buffer))>0) {
out.write(buffer,0,len);
}
out.close();
in.close();
}
}