package org.openslx.dozmod;
import java.awt.AWTEvent;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.AWTEventListener;
import java.awt.event.ComponentEvent;
import java.awt.event.ContainerEvent;
import java.io.File;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.net.ssl.SSLContext;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import org.apache.log4j.AppenderSkeleton;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.spi.LoggingEvent;
import org.openslx.dozmod.gui.Gui;
import org.openslx.dozmod.gui.MainWindow;
import org.openslx.dozmod.gui.helper.MessageType;
import org.openslx.dozmod.util.ProxyConfigurator;
import org.openslx.thrifthelper.ThriftManager;
import org.openslx.util.Util;
public class App {
// Logger
private final static Logger LOGGER = Logger.getLogger(App.class);
public static final int THRIFT_PORT = 9090;
public static final int THRIFT_SSL_PORT = THRIFT_PORT + 1;
public static final int THRIFT_TIMEOUT_MS = 15000;
private static Thread proxyThread = null;
private static void setupLogger() {
// path to the log file
final String logFilePath = Config.getPath() + File.separator + "bwSuite.log";
// check if we had an old log file
final File logFile = new File(logFilePath);
if (logFile.exists() && !logFile.isDirectory()) {
// we have one, rename it to 'bwSuite.log.old'
LOGGER.info("renaming old log file");
try {
File oldFile = new File(logFilePath + ".old");
oldFile.delete();
logFile.renameTo(oldFile);
logFile.delete();
} catch (Exception e) {
LOGGER.error("Could not move '" + logFilePath + "' to '" + logFilePath + ".old'", e);
}
}
// add file appender to global logger
FileAppender fa = null;
try {
fa = new FileAppender(new PatternLayout("%d [%F:%M] %m%n"), logFilePath);
// All classes should log to file, configure global file appender.
} catch (IOException e) {
e.printStackTrace();
BasicConfigurator.configure();
return;
}
final FileAppender ffa = fa;
final Pattern re = Pattern.compile("authorization:(\\w|\\+|/|\\s)+", Pattern.CASE_INSENSITIVE
| Pattern.MULTILINE);
AppenderSkeleton ap = new AppenderSkeleton() {
@Override
public boolean requiresLayout() {
return ffa.requiresLayout();
}
@Override
public void close() {
ffa.close();
}
@Override
protected void append(LoggingEvent event) {
String s = event.getRenderedMessage();
if (s.contains("uthorization")) {
Matcher m = re.matcher(s);
if (m.find()) {
s = m.replaceAll("Authorization: ***********");
}
}
ffa.append(new LoggingEvent(event.getFQNOfLoggerClass(), event.getLogger(),
event.getTimeStamp(), event.getLevel(), s, event.getThreadName(),
event.getThrowableInformation(), event.getNDC(), event.getLocationInformation(),
event.getProperties()));
}
};
BasicConfigurator.configure(ap);
LOGGER.info("Starting logging to: " + logFilePath);
}
public static void main(final String[] args) {
try {
Config.init();
} catch (Exception e) {
Gui.showMessageBox(null, "Error loading configuration", MessageType.ERROR, LOGGER, e);
return;
}
setupLogger();
// Initialize the proxy settings
proxyThread = new Thread() {
@Override
public void run() {
ProxyConfigurator.init();
}
};
proxyThread.start();
// Setup swing style
System.setProperty("awt.useSystemAAFontSettings", "on");
System.setProperty("swing.aatext", "true");
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
} catch (Exception e1) {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
}
}
// Adjust font size
if (System.getProperty("bigfont") != null) {
adjustFontSize();
}
// setup global thrift connection error handler before anything else
// Set master server to use (TODO: make configurable via command line)
try {
ThriftManager.setMasterServerAddress(SSLContext.getDefault(),
"bwlp-masterserver.ruf.uni-freiburg.de", THRIFT_SSL_PORT, THRIFT_TIMEOUT_MS);
} catch (final NoSuchAlgorithmException e1) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Gui.showMessageBox(null, "SSL nicht verfügbar", MessageType.ERROR, LOGGER, e1);
// TODO: Ask if user wants to establish plain connection, quit otherwise
System.exit(1);
}
});
return;
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
@Override
public void uncaughtException(Thread t, Throwable e) {
Gui.showMessageBox(
null,
"Ungefangene Ausnahme in Faden "
+ t.getName()
+ "\n"
+ "Die Anwendung könnte instabil laufen. Zur Sicherheit sollten Sie sie neustarten.",
MessageType.WARNING, LOGGER, e);
}
});
MainWindow.open();
}
});
Util.sleep(1000);
}
private static void adjustFontSize() {
int size = determineDefaultFontSize(UIManager.getLookAndFeelDefaults());
if (size == -1) {
size = determineDefaultFontSize(UIManager.getDefaults());
}
if (size == -1) {
size = 12;
}
final int defaultSize = size;
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
@Override
public void eventDispatched(AWTEvent event) {
if (event instanceof ContainerEvent && event instanceof ComponentEvent) {
ContainerEvent containerEvent = (ContainerEvent) event;
if (containerEvent.getID() == ContainerEvent.COMPONENT_ADDED) {
Font font = containerEvent.getChild().getFont();
if (font != null && font.getSize() <= defaultSize) {
containerEvent.getChild().setFont(
new Font(font.getName(), font.getStyle(), font.getSize() * 2));
}
}
}
}
}, AWTEvent.COMPONENT_EVENT_MASK | AWTEvent.CONTAINER_EVENT_MASK);
}
private static int determineDefaultFontSize(UIDefaults defaults) {
if (defaults == null)
return -1;
int sizes[] = new int[100];
Set<Object> keys = new HashSet<>(defaults.keySet());
for (Object key : keys) {
if (key == null)
continue;
Object value = defaults.get(key);
if (value == null)
continue;
if (value instanceof Font) {
Font font = (Font) value;
if (font.getSize() > 0 && font.getSize() < sizes.length) {
sizes[font.getSize()]++;
}
}
}
int best = -1;
for (int index = 0; index < sizes.length; ++index) {
if (best == -1 || sizes[best] < sizes[index]) {
best = index;
}
}
return sizes[best];
}
/**
* Blocks as long as initialization is still going on. Currently this is
* just the proxy setup, so this should be used before any network
* communication happens.
*/
public static synchronized void waitForInit() {
if (proxyThread == null)
return;
try {
proxyThread.join();
} catch (InterruptedException e) {
}
proxyThread = null;
}
}