package marubinotto.piggydb.standalone;
import java.awt.AWTException;
import java.awt.Desktop;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SplashScreen;
import java.awt.SystemTray;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ResourceBundle;
import javax.imageio.ImageIO;
import javax.swing.JOptionPane;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.webapp.WebAppContext;
public class PiggydbServer {
private static Log logger = LogFactory.getLog(PiggydbServer.class);
static final String SERVER_NAME = "Piggydb";
static final String URL_PREFIX = "http://localhost";
static ResourceBundle messages;
static PiggydbSplashScreen splashScreen = PiggydbSplashScreen.NULL;
static Settings settings;
static Server server;
static WebAppContext webapp;
static TrayIcon trayIcon;
public static void main(String[] args) {
try {
launch();
}
catch (Throwable e) {
splashScreen.close();
JOptionPane.showMessageDialog(
null,
getSystemErrorMessage(),
SERVER_NAME + " Error",
JOptionPane.ERROR_MESSAGE);
logger.error(e.toString(), e);
System.exit(1);
}
}
static final String DEFAULT_ERRMSG =
"An unexpected error occurred. Check the log file for the error.";
static String getSystemErrorMessage() {
if (messages == null) return DEFAULT_ERRMSG;
return messages.getString("system-error");
}
static void launch() throws Throwable {
messages = ResourceBundle.getBundle("messages");
initSplashScreen();
splashScreen.message("Loading " + Settings.FILE_NAME + " ...");
loadSettings();
splashScreen.message("Initializing the server ...");
initServer();
splashScreen.message("Starting the server ...");
server.start();
logger.debug("The server has been started.");
ensureWebappAvailable();
setupTrayIcon();
if (settings.isLaunchBrowserWhenStartup()) {
splashScreen.message("Opening the home page ...");
launchBrowser();
}
splashScreen.close();
splashScreen = null;
server.join();
}
static void initSplashScreen() throws Exception {
String version = null;
InputStream input = PiggydbServer.class.getResourceAsStream("VERSION");
try {
version = IOUtils.toString(input);
}
finally {
input.close();
}
SplashScreen s = SplashScreen.getSplashScreen();
if (s != null) splashScreen = new PiggydbSplashScreen(s, version);
}
static void loadSettings() throws Exception {
File baseDir = new File(System.getProperty("user.dir"));
logger.info("baseDir: " + baseDir.getAbsolutePath());
settings = new Settings(baseDir);
}
static final String WEBAPP_DIR = "webapp";
static final String APP_SETTINGS_FILE_NAME = "application.properties";
static final String APP_SETTINGS_FILE_PATH = WEBAPP_DIR + "/WEB-INF/config/" + APP_SETTINGS_FILE_NAME;
static void initServer() throws IOException {
server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
connector.setPort(settings.getPort());
server.addConnector(connector);
File resourceBase = settings.getResourcePath(WEBAPP_DIR);
File descriptor = settings.getResourcePath(WEBAPP_DIR + "/WEB-INF/web.xml");
if (!resourceBase.isDirectory()) throw new FileNotFoundException(resourceBase.getAbsolutePath());
if (!descriptor.isFile()) throw new FileNotFoundException(descriptor.getAbsolutePath());
// Apply application.properties
File appSettingsSrc = settings.getResourcePath(APP_SETTINGS_FILE_NAME);
if (appSettingsSrc.isFile()) {
File appSettingsDest = settings.getResourcePath(APP_SETTINGS_FILE_PATH);
FileUtils.copyFile(appSettingsSrc, appSettingsDest);
}
webapp = new WebAppContext();
webapp.setContextPath("/");
webapp.setResourceBase(resourceBase.getAbsolutePath());
webapp.setDescriptor(descriptor.getAbsolutePath());
webapp.setParentLoaderPriority(true);
server.setHandler(webapp);
}
static void ensureWebappAvailable() throws Throwable {
// Check the context
Throwable webappError = webapp.getUnavailableException();
if (logger.isInfoEnabled()) {
logger.info("Server started {");
logger.info(" isAvailable: " + webapp.isAvailable());
logger.info(" getUnavailableException: " + webappError);
logger.info("}");
}
if (webappError != null) throw webappError;
// Check the servlets
for (ServletHolder holder : webapp.getServletHandler().getServlets()) {
// force to fill the UnavailableException when the servlet class is not found
boolean servletAvailable = holder.isAvailable();
Throwable servletError = holder.getUnavailableException();
if (logger.isInfoEnabled()) {
logger.info("Servlet: [" + holder.getName() + "] {");
logger.info(" isAvailable: " + servletAvailable);
logger.info(" getUnavailableException: " + servletError);
logger.info("}");
}
if (servletError != null) throw servletError;
}
}
static void setupTrayIcon() throws IOException, AWTException {
logger.debug("Loading the tray icon ...");
trayIcon = new TrayIcon(
ImageIO.read(PiggydbServer.class.getResourceAsStream("tray-icon.png")),
SERVER_NAME);
// trayIcon.setImageAutoSize(true);
PopupMenu menu = new PopupMenu();
menu.add(createMenuItem(messages.getString("home"), new ActionListener() {
public void actionPerformed(ActionEvent event) {
try {
launchBrowser();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
}));
menu.add(createMenuItem(messages.getString("info"), new ActionListener() {
public void actionPerformed(ActionEvent event) {
trayIcon.displayMessage(
SERVER_NAME,
"Piggydb server is running on port " + settings.getPort(),
TrayIcon.MessageType.INFO);
}
}));
menu.add(createMenuItem(messages.getString("shutdown"), new ActionListener() {
public void actionPerformed(ActionEvent event) {
try {
server.stop();
}
catch (Exception e) {
throw new RuntimeException(e);
}
System.exit(0);
}
}));
trayIcon.setPopupMenu(menu);
logger.debug("Adding the icon to the system tray ...");
SystemTray.getSystemTray().add(trayIcon);
logger.debug("Done setupTrayIcon()");
}
static MenuItem createMenuItem(String label, ActionListener listener) {
MenuItem item = new MenuItem(label);
item.addActionListener(listener);
return item;
}
static void launchBrowser() throws IOException, URISyntaxException {
String url = URL_PREFIX;
if (settings.getPort() != 80) url = url + ":" + settings.getPort();
Desktop.getDesktop().browse(new URI(url));
}
}