summaryrefslogtreecommitdiff
path: root/src/main/java/de
diff options
context:
space:
mode:
authoryvesf <yvesf-git@xapek.org>2011-02-24 22:45:14 +0100
committeryvesf <yvesf-git@xapek.org>2011-02-24 22:45:14 +0100
commit6dc7723c738c8307369f2fcfd8feb0fd2ea703c1 (patch)
tree33faebb05fbb8793f465ef976a7d22995985e5d9 /src/main/java/de
parent962ddff447068e759b37841536a51e8973691097 (diff)
downloaddhbw-calendar-6dc7723c738c8307369f2fcfd8feb0fd2ea703c1.tar.gz
dhbw-calendar-6dc7723c738c8307369f2fcfd8feb0fd2ea703c1.zip
file-copy from previous development-repository
Diffstat (limited to 'src/main/java/de')
-rw-r--r--src/main/java/de/dhbw/horb/calendar/ICSServlet.java39
-rw-r--r--src/main/java/de/dhbw/horb/calendar/dualis/DualisConnection.java173
-rw-r--r--src/main/java/de/dhbw/horb/calendar/dualis/DualisException.java33
-rw-r--r--src/main/java/de/dhbw/horb/calendar/ics/AbstractICSType.java43
-rw-r--r--src/main/java/de/dhbw/horb/calendar/ics/VCalendar.java51
-rw-r--r--src/main/java/de/dhbw/horb/calendar/ics/VEvent.java79
-rw-r--r--src/main/java/de/dhbw/horb/calendar/ui/LoginWorker.java90
-rw-r--r--src/main/java/de/dhbw/horb/calendar/ui/MyApplication.java161
-rw-r--r--src/main/java/de/dhbw/horb/calendar/ui/StundenplanComponent.java102
-rw-r--r--src/main/java/de/dhbw/horb/calendar/util/AuthenticatedServlet.java84
10 files changed, 855 insertions, 0 deletions
diff --git a/src/main/java/de/dhbw/horb/calendar/ICSServlet.java b/src/main/java/de/dhbw/horb/calendar/ICSServlet.java
new file mode 100644
index 0000000..8a1be3e
--- /dev/null
+++ b/src/main/java/de/dhbw/horb/calendar/ICSServlet.java
@@ -0,0 +1,39 @@
+package de.dhbw.horb.calendar;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import de.dhbw.horb.calendar.dualis.DualisConnection;
+import de.dhbw.horb.calendar.dualis.DualisException;
+import de.dhbw.horb.calendar.ics.VCalendar;
+import de.dhbw.horb.calendar.ics.VEvent;
+import de.dhbw.horb.calendar.util.AuthenticatedServlet;
+
+public class ICSServlet extends AuthenticatedServlet {
+ private static final long serialVersionUID = 1L;
+
+ public ICSServlet() {
+ setLoginRealm("Dualis Calendar Connector");
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request,
+ HttpServletResponse response, String username, String password)
+ throws IOException {
+ response.setHeader("Content-Type", "text/calendar; charset=utf-8");
+
+ VCalendar calendar = new VCalendar("DHBW Calendar");
+ try {
+ DualisConnection connection = new DualisConnection(username,
+ password);
+ for (VEvent event : connection.getEvents()) {
+ calendar.add(event);
+ }
+ } catch (DualisException e) {
+ e.printStackTrace();
+ }
+ response.getOutputStream().write(calendar.serialize().getBytes());
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/dhbw/horb/calendar/dualis/DualisConnection.java b/src/main/java/de/dhbw/horb/calendar/dualis/DualisConnection.java
new file mode 100644
index 0000000..f7bf369
--- /dev/null
+++ b/src/main/java/de/dhbw/horb/calendar/dualis/DualisConnection.java
@@ -0,0 +1,173 @@
+package de.dhbw.horb.calendar.dualis;
+
+import java.io.IOException;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.gargoylesoftware.htmlunit.ElementNotFoundException;
+import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
+import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.html.DomAttr;
+import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
+import com.gargoylesoftware.htmlunit.html.HtmlElement;
+import com.gargoylesoftware.htmlunit.html.HtmlForm;
+import com.gargoylesoftware.htmlunit.html.HtmlInput;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+
+import de.dhbw.horb.calendar.dualis.DualisException.DualisAuthenticationException;
+import de.dhbw.horb.calendar.dualis.DualisException.DualisScrapingException;
+import de.dhbw.horb.calendar.ics.VEvent;
+
+public class DualisConnection {
+ public static final String DUALIS_URL = "https://dualis.dhbw.de/scripts/mgrqcgi?APPNAME=CampusNet&PRGNAME=EXTERNALPAGES&ARGUMENTS=-N000000000000001,-N,-Awelcome";
+
+ private final String username;
+ private final String password;
+
+ /**
+ * Baut eine Verbindung mit Dualis auf und führt einen Login durch
+ *
+ * @param username
+ * Dualis Benutzername
+ * @param password
+ * Dualis Password
+ * @throws FailingHttpStatusCodeException
+ * @throws IOException
+ * @throws DualisScrapingException
+ * @throws DualisAuthenticationException
+ */
+ public DualisConnection(final String username, final String password) {
+ this.username = username;
+ this.password = password;
+ }
+
+ @SuppressWarnings("deprecation")
+ public List<VEvent> getEvents() throws FailingHttpStatusCodeException,
+ IOException, DualisScrapingException, DualisAuthenticationException {
+ HtmlPage page, loginPage;
+ final HtmlForm loginForm;
+ final HtmlInput usernameField, passwordField, submitButton;
+ final WebClient webClient = new WebClient();
+ final List<VEvent> events = new ArrayList<VEvent>();
+
+ webClient.setJavaScriptEnabled(false);
+ loginPage = webClient.getPage(DUALIS_URL);
+ try {
+ loginForm = loginPage.getFormByName("cn_loginForm");
+ } catch (ElementNotFoundException e) {
+ throw new DualisException.DualisScrapingException(
+ "Fehler beim Suchen des Login Formular auf der Startseite mit Name 'cn_loginForm'",
+ e);
+ }
+ try {
+ usernameField = loginForm.getInputByName("usrname");
+ } catch (ElementNotFoundException e) {
+ throw new DualisException.DualisScrapingException(
+ "Fehler beim Suchen des Username Input mit Name 'usrname'",
+ e);
+ }
+ usernameField.type(username);
+ try {
+ passwordField = loginForm.getInputByName("pass");
+ } catch (ElementNotFoundException e) {
+ throw new DualisException.DualisScrapingException(
+ "Fehler beim Suchen des Password Input mit Name 'pass'", e);
+ }
+ passwordField.type(password);
+
+ try {
+ submitButton = loginForm.getInputByValue("Anmelden");
+ } catch (ElementNotFoundException e) {
+ throw new DualisException.DualisScrapingException(
+ "Fehler beim Suchen des Login Submit Buttons mit Text 'Anmelden'",
+ e);
+ }
+ page = submitButton.click();
+ HtmlAnchor anchorByText;
+ try {
+ anchorByText = page.getAnchorByText("Stundenplan");
+ } catch (ElementNotFoundException e) { // Login failed
+ throw new DualisException.DualisAuthenticationException(
+ "Authentifizierung fehltgeschlagen", e);
+ }
+ page = anchorByText.click();
+
+ HtmlAnchor anchorMonat;
+ try {
+ anchorMonat = page.getAnchorByText("Monat");
+ } catch (ElementNotFoundException e) {
+ throw new DualisException.DualisScrapingException(
+ "Link Studenplan 'Woche' nicht gefunden", e);
+ }
+ page = anchorMonat.click();
+
+ for (HtmlElement elem : page.getElementsByTagName("div")) {
+ if (!elem.getAttribute("class").equals("tbMonthDay"))
+ continue;
+ final Date day;
+ Object dayTitle = elem
+ .getFirstByXPath("div[@class='tbsubhead']/a/@title");
+ if (dayTitle instanceof DomAttr) {
+ String value = ((DomAttr) dayTitle).getValue();
+ try {
+ day = dateFormat.parse(value);
+ } catch (ParseException e) {
+ e.printStackTrace();
+ continue;
+ }
+ } else {
+ System.err.println("kann datum nicht bestimmen");
+ continue;
+ }
+ for (HtmlElement appLink : elem.getElementsByTagName("a")) {
+ if (!appLink.getAttribute("class").equals("apmntLink"))
+ continue;
+ // title="08:15 - 10:45 / HOR-121 / Open Source Systeme"
+ String desc = StringUtils.strip(appLink.getAttribute("title"));
+ java.util.regex.Matcher matcher = appLinkPattern.matcher(desc);
+ if (matcher.matches() && matcher.groupCount() == 4) {
+ String timeStart = matcher.group(1);
+ String timeEnd = matcher.group(2);
+ String room = matcher.group(3);
+ String title = matcher.group(4);
+ System.out.println(timeStart + "-" + timeEnd + "-" + room
+ + "-" + title + "-" + day);
+ int hStart = Integer.parseInt(timeStart.split(":")[0]);
+ int mStart = Integer.parseInt(timeStart.split(":")[1]);
+ int hEnd = Integer.parseInt(timeEnd.split(":")[0]);
+ int mEnd = Integer.parseInt(timeEnd.split(":")[1]);
+ Date start = (Date) day.clone();
+ start.setHours(hStart);
+ start.setMinutes(mStart);
+ Date end = (Date) day.clone();
+ end.setHours(hEnd);
+ end.setMinutes(mEnd);
+ VEvent event = new VEvent.Builder().dtstart(start)
+ .dtstamp(start).dtend(end).summary(title).description(title)
+ .location(room).status("CONFIRMED").build();
+ events.add(event);
+ } else {
+ System.err.println("Skip: " + desc + " at day " + day);
+ }
+ }
+ }
+
+ return events;
+ }
+
+ // Parse Dates
+ private static final SimpleDateFormat dateFormat = new SimpleDateFormat(
+ "dd.MM.yyyy");
+
+ // Appointment Link Title
+ // example: 08:15 - 10:45 / HOR-121 / Open Source Systeme
+ private static final Pattern appLinkPattern = Pattern
+ .compile("(\\d{2}:\\d{2})\\s-\\s(\\d{2}:\\d{2})\\s\\/\\s(.+)\\s\\/\\s(.+)");
+
+} \ No newline at end of file
diff --git a/src/main/java/de/dhbw/horb/calendar/dualis/DualisException.java b/src/main/java/de/dhbw/horb/calendar/dualis/DualisException.java
new file mode 100644
index 0000000..5f337a2
--- /dev/null
+++ b/src/main/java/de/dhbw/horb/calendar/dualis/DualisException.java
@@ -0,0 +1,33 @@
+package de.dhbw.horb.calendar.dualis;
+
+public abstract class DualisException extends Exception {
+ public DualisException(String msg) {
+ super(msg);
+ }
+
+ public DualisException(String msg, Throwable e) {
+ super(msg, e);
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ public static class DualisAuthenticationException extends DualisException {
+ private static final long serialVersionUID = 1L;
+
+ public DualisAuthenticationException(String msg, Throwable e) {
+ super(msg, e);
+ }
+
+ public DualisAuthenticationException(String msg) {
+ super(msg);
+ }
+ }
+
+ public static class DualisScrapingException extends DualisException {
+ private static final long serialVersionUID = 1L;
+
+ public DualisScrapingException(String msg, Throwable e) {
+ super(msg, e);
+ }
+ }
+}
diff --git a/src/main/java/de/dhbw/horb/calendar/ics/AbstractICSType.java b/src/main/java/de/dhbw/horb/calendar/ics/AbstractICSType.java
new file mode 100644
index 0000000..3b6019d
--- /dev/null
+++ b/src/main/java/de/dhbw/horb/calendar/ics/AbstractICSType.java
@@ -0,0 +1,43 @@
+package de.dhbw.horb.calendar.ics;
+
+import java.text.SimpleDateFormat;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+public abstract class AbstractICSType {
+ /**
+ * Serialisierert dieses Calenderteil. Dem Ergebnis Fehlt noch der vCalendar
+ * Header und Footer
+ *
+ */
+ public abstract String serialize();
+
+ /**
+ * <b>RFC says:</b>
+ * <pre>
+ * FORM #2: DATE WITH UTC TIME
+ *
+ * The date with UTC time, or absolute time, is identified by a LATIN
+ * CAPITAL LETTER Z suffix character, the UTC designator, appended to
+ * the time value. For example, the following represents January 19,
+ * 1998, at 0700 UTC:
+ *
+ * 19980119T070000Z
+ *
+ * The "TZID" property parameter MUST NOT be applied to DATE-TIME
+ * properties whose time values are specified in UTC.
+ * </pre>
+ */
+ public static SimpleDateFormat dateTimeFormat = new SimpleDateFormat(
+ "yyyyMMdd'T'HHmmss'Z'");
+
+ /**
+ * described in <b>RFC section 3.3.11</b>
+ *
+ * @param text
+ * @return
+ */
+ public static String escapeText(String text) {
+ return StringEscapeUtils.escapeJava(text); //XXX TODO
+ }
+}
diff --git a/src/main/java/de/dhbw/horb/calendar/ics/VCalendar.java b/src/main/java/de/dhbw/horb/calendar/ics/VCalendar.java
new file mode 100644
index 0000000..fcf083a
--- /dev/null
+++ b/src/main/java/de/dhbw/horb/calendar/ics/VCalendar.java
@@ -0,0 +1,51 @@
+package de.dhbw.horb.calendar.ics;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class VCalendar {
+ List<AbstractICSType> icsObjects = new ArrayList<AbstractICSType>();
+ private final String title;
+
+ public VCalendar(final String title) {
+ this.title = title;
+ }
+
+ public void add(AbstractICSType ics) {
+ icsObjects.add(ics);
+ }
+
+ /**
+ *
+ * @return
+ */
+ public String serialize() {
+ final StringBuilder sb = new StringBuilder();
+ // Einleiten des Kalenders
+ sb.append("BEGIN:VCALENDAR\n");
+ // This property specifies the identifier for the product that created
+ // the iCalendar object.
+ sb.append("PRODID:-//DHBW Horb i08005//DHBW Calender 0.1//EN\n");
+ // Datenformat version
+ sb.append("VERSION:2.0\n");
+ // This property defines the calendar scale used for the
+ // calendar information specified in the iCalendar object.
+ sb.append("CALSCALE:GREGORIAN\n");
+ // This property defines the iCalendar object method
+ // associated with the calendar object.
+ sb.append("METHOD:PUBLISH\n");
+ /* Extensions */
+ //
+ sb.append("X-WR-TIMEZONE:UTC\n");
+ // Name des Kalenders
+ sb.append("X-WR-CALDESC:" + AbstractICSType.escapeText(title)+"\n");
+ sb.append("X-WR-CALNAME:" + AbstractICSType.escapeText(title)+"\n");
+
+ // Elemente
+ for (AbstractICSType ics : icsObjects) {
+ sb.append(ics.serialize());
+ }
+ sb.append("END:VCALENDAR\n");
+ return sb.toString();
+ }
+}
diff --git a/src/main/java/de/dhbw/horb/calendar/ics/VEvent.java b/src/main/java/de/dhbw/horb/calendar/ics/VEvent.java
new file mode 100644
index 0000000..74f00ba
--- /dev/null
+++ b/src/main/java/de/dhbw/horb/calendar/ics/VEvent.java
@@ -0,0 +1,79 @@
+package de.dhbw.horb.calendar.ics;
+
+import java.util.Date;
+
+public class VEvent extends AbstractICSType {
+ public Date dtstamp = new Date();
+ public Date dtstart = new Date();
+ public Date dtend = new Date();
+ public String status = "";
+ public String summary = "";
+ public String description = "";
+ public String location = "";
+
+ /**
+ * {@inheritDoc} <br/>
+ * <br/>
+ * <b>See RFC section 3.6.1</b> for VEVENT Specification
+ */
+ @Override
+ public String serialize() {
+ final StringBuffer sb = new StringBuffer();
+ sb.append("BEGIN:VEVENT\n");
+ sb.append("DTSTART:" + dateTimeFormat.format(dtstart) + "\n");
+ sb.append("DTEND:" + dateTimeFormat.format(dtend) + "\n");
+ sb.append("DTSTAMP:" + dateTimeFormat.format(dtstamp) + "\n");
+ sb.append("UID:vevent_" + dateTimeFormat.format(dtstamp) + "@dhbw.de\n");
+ sb.append("CREATED:" + dateTimeFormat.format(new Date()) + "\n");
+ sb.append("STATUS:" + escapeText(status) + "\n");
+ sb.append("SUMMARY:" + escapeText(summary) + "\n");
+ sb.append("DESCRIPTION:" + escapeText(description) + "\n");
+ sb.append("LOCATION:" + escapeText(location) + "\n");
+ sb.append("TRANSP:OPAQUE\n");
+ sb.append("END:VEVENT\n");
+ return sb.toString();
+ }
+
+ public static class Builder {
+ VEvent event = new VEvent();
+
+ public Builder dtstamp(Date dtstamp) {
+ event.dtstamp = dtstamp;
+ return this;
+ }
+
+ public Builder dtstart(Date dtstart) {
+ event.dtstart = dtstart;
+ return this;
+ }
+
+ public Builder dtend(Date dtend) {
+ event.dtend = dtend;
+ return this;
+ }
+
+ public Builder summary(String summary) {
+ event.summary = summary;
+ return this;
+ }
+
+ public Builder description(String description) {
+ event.description = description;
+ return this;
+ }
+
+ public Builder location(String location) {
+ event.location = location;
+ return this;
+ }
+
+ public VEvent build() {
+ return event;
+ }
+
+ public Builder status(String status) {
+ event.status = status;
+ return this;
+ }
+ }
+}
diff --git a/src/main/java/de/dhbw/horb/calendar/ui/LoginWorker.java b/src/main/java/de/dhbw/horb/calendar/ui/LoginWorker.java
new file mode 100644
index 0000000..aa2c9b7
--- /dev/null
+++ b/src/main/java/de/dhbw/horb/calendar/ui/LoginWorker.java
@@ -0,0 +1,90 @@
+package de.dhbw.horb.calendar.ui;
+
+import java.io.IOException;
+
+import com.gargoylesoftware.htmlunit.ElementNotFoundException;
+import com.gargoylesoftware.htmlunit.WebClient;
+import com.gargoylesoftware.htmlunit.html.HtmlForm;
+import com.gargoylesoftware.htmlunit.html.HtmlInput;
+import com.gargoylesoftware.htmlunit.html.HtmlPage;
+
+import de.dhbw.horb.calendar.dualis.DualisConnection;
+import de.dhbw.horb.calendar.dualis.DualisException;
+import de.dhbw.horb.calendar.dualis.DualisException.DualisAuthenticationException;
+
+class LoginWorker implements Runnable {
+ private final WebClient client;
+ private HtmlPage page = null;
+ private HtmlForm loginForm = null;
+ private HtmlInput usernameField;
+ private HtmlInput passwordField;
+ private HtmlInput submitButton;
+ private final String username;
+ private final String password;
+ private final LoginWorkerListener listener;
+
+ public LoginWorker(final LoginWorkerListener listener, final String username, final String password) {
+ this.listener = listener;
+ this.username = username;
+ this.password = password;
+
+ client = new WebClient();
+ }
+
+ private void step1() throws Exception {
+ page = client.getPage(DualisConnection.DUALIS_URL);
+ }
+
+ private void step2() {
+ loginForm = page.getFormByName("cn_loginForm");
+ usernameField = loginForm.getInputByName("usrname");
+ passwordField = loginForm.getInputByName("pass");
+ submitButton = loginForm.getInputByValue("Anmelden");
+ }
+
+ private void step3() throws IOException {
+ usernameField.type(username);
+ passwordField.type(password);
+ page = submitButton.click();
+ }
+
+ private void step4() throws DualisAuthenticationException {
+ try {
+ page.getAnchorByText("Stundenplan");
+ } catch (ElementNotFoundException e) {
+ throw new DualisException.DualisAuthenticationException(
+ "Authentifizierung fehltgeschlagen", e);
+ }
+ }
+
+ @Override
+ public void run() {
+ try {
+ listener.setProgress(0.2, "Lade Seite");
+ step1();
+
+ listener.setProgress(0.4, "Analysiere Seite");
+ step2();
+
+ listener.setProgress(0.6, "Sende Login");
+ step3();
+
+ listener.setProgress(0.8, "Prüfe Login");
+ step4();
+ listener.setProgress(1.0, "Erfolgreich");
+
+ listener.success(username,password);
+ } catch (Exception e) {
+ e.printStackTrace();
+ listener.error(e);
+ }
+ }
+
+ public interface LoginWorkerListener {
+ public void setProgress(double d, String description);
+
+ public void success(String username, String password);
+
+ public void error(Exception e);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/dhbw/horb/calendar/ui/MyApplication.java b/src/main/java/de/dhbw/horb/calendar/ui/MyApplication.java
new file mode 100644
index 0000000..9a0f222
--- /dev/null
+++ b/src/main/java/de/dhbw/horb/calendar/ui/MyApplication.java
@@ -0,0 +1,161 @@
+package de.dhbw.horb.calendar.ui;
+
+import com.vaadin.Application;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.ui.Label;
+import com.vaadin.ui.LoginForm;
+import com.vaadin.ui.LoginForm.LoginEvent;
+import com.vaadin.ui.LoginForm.LoginListener;
+import com.vaadin.ui.ProgressIndicator;
+import com.vaadin.ui.TabSheet;
+import com.vaadin.ui.Window;
+
+import de.dhbw.horb.calendar.ui.LoginWorker.LoginWorkerListener;
+
+public class MyApplication extends Application {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void init() {
+ setMainWindow(new MyMainWindow());
+ }
+
+ public static class MyMainWindow extends Window {
+ private static final long serialVersionUID = 1L;
+ private TabSheet tabSheet = new TabSheet();
+ private LoginComponent loginComponent;
+ private StundenplanComponent stundenplanComponent;
+ private LogoutComponent logoutComponent;
+ private String password = "";
+ private String username = "";
+ {
+ {
+ loginComponent = new LoginComponent(this);
+ stundenplanComponent = new StundenplanComponent(this);
+ logoutComponent = new LogoutComponent(this);
+ }
+ }
+
+ public MyMainWindow() {
+ super("DHBW Calendar");
+ tabSheet.addTab(loginComponent, "Login", null);
+ addComponent(tabSheet);
+ }
+
+ public void login(String username, String password) {
+ this.username = username;
+ this.password = password;
+ tabSheet.removeTab(tabSheet.getTab(loginComponent));
+
+ tabSheet.addTab(stundenplanComponent, "Stundenplan", null);
+ tabSheet.addTab(logoutComponent, "Logout", null);
+ }
+
+ public void logout() {
+ this.username = this.password = "";
+ tabSheet.removeTab(tabSheet.getTab(stundenplanComponent));
+ tabSheet.removeTab(tabSheet.getTab(logoutComponent));
+
+ tabSheet.addTab(loginComponent, "Login", null);
+ }
+
+ public String getUsername() {
+ return username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+ }
+
+ private static class LogoutComponent extends FormLayout {
+ private static final long serialVersionUID = 1L;
+
+ private final MyMainWindow mainWindow;
+
+ public LogoutComponent(MyMainWindow mainWindow) {
+ this.mainWindow = mainWindow;
+ Button logoutButton = new Button("Logout");
+ logoutButton.addListener(new ClickListener() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ LogoutComponent.this.mainWindow.logout();
+ }
+ });
+ addComponent(logoutButton);
+ }
+ }
+
+ private static class LoginComponent extends FormLayout {
+ private static final long serialVersionUID = 1L;
+
+ private final MyMainWindow mainWindow;
+ private final DualisLoginForm loginForm;
+ private final Label labelDescription;
+ private final ProgressIndicator progressIndicator;
+ private final LoginWorkerListener loginWorkerListener;
+ {
+ {
+ loginForm = new DualisLoginForm();
+ labelDescription = new Label("");
+
+ progressIndicator = new ProgressIndicator();
+ progressIndicator.setVisible(false);
+ progressIndicator.setSizeFull();
+
+ loginWorkerListener = new LoginWorkerListener() {
+
+ @Override
+ public void success(String username, String password) {
+ mainWindow.login(username, password);
+ labelDescription.setValue("");
+ progressIndicator.setVisible(false);
+ loginForm.setVisible(true);
+ }
+
+ @Override
+ public void setProgress(double d, String description) {
+ progressIndicator.setValue(new Float(d));
+ labelDescription.setValue(description);
+ }
+
+ @Override
+ public void error(Exception e) {
+ progressIndicator.setVisible(false);
+ labelDescription.setValue("Fehler: " + e.getMessage());
+ loginForm.setVisible(true);
+ }
+ };
+ }
+ }
+
+ public LoginComponent(final MyMainWindow mainWindow) {
+ this.mainWindow = mainWindow;
+
+ loginForm.addListener(new LoginListener() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void onLogin(LoginEvent event) {
+ new Thread(new LoginWorker(loginWorkerListener, event
+ .getLoginParameter("username"), event
+ .getLoginParameter("password"))).start();
+ loginForm.setVisible(false);
+ progressIndicator.setVisible(true);
+ }
+ });
+ addComponent(loginForm);
+ addComponent(labelDescription);
+ addComponent(progressIndicator);
+ }
+ }
+
+ private static class DualisLoginForm extends LoginForm {
+ private static final long serialVersionUID = 1L;
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/dhbw/horb/calendar/ui/StundenplanComponent.java b/src/main/java/de/dhbw/horb/calendar/ui/StundenplanComponent.java
new file mode 100644
index 0000000..ba3cc1c
--- /dev/null
+++ b/src/main/java/de/dhbw/horb/calendar/ui/StundenplanComponent.java
@@ -0,0 +1,102 @@
+package de.dhbw.horb.calendar.ui;
+
+import java.util.Date;
+
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Button.ClickEvent;
+import com.vaadin.ui.Button.ClickListener;
+import com.vaadin.ui.Alignment;
+import com.vaadin.ui.FormLayout;
+import com.vaadin.ui.ProgressIndicator;
+import com.vaadin.ui.Table;
+import com.vaadin.ui.VerticalLayout;
+
+import de.dhbw.horb.calendar.dualis.DualisConnection;
+import de.dhbw.horb.calendar.ics.VEvent;
+import de.dhbw.horb.calendar.ui.MyApplication.MyMainWindow;
+
+public class StundenplanComponent extends FormLayout {
+ private static final long serialVersionUID = 1L;
+
+ private ClickListener buttonFetchListener = new ClickListener() {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ public void buttonClick(ClickEvent event) {
+ table.removeAllItems();
+ table.setEnabled(false);
+ buttonFetch.setVisible(false);
+ StundenplanComponent.this.addComponentAsFirst(refresher);
+
+ new Thread() {
+ public void run() {
+ DualisConnection dualisConnection = new DualisConnection(
+ myMainWindow.getUsername(),
+ myMainWindow.getPassword());
+ try {
+ for (VEvent vevent : dualisConnection.getEvents()) {
+ synchronized (getApplication()) {
+ table.addItem(new Object[] { vevent.dtstart,
+ vevent.dtend, vevent.summary,
+ vevent.location },
+ vevent.dtstart.getTime());
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ table.addItem(new Object[] { new Date(), new Date(),
+ "Fehler", e.getMessage() });
+ }
+ synchronized (getApplication()) {
+ buttonFetch.setVisible(true);
+ table.setEnabled(true);
+ StundenplanComponent.this.removeComponent(refresher);
+ }
+ };
+ }.start();
+ }
+ };
+
+ private final Button buttonFetch = new Button("Kalender holen",
+ buttonFetchListener);
+
+ /**
+ * The Progress Indicator have no real sense. Its used to force the client
+ * to poll all 500ms for new events
+ */
+ final ProgressIndicator refresher = new ProgressIndicator();
+ {
+ {
+ refresher.setPollingInterval(500);
+ refresher.setSizeFull();
+ }
+ }
+
+ private final Table table = new Table("Stundenplan");
+ {
+ {
+ table.setSizeFull();
+ table.setSelectable(true);
+ table.addContainerProperty("begin", Date.class, "");
+ table.addContainerProperty("end", Date.class, "");
+ table.addContainerProperty("summary", String.class, "");
+ table.addContainerProperty("location", String.class, "");
+ }
+ }
+
+ private final MyMainWindow myMainWindow;
+
+ public StundenplanComponent(MyMainWindow myMainWindow) {
+ this.myMainWindow = myMainWindow;
+
+ VerticalLayout layout = new VerticalLayout();
+ layout.addComponent(buttonFetch);
+ layout.addComponent(table);
+ layout.setSizeFull();
+
+ addComponent(layout);
+ layout.setComponentAlignment(
+ buttonFetch,
+ Alignment.MIDDLE_CENTER);
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/dhbw/horb/calendar/util/AuthenticatedServlet.java b/src/main/java/de/dhbw/horb/calendar/util/AuthenticatedServlet.java
new file mode 100644
index 0000000..47ca537
--- /dev/null
+++ b/src/main/java/de/dhbw/horb/calendar/util/AuthenticatedServlet.java
@@ -0,0 +1,84 @@
+package de.dhbw.horb.calendar.util;
+
+import java.io.IOException;
+import java.util.StringTokenizer;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+
+import sun.misc.BASE64Decoder;
+
+public abstract class AuthenticatedServlet extends HttpServlet {
+ private static final long serialVersionUID = 1L;
+
+
+ private String loginRealm = "Servlet Login";
+
+ public void setLoginRealm(String loginRealm) {
+ this.loginRealm = loginRealm;
+ }
+
+ public String getLoginRealm() {
+ return loginRealm;
+ }
+
+ String[] getUsernamePassword(HttpServletRequest request) throws IOException {
+ String authHeader = request.getHeader("Authorization");
+ if (authHeader != null) {
+ StringTokenizer st = new StringTokenizer(authHeader);
+ if (st.hasMoreTokens()) {
+ String basic = st.nextToken();
+ if (basic.equalsIgnoreCase("Basic")) {
+ String credentials = st.nextToken();
+
+ // XXX fixme, dont use sun.misc
+ BASE64Decoder decoder = new BASE64Decoder();
+ String userPass = new String(
+ decoder.decodeBuffer(credentials));
+
+ // The decoded string is in the form
+ // "userID:password".
+ int p = userPass.indexOf(":");
+ if (p != -1) {
+ String username = userPass.substring(0, p).trim();
+ String password = userPass.substring(p + 1).trim();
+ String[] userPassword = new String[] { username,
+ password };
+ if ("".equals(userPassword) || "".equals(password)) {
+ return null;
+ } else {
+ return new String[] { username, password };
+ }
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ void writeAuthenticationRequest(HttpServletResponse response) {
+ String realm = StringEscapeUtils.escapeJava(getLoginRealm());
+ String s = "Basic realm=\"" + realm + "\"";
+ response.setHeader("WWW-Authenticate", s);
+ response.setStatus(401);
+ }
+
+ @Override
+ protected void doGet(HttpServletRequest request,
+ HttpServletResponse response) throws ServletException, IOException {
+
+ String[] usernamePassword = getUsernamePassword(request);
+ if (usernamePassword == null) {
+ writeAuthenticationRequest(response);
+ return;
+ }
+ doGet(request, response, usernamePassword[0], usernamePassword[1]);
+ }
+
+ protected abstract void doGet(HttpServletRequest request,
+ HttpServletResponse response, String username, String password) throws ServletException, IOException;
+}