summaryrefslogtreecommitdiff
path: root/BKUCommonGUI
diff options
context:
space:
mode:
Diffstat (limited to 'BKUCommonGUI')
-rw-r--r--BKUCommonGUI/pom.xml43
-rw-r--r--BKUCommonGUI/src/main/java/META-INF/MANIFEST.MF3
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/AbstractHelpListener.java103
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java176
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java1665
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUIcons.java57
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/DefaultHelpListener.java81
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataTableModel.java63
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpKeyListener.java46
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpLinkFocusManager.java138
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpMouseListener.java54
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpViewer.java218
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HyperlinkRenderer.java54
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/ImagePanel.java50
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java74
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java360
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusFocusListener.java38
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusListener.java44
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/html/RestrictedHTMLEditorKit.java49
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/html/RestrictedImageView.java67
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/FontProvider.java40
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/FontProviderException.java29
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/MimeFilter.java65
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/MimeTypes.java53
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/SecureViewerSaveDialog.java121
-rw-r--r--BKUCommonGUI/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java107
-rw-r--r--BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties109
-rw-r--r--BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties107
-rw-r--r--BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip128.pngbin0 -> 7775 bytes
-rw-r--r--BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip16.pngbin0 -> 787 bytes
-rw-r--r--BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip24.pngbin0 -> 1227 bytes
-rw-r--r--BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip32.pngbin0 -> 1753 bytes
-rw-r--r--BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip48.pngbin0 -> 2771 bytes
-rw-r--r--BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chiperling105.pngbin0 -> 4035 bytes
-rw-r--r--BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/help.pngbin0 -> 441 bytes
-rw-r--r--BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/help_focus.pngbin0 -> 343 bytes
-rw-r--r--BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java62
-rw-r--r--BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java199
-rw-r--r--BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/DummyFontLoader.java41
-rw-r--r--BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/SecureViewerDialogTest.java167
-rw-r--r--BKUCommonGUI/src/test/resources/commons-logging.properties1
-rw-r--r--BKUCommonGUI/src/test/resources/log4j.properties19
42 files changed, 4503 insertions, 0 deletions
diff --git a/BKUCommonGUI/pom.xml b/BKUCommonGUI/pom.xml
new file mode 100644
index 00000000..b0ac6418
--- /dev/null
+++ b/BKUCommonGUI/pom.xml
@@ -0,0 +1,43 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <artifactId>bku</artifactId>
+ <groupId>at.gv.egiz</groupId>
+ <version>1.2.11</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>at.gv.egiz</groupId>
+ <artifactId>BKUCommonGUI</artifactId>
+ <name>BKU GUI</name>
+ <version>1.2.11</version>
+ <dependencies>
+ <dependency>
+ <groupId>at.gv.egiz</groupId>
+ <artifactId>smcc</artifactId>
+ <version>1.2.11</version>
+ </dependency>
+ <dependency>
+ <groupId>at.gv.egiz</groupId>
+ <artifactId>STAL</artifactId>
+ <version>1.2.11</version>
+ <scope>compile</scope>
+ </dependency>
+ <!-- see BKUFonts.pom
+ <dependency>
+ <groupId>at.gv.egiz</groupId>
+ <artifactId>BKUFonts</artifactId>
+ <version>1.0</version>
+ <scope>runtime</scope>
+ </dependency-->
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <groupId>org.apache.maven.plugins</groupId>
+ <configuration>
+ <debug>false</debug>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project> \ No newline at end of file
diff --git a/BKUCommonGUI/src/main/java/META-INF/MANIFEST.MF b/BKUCommonGUI/src/main/java/META-INF/MANIFEST.MF
new file mode 100644
index 00000000..5e949512
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/META-INF/MANIFEST.MF
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Class-Path:
+
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/AbstractHelpListener.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/AbstractHelpListener.java
new file mode 100644
index 00000000..6fd1ffea
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/AbstractHelpListener.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.gui;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Implement the showDocument(URL) method to provide an actual HelpListener.
+ * This class does not keep a GUI reference and subclasses should not interfere with the GUI.
+ * Therefore, any errors occurring in showDocument() should be handled/displayed within
+ * showDocument() and exceptions thrown from showDocument() are logged, not displayed in the GUI.
+ * <br/>
+ * The help URL is build as [baseURL]/[locale]/[helpTopic].html
+ * (note that no session information is contained).
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public abstract class AbstractHelpListener implements ActionListener {
+
+ /**
+ * any locale not in the list will be mapped to 'de'
+ */
+ public static final String[] SUPPORTED_LANGUAGES = new String[] { "de" };
+
+ protected final static Log log = LogFactory.getLog(AbstractHelpListener.class);
+ protected URL baseURL;
+ protected Locale locale;
+ protected ResourceBundle messages;
+
+ public AbstractHelpListener(URL baseURL, Locale locale) {
+ if (baseURL == null || "".equals(baseURL.toString())) {
+ throw new RuntimeException("no help URL provided");
+ }
+ this.baseURL = baseURL;
+ this.locale = locale;
+ if (locale != null) {
+ messages = ResourceBundle.getBundle(BKUGUIFacade.MESSAGES_BUNDLE, locale);
+ } else {
+ messages = ResourceBundle.getBundle(BKUGUIFacade.MESSAGES_BUNDLE);
+ }
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.debug("received help action: " + e.getActionCommand());
+ URL helpURL = constructHelpURL(baseURL, e.getActionCommand());
+ try {
+ showDocument(helpURL, e.getActionCommand());
+ } catch (Exception ex) {
+ log.error("could not display help document " + helpURL + ": " + ex.getMessage());
+ }
+ }
+
+ private URL constructHelpURL(URL baseURL, String helpTopic) {
+ URL helpURL = baseURL;
+ log.trace("constructing help URL: " + helpURL);
+ try {
+ // not localized for now
+ //check if locale.getLanguage() supported and add default if not
+// if (locale != null) {
+// helpURL = new URL(helpURL, locale.toString() + "/");
+// log.trace("constructing help URL: " + helpURL);
+// }
+ if (helpTopic != null && !"".equals(helpTopic)) {
+ helpURL = new URL(helpURL, "de/" + helpTopic + ".html");
+ log.trace("constructing help URL: " + helpURL);
+ }
+ } catch (MalformedURLException ex) {
+ log.error("Failed to construct help URL for help item " + helpTopic + ": " + ex.getMessage());
+ }
+ return helpURL;
+ }
+
+ /**
+ * Errors from HelpListeners should not (are not) displayed in the applet,
+ * but should rather be in the HelpListener specific way.
+ * Therefore, implementations SHOULD NOT throw exceptions (these are only logged).
+ * @param helpDocument
+ * @throws java.lang.Exception
+ */
+ public abstract void showDocument(URL helpDocument, String helpTopic) throws Exception;
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java
new file mode 100644
index 00000000..1e23c64c
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java
@@ -0,0 +1,176 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.gui;
+
+ import at.gv.egiz.stal.HashDataInput;
+import at.gv.egiz.smcc.PINSpec;
+import java.awt.Color;
+import java.awt.event.ActionListener;
+import java.util.List;
+import java.util.Locale;
+
+public interface BKUGUIFacade {
+
+ public static final String ERR_UNKNOWN_WITH_PARAM = "error.unknown.param";
+ public static final String ERR_UNKNOWN = "error.unknown";
+ public static final String ERR_SERVICE_UNREACHABLE = "error.ws.unreachable";
+ public static final String ERR_NO_PCSC = "error.pcsc";
+ public static final String ERR_NO_CARDTERMINAL = "error.cardterminal";
+ public static final String ERR_NO_HASHDATA = "error.no.hashdata";
+ public static final String ERR_DISPLAY_HASHDATA = "error.display.hashdata";
+ public static final String ERR_WRITE_HASHDATA = "error.write.hashdata";
+ public static final String ERR_INVALID_HASH = "error.invalid.hash";
+ public static final String ERR_CARD_LOCKED = "error.card.locked";
+ public static final String ERR_CARD_NOTACTIVATED = "error.card.notactivated";
+ public static final String ERR_PIN_TIMEOUT = "error.pin.timeout";
+ public static final String ERR_VIEWER = "error.viewer";
+ public static final String ERR_EXTERNAL_LINK = "error.external.link";
+ public static final String ERR_CONFIG = "error.config";
+
+ /** no leading slash for Messages resource, leading slash for images */
+ public static final String MESSAGES_BUNDLE = "at/gv/egiz/bku/gui/Messages";
+ public static final String DEFAULT_BACKGROUND = "/at/gv/egiz/bku/gui/chip32.png";
+ public static final String DEFAULT_ICON = "/at/gv/egiz/bku/gui/chiperling105.png";
+ public static final String HELP_IMG = "/at/gv/egiz/bku/gui/help.png";
+ public static final String HELP_IMG_FOCUS = "/at/gv/egiz/bku/gui/help.png"; //help_focus.png";
+ public static final String HASHDATA_FONT = "Monospaced";
+ public static final Color ERROR_COLOR = Color.RED;
+ public static final Color HYPERLINK_COLOR = Color.BLUE;
+ public static final String TITLE_WELCOME = "title.welcome";
+ public static final String TITLE_INSERTCARD = "title.insertcard";
+ public static final String TITLE_CARD_NOT_SUPPORTED = "title.cardnotsupported";
+ public static final String TITLE_VERIFY_PIN = "title.verify.pin";
+ public static final String TITLE_SIGN = "title.sign";
+ public static final String TITLE_VERIFY_PINPAD = "title.verify.pinpad";
+ public static final String TITLE_ERROR = "title.error";
+ public static final String TITLE_WARNING = "title.warning";
+ public static final String TITLE_ENTRY_TIMEOUT = "title.entry.timeout";
+ public static final String TITLE_RETRY = "title.retry";
+ public static final String TITLE_WAIT = "title.wait";
+ public static final String TITLE_SIGNATURE_DATA = "title.signature.data";
+ public static final String WINDOWTITLE_SAVE = "windowtitle.save";
+ public static final String WINDOWTITLE_ERROR = "windowtitle.error";
+ public static final String WINDOWTITLE_SAVEDIR = "windowtitle.savedir";
+ public static final String WINDOWTITLE_OVERWRITE = "windowtitle.overwrite";
+ public static final String WINDOWTITLE_VIEWER = "windowtitle.viewer";
+ public static final String WINDOWTITLE_HELP = "windowtitle.help";
+
+ // removed message.* prefix to reuse keys as help keys
+ public static final String MESSAGE_WELCOME = "welcome";
+ public static final String MESSAGE_WAIT = "wait";
+ public static final String MESSAGE_INSERTCARD = "insertcard";
+ public static final String MESSAGE_CARD_NOT_SUPPORTED = "cardnotsupported";
+ public static final String MESSAGE_ENTERPIN = "enterpin";
+ public static final String MESSAGE_ENTERPIN_PINPAD = "enterpin.pinpad";
+ public static final String MESSAGE_ENTERPIN_PINPAD_DIRECT = "enterpin.pinpad.direct";
+ public static final String MESSAGE_HASHDATALINK = "hashdatalink";
+ public static final String MESSAGE_HASHDATALINK_TINY = "hashdatalink.tiny";
+ public static final String MESSAGE_HASHDATALINK_FOCUS = "hashdatalink.focus";
+ public static final String MESSAGE_HASHDATALINK_TINY_FOCUS = "hashdatalink.tiny.focus";
+ public static final String MESSAGE_HASHDATALIST = "hashdatalist";
+ public static final String MESSAGE_HASHDATA_VIEWER = "hashdata.viewer";
+ public static final String MESSAGE_UNSUPPORTED_MIMETYPE = "unsupported.mimetype";
+ public static final String MESSAGE_RETRIES = "retries";
+ public static final String MESSAGE_LAST_RETRY = "retries.last";
+ public static final String MESSAGE_RETRIES_PINPAD = "retries.pinpad";
+ public static final String MESSAGE_LAST_RETRY_PINPAD = "retries.pinpad.last";
+ public static final String MESSAGE_OVERWRITE = "overwrite";
+ public static final String MESSAGE_HELP = "help";
+
+ public static final String WARNING_XHTML = "warning.xhtml";
+ public static final String LABEL_PIN = "label.pin";
+ public static final String LABEL_PINSIZE = "label.pinsize";
+ public static final String HELP_WELCOME = "help.welcome";
+ public static final String HELP_WAIT = "help.wait";
+ public static final String HELP_CARDNOTSUPPORTED = "help.cardnotsupported";
+ public static final String HELP_INSERTCARD = "help.insertcard";
+ public static final String HELP_VERIFY_PIN = "help.cardpin";
+ public static final String HELP_SIGNPIN = "help.signpin";
+ public static final String HELP_PINPAD = "help.pinpad";
+ public static final String HELP_RETRY = "help.retry";
+ public static final String HELP_HASHDATA = "help.hashdata";
+ public static final String HELP_HASHDATALIST = "help.hashdatalist";
+ public static final String HELP_HASHDATAVIEWER = "help.hashdataviewer";
+ public static final String BUTTON_OK = "button.ok";
+ public static final String BUTTON_CANCEL = "button.cancel";
+ public static final String BUTTON_BACK = "button.back";
+ public static final String BUTTON_SIGN = "button.sign";
+ public static final String BUTTON_SAVE = "button.save";
+ public static final String BUTTON_CLOSE = "button.close";
+ public static final String SAVE_HASHDATAINPUT_PREFIX = "save.hashdatainput.prefix";
+ public static final String ALT_HELP = "alt.help";
+
+ public void showEnterPINDirect(PINSpec spec, int retries);
+
+ public void showEnterPIN(PINSpec spec, int retries);
+
+ public void showSignatureDataDialog(PINSpec spec, ActionListener listener, String string, ActionListener aThis0, String string0, ActionListener aThis1, String string1);
+
+ public void correctionButtonPressed();
+
+ public void allKeysCleared();
+
+ public void validKeyPressed();
+
+ public enum Style { tiny, simple, advanced };
+
+ /**
+ * BKUWorker needs to init signature card with locale
+ * @return
+ */
+ public Locale getLocale();
+
+ public void showVerifyPINDialog(PINSpec pinSpec, int numRetries,
+ ActionListener okListener, String okCommand,
+ ActionListener cancelListener, String cancelCommand);
+
+ public void showSignaturePINDialog(PINSpec pinSpec, int numRetries,
+ ActionListener signListener, String signCommand,
+ ActionListener cancelListener, String cancelCommand,
+ ActionListener viewerListener, String viewerCommand);
+
+ public char[] getPin();
+
+ /**
+ *
+ * @param dataToBeSigned
+ * @param backListener if list of references hides pin dialog, backListener
+ * receives an action when user hits 'back' button (i.e. whenever the pin-dialog
+ * needs to be re-paint)
+ * @param backCommand
+ */
+ public void showSecureViewer(List<HashDataInput> dataToBeSigned,
+ ActionListener backListener, String backCommand);
+
+ public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams,
+ ActionListener okListener, String okCommand);
+
+ public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams);
+
+ public void showMessageDialog(String titleKey,
+ String msgKey, Object[] msgParams,
+ String buttonKey,
+ ActionListener okListener, String okCommand);
+
+ public void showMessageDialog(String titleKey,
+ String msgKey, Object[] msgParams);
+
+ public void showMessageDialog(String titleKey,
+ String msgKey);
+
+ public void getFocusFromBrowser();
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java
new file mode 100644
index 00000000..e005836c
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java
@@ -0,0 +1,1665 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package at.gv.egiz.bku.gui;
+
+import at.gv.egiz.bku.gui.viewer.FontProviderException;
+import at.gv.egiz.bku.gui.viewer.FontProvider;
+import at.gv.egiz.bku.gui.viewer.SecureViewerSaveDialog;
+import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.stal.HashDataInput;
+import java.awt.Color;
+import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.Font;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseMotionAdapter;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.List;
+import java.util.Locale;
+import java.util.ResourceBundle;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import javax.swing.GroupLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.LayoutStyle;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+
+
+/**
+ *
+ * @author clemens
+ */
+public class BKUGUIImpl implements BKUGUIFacade {
+
+ protected static final Log log = LogFactory.getLog(BKUGUIImpl.class);
+
+ protected enum PinLabelPosition {
+ LEFT, ABOVE
+ }
+
+ protected HelpMouseListener helpMouseListener;
+ protected HelpKeyListener helpKeyListener;
+ protected SwitchFocusFocusListener switchFocusKeyListener;
+ protected SecureViewerDialog secureViewer;
+ protected FontProvider fontProvider;
+
+ protected Container contentPane;
+ protected ResourceBundle messages;
+ /** left and right side main panels */
+ protected JPanel iconPanel;
+ protected JPanel contentPanel;
+ /** right side content panels and layouts */
+ protected JPanel headerPanel;
+ protected JPanel mainPanel;
+ protected JPanel buttonPanel;
+ /** right side fixed labels */
+ protected JLabel titleLabel;
+ protected JLabel helpLabel;
+ protected JLabel switchFocusDummyLabel;
+ /** remember the pinfield to return to worker */
+ protected JPasswordField pinField;
+ protected Document pinpadPIN;
+
+ protected int buttonSize;
+
+ /** gui style config (default 'simple') */
+ protected boolean renderHeaderPanel = false;
+ protected boolean renderIconPanel = false;
+ protected boolean renderCancelButton = false;
+ protected boolean shortText = false;
+ protected PinLabelPosition pinLabelPos = PinLabelPosition.LEFT;
+ protected boolean renderRefId = false;
+
+ /**
+ * set contentPane
+ * init message bundle
+ * configure the style
+ * register the help listener
+ * create GUI (on event-dispatching thread)
+ *
+ * @param contentPane
+ * @param locale
+ * @param guiStyle
+ * @param background
+ * @param helpListener
+ */
+ public BKUGUIImpl(Container contentPane,
+ Locale locale,
+ Style guiStyle,
+ URL background,
+ FontProvider fontProvider,
+ ActionListener helpListener,
+ SwitchFocusListener switchFocusListener) {
+ this.contentPane = contentPane;
+
+ loadMessageBundle(locale);
+
+ if (guiStyle == Style.advanced) {
+ renderHeaderPanel = true;
+ renderIconPanel = false;
+ renderCancelButton = true;
+ renderRefId = true;
+ } else if (guiStyle == Style.tiny) {
+ shortText = true;
+ pinLabelPos = PinLabelPosition.ABOVE;
+ }
+
+ // ensure that buttons can be fired with enter key too
+ UIManager.put("Button.defaultButtonFollowsFocus", Boolean.TRUE);
+
+ registerHelpListener(helpListener);
+
+ registerSwitchFocusListener(switchFocusListener);
+
+ this.fontProvider = fontProvider;
+ createGUI(background);
+ }
+
+ private void createGUI(final URL background) {
+
+ try {
+
+ log.debug("scheduling gui initialization");
+
+ SwingUtilities.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+
+ log.debug("[" + Thread.currentThread().getName() + "] initializing gui");
+
+ if (renderIconPanel) {
+ initIconPanel(background);
+ initContentPanel(null);
+ } else {
+ initContentPanel(background);
+ }
+
+ GroupLayout layout = new GroupLayout(contentPane);
+ contentPane.setLayout(layout);
+
+ if (renderIconPanel) {
+ layout.setHorizontalGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(iconPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addContainerGap());
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addComponent(iconPanel, GroupLayout.Alignment.TRAILING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(contentPanel, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addContainerGap());
+ } else {
+ layout.setHorizontalGroup(layout.createSequentialGroup()
+ // left border
+ .addContainerGap()
+ .addComponent(contentPanel)
+ .addContainerGap());
+ layout.setVerticalGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(contentPanel)
+ .addContainerGap());
+ }
+ }
+ });
+ } catch (Exception ex) {
+ throw new RuntimeException("Failed to init GUI: " + ex.getMessage());
+ }
+ }
+
+ protected void initIconPanel(URL background) {
+ if (background == null) {
+ background = getClass().getResource(DEFAULT_ICON);
+ }
+ if ("file".equals(background.getProtocol())) {
+ log.warn("file:// background images not permitted: " + background +
+ ", loading default background");
+ background = getClass().getResource(DEFAULT_ICON);
+ }
+ log.debug("loading icon panel background " + background);
+
+ iconPanel = new JPanel();
+ JLabel iconLabel = new JLabel();
+ iconLabel.setIcon(new ImageIcon(background));
+
+ GroupLayout iconPanelLayout = new GroupLayout(iconPanel);
+ iconPanel.setLayout(iconPanelLayout);
+ iconPanelLayout.setHorizontalGroup(
+ iconPanelLayout.createSequentialGroup()
+ .addComponent(iconLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE));
+ iconPanelLayout.setVerticalGroup(
+ iconPanelLayout.createSequentialGroup()
+ .addComponent(iconLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE));
+ }
+
+ protected void initContentPanel(URL background) {
+
+ if (background == null) {
+ log.debug("no background image set");
+// contentPanel = new ImagePanel(getClass().getResource(DEFAULT_BACKGROUND));
+ contentPanel = new JPanel();
+ } else if ("file".equals(background.getProtocol())) {
+ log.warn("file:// background images not permitted: " + background);
+ contentPanel = new JPanel();
+ } else {
+ log.debug("loading background " + background);
+ contentPanel = new ImagePanel(background);
+ }
+ contentPanel.setOpaque(false);
+ mainPanel = new JPanel();
+ mainPanel.setOpaque(false);
+ buttonPanel = new JPanel();
+ buttonPanel.setOpaque(false);
+
+ helpLabel = new JLabel();
+ helpLabel.setIcon(new ImageIcon(getClass().getResource(HELP_IMG)));
+ helpLabel.getAccessibleContext().setAccessibleName(getMessage(ALT_HELP));
+ helpLabel.setFocusable(true);
+ helpLabel.addMouseListener(helpMouseListener);
+ helpLabel.addKeyListener(helpKeyListener);
+ helpLabel.addFocusListener(new FocusAdapter() {
+
+ @Override
+ public void focusGained(FocusEvent e) {
+
+ helpLabel.setIcon(new ImageIcon(getClass().getResource(HELP_IMG_FOCUS)));
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+
+ helpLabel.setIcon(new ImageIcon(getClass().getResource(HELP_IMG)));
+ }
+
+
+ });
+ helpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+
+ switchFocusDummyLabel = new JLabel();
+ switchFocusDummyLabel.setText("");
+ switchFocusDummyLabel.setFocusable(true);
+ switchFocusDummyLabel.addFocusListener(switchFocusKeyListener);
+
+ buttonSize = initButtonSize();
+
+ if (renderHeaderPanel) {
+ headerPanel = new JPanel();
+ headerPanel.setOpaque(false);
+
+ titleLabel = new JLabel();
+ titleLabel.setFont(titleLabel.getFont().deriveFont(titleLabel.getFont().getStyle() |
+ java.awt.Font.BOLD, titleLabel.getFont().getSize() + 2));
+
+ GroupLayout headerPanelLayout = new GroupLayout(headerPanel);
+ headerPanel.setLayout(headerPanelLayout);
+
+ headerPanelLayout.setHorizontalGroup(
+ headerPanelLayout.createSequentialGroup()
+ .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ );
+ headerPanelLayout.setVerticalGroup(
+ headerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addComponent(titleLabel, 0, GroupLayout.PREFERRED_SIZE, Short.MAX_VALUE)
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ );
+ }
+
+ GroupLayout contentPanelLayout = new GroupLayout(contentPanel);
+ contentPanel.setLayout(contentPanelLayout);
+
+ // align header, main and button to the right
+ GroupLayout.ParallelGroup horizontalContent =
+ contentPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING); //LEADING);
+ GroupLayout.SequentialGroup verticalContent =
+ contentPanelLayout.createSequentialGroup();
+
+ if (renderHeaderPanel) {
+ horizontalContent
+ .addComponent(headerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE);
+ verticalContent
+ .addComponent(headerPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED);
+
+ }
+ horizontalContent
+ .addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE); //Short.MAX_VALUE);
+ verticalContent
+ .addComponent(mainPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
+ .addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);
+
+ contentPanelLayout.setHorizontalGroup(horizontalContent); //Outer);
+ contentPanelLayout.setVerticalGroup(verticalContent);
+ }
+
+ /**
+ * BKUWorker inits signaturecard with locale
+ * @return
+ */
+ @Override
+ public Locale getLocale() {
+ return messages.getLocale();
+ }
+
+ /**
+ * to be overridden by subclasses providing additional resource messages
+ * @param key
+ * @return
+ */
+ protected String getMessage(String key) {
+ return messages.getString(key);
+ }
+
+ /**
+ * to be overridden by subclasses providing additional resource messages
+ * @param key
+ * @return
+ */
+ protected boolean hasMessage(String key) {
+ return messages.containsKey(key);
+ }
+
+ @Override
+ public void showVerifyPINDialog(final PINSpec pinSpec, final int numRetries,
+ final ActionListener okListener, final String okCommand,
+ final ActionListener cancelListener, final String cancelCommand) {
+
+ log.debug("scheduling verify pin dialog");
+
+ SwingUtilities.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+
+ log.debug("[" + Thread.currentThread().getName() + "] show verify pin dialog");
+
+ mainPanel.removeAll();
+ buttonPanel.removeAll();
+
+ if (renderHeaderPanel) {
+ if (numRetries < 0) {
+ String verifyTitle = getMessage(TITLE_VERIFY_PIN);
+ titleLabel.setText(MessageFormat.format(verifyTitle, new Object[]{pinSpec.getLocalizedName()}));
+ } else {
+ titleLabel.setText(getMessage(TITLE_RETRY));
+ }
+ }
+
+ JButton okButton = new JButton();
+ okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD));
+ okButton.setText(getMessage(BUTTON_OK));
+ okButton.setEnabled(pinSpec.getMinLength() <= 0);
+ okButton.setActionCommand(okCommand);
+ okButton.addActionListener(okListener);
+
+ JLabel cardPinLabel = new JLabel();
+ cardPinLabel.setFont(cardPinLabel.getFont().deriveFont(cardPinLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
+ String pinLabel = getMessage(LABEL_PIN);
+ cardPinLabel.setText(MessageFormat.format(pinLabel, new Object[]{pinSpec.getLocalizedName()}));
+
+ pinField = new JPasswordField();
+ pinField.setText("");
+ pinField.setDocument(new PINDocument(pinSpec.getMinLength(), pinSpec.getMaxLength(), pinSpec.getRexepPattern(), okButton));
+ pinField.setActionCommand(okCommand);
+ pinField.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (pinField.getPassword().length >= pinSpec.getMinLength()) {
+ okListener.actionPerformed(e);
+ }
+ }
+ });
+
+ JLabel infoLabel = new JLabel();
+ if (numRetries < 0) {
+ infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
+ String infoPattern = getMessage(MESSAGE_ENTERPIN);
+ if (shortText) {
+ infoLabel.setText(MessageFormat.format(infoPattern, new Object[] {"PIN"}));
+ } else {
+ infoLabel.setText(MessageFormat.format(infoPattern, new Object[] {pinSpec.getLocalizedName()}));
+ }
+ helpMouseListener.setHelpTopic(HELP_VERIFY_PIN);
+ helpKeyListener.setHelpTopic(HELP_VERIFY_PIN);
+ } else {
+ String retryPattern;
+ if (numRetries < 2) {
+ retryPattern = getMessage(MESSAGE_LAST_RETRY);
+ } else {
+ retryPattern = getMessage(MESSAGE_RETRIES);
+ }
+ infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD));
+ infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)}));
+ infoLabel.setForeground(ERROR_COLOR);
+ helpMouseListener.setHelpTopic(HELP_RETRY);
+ helpKeyListener.setHelpTopic(HELP_RETRY);
+ }
+
+ JLabel pinsizeLabel = new JLabel();
+ pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~java.awt.Font.BOLD, pinsizeLabel.getFont().getSize()-2));
+ pinsizeLabel.setText(MessageFormat.format(getMessage(LABEL_PINSIZE), pinSpec.getLocalizedLength()));
+
+ GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
+ mainPanel.setLayout(mainPanelLayout);
+
+ GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup()
+ .addComponent(infoLabel);
+ GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addComponent(infoLabel);
+
+ if (!renderHeaderPanel) {
+ infoHorizontal
+ .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ ;
+ infoVertical
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ ;
+ }
+
+ // align pinfield and pinsize to the right
+ GroupLayout.ParallelGroup pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING);
+ GroupLayout.Group pinVertical;
+
+ if (pinLabelPos == PinLabelPosition.ABOVE) {
+ pinHorizontal
+ .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addComponent(cardPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+ .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);
+ pinVertical = mainPanelLayout.createSequentialGroup()
+ .addComponent(cardPinLabel)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);
+ } else {
+ pinHorizontal
+ .addGroup(mainPanelLayout.createSequentialGroup()
+ .addComponent(cardPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);
+ pinVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(cardPinLabel)
+ .addComponent(pinField);
+ }
+
+ mainPanelLayout.setHorizontalGroup(
+ mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addGroup(infoHorizontal)
+ .addGroup(pinHorizontal));
+
+ mainPanelLayout.setVerticalGroup(
+ mainPanelLayout.createSequentialGroup()
+ .addGroup(infoVertical)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(pinVertical)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pinsizeLabel));
+
+
+ GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel);
+ buttonPanel.setLayout(buttonPanelLayout);
+
+ GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup()
+ .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE);
+ GroupLayout.Group buttonVertical;
+
+ if (renderCancelButton) {
+ JButton cancelButton = new JButton();
+ cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD));
+ cancelButton.setText(getMessage(BUTTON_CANCEL));
+ cancelButton.setActionCommand(cancelCommand);
+ cancelButton.addActionListener(cancelListener);
+
+ buttonHorizontal
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE);
+ buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(okButton)
+ .addComponent(cancelButton);
+ } else {
+ buttonVertical = buttonPanelLayout.createSequentialGroup()
+ .addComponent(okButton);
+ }
+
+ buttonPanelLayout.setHorizontalGroup(buttonHorizontal);
+ buttonPanelLayout.setVerticalGroup(buttonVertical);
+
+// pinField.requestFocusInWindow();
+// helpLabel.requestFocus();
+ pinField.requestFocus();
+ contentPanel.validate();
+
+ }
+ });
+ }
+
+ @Override
+ public void showEnterPINDirect(PINSpec pinSpec, int retries) {
+ if (retries < 0) {
+ showMessageDialog(TITLE_VERIFY_PINPAD, MESSAGE_ENTERPIN_PINPAD_DIRECT, new Object[] {
+ pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() });
+ } else {
+ showMessageDialog(TITLE_RETRY, MESSAGE_RETRIES, new Object[]{String.valueOf(retries) });
+ }
+ }
+
+ @Override
+ public void showEnterPIN(final PINSpec pinSpec, final int retries) {
+ showEnterPIN(pinSpec, retries, TITLE_VERIFY_PINPAD, MESSAGE_ENTERPIN_PINPAD, null);
+ }
+
+ protected void showEnterPIN(final PINSpec pinSpec, final int retries, final String titleKey, final String messageKey, final Object[] messageParams) {
+ log.debug("scheduling pinpad dialog");
+
+ SwingUtilities.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+
+ log.debug("[" + Thread.currentThread().getName() + "] show pinpad dialog");
+
+ mainPanel.removeAll();
+ buttonPanel.removeAll();
+
+ if (renderHeaderPanel) {
+ if (retries < 0) {
+ titleLabel.setText(getMessage(titleKey));
+ } else {
+ titleLabel.setText(getMessage(TITLE_RETRY));
+ }
+ }
+
+ final JLabel infoLabel = new JLabel();
+ if (retries < 0) {
+ infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
+ infoLabel.setText(MessageFormat.format(getMessage(messageKey), messageParams));
+ helpMouseListener.setHelpTopic(HELP_PINPAD);
+ helpKeyListener.setHelpTopic(HELP_PINPAD);
+ } else {
+ String retryPattern;
+ if (retries == 1) {
+ retryPattern = getMessage(MESSAGE_LAST_RETRY);
+ } else {
+ retryPattern = getMessage(MESSAGE_RETRIES);
+ }
+ infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(retries)}));
+ infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD));
+ infoLabel.setForeground(ERROR_COLOR);
+ helpMouseListener.setHelpTopic(HELP_RETRY);
+ helpKeyListener.setHelpTopic(HELP_RETRY);
+ }
+
+ JLabel pinLabel = new JLabel();
+ pinLabel.setFont(pinLabel.getFont().deriveFont(pinLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
+ String pinName = getMessage(LABEL_PIN);
+ pinLabel.setText(MessageFormat.format(pinName, new Object[]{pinSpec.getLocalizedName()}));
+
+ JPasswordField pinpadPINField = new JPasswordField();
+ pinpadPINField.setText("");
+ pinpadPINField.setEnabled(false);
+ pinpadPIN = pinpadPINField.getDocument();
+
+ JLabel pinsizeLabel = new JLabel();
+ pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~java.awt.Font.BOLD, pinsizeLabel.getFont().getSize()-2));
+ pinsizeLabel.setText(MessageFormat.format(getMessage(LABEL_PINSIZE), pinSpec.getLocalizedLength()));
+
+ GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
+ mainPanel.setLayout(mainPanelLayout);
+
+ GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup()
+ .addComponent(infoLabel);
+ GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addComponent(infoLabel);
+
+ if (!renderHeaderPanel) {
+ infoHorizontal
+ .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ ;
+ infoVertical
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ ;
+ }
+
+ // align pinfield and pinsize to the right
+ GroupLayout.Group pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING);
+ GroupLayout.SequentialGroup pinVertical = mainPanelLayout.createSequentialGroup();
+
+ if (pinLabelPos == PinLabelPosition.ABOVE) {
+ pinHorizontal
+ .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+ .addComponent(pinpadPINField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);
+ pinVertical
+ .addComponent(pinLabel)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pinpadPINField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pinsizeLabel);
+ } else { // PinLabelPosition.LEFT
+ pinHorizontal
+ .addGroup(mainPanelLayout.createSequentialGroup()
+ .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pinpadPINField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);
+ pinVertical
+ .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(pinLabel)
+ .addComponent(pinpadPINField))
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pinsizeLabel);
+ }
+
+ mainPanelLayout.setHorizontalGroup(
+ mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addGroup(infoHorizontal)
+ .addGroup(pinHorizontal));
+
+ mainPanelLayout.setVerticalGroup(
+ mainPanelLayout.createSequentialGroup()
+ .addGroup(infoVertical)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(pinVertical));
+
+ contentPanel.validate();
+ }
+ });
+ }
+
+ @Override
+ public void showSignatureDataDialog(PINSpec spec,
+ final ActionListener enterPINListener, final String enterPINCommand,
+ final ActionListener cancelListener, final String cancelCommand,
+ final ActionListener hashdataListener, final String hashdataCommand) {
+
+ log.debug("scheduling signature-data dialog");
+
+ SwingUtilities.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+
+ log.debug("[" + Thread.currentThread().getName() + "] show signature-data dialog");
+
+ mainPanel.removeAll();
+ buttonPanel.removeAll();
+
+ if (renderHeaderPanel) {
+ titleLabel.setText(getMessage(TITLE_SIGNATURE_DATA));
+ }
+
+ final JLabel infoLabel = new JLabel();
+ infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
+ if (shortText) {
+ infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY));
+ } else {
+ infoLabel.setText(getMessage(MESSAGE_HASHDATALINK));
+ }
+ infoLabel.setFocusable(true);
+ infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ infoLabel.setForeground(HYPERLINK_COLOR);
+ infoLabel.addMouseListener(new MouseAdapter() {
+
+ @Override
+ public void mouseClicked(MouseEvent me) {
+ ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand);
+ hashdataListener.actionPerformed(e);
+ }
+ });
+
+ infoLabel.addKeyListener(new KeyAdapter() {
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+
+ if(e.getKeyCode() == KeyEvent.VK_ENTER) {
+ ActionEvent e1 = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand);
+ hashdataListener.actionPerformed(e1);
+ }
+ }
+
+ });
+
+ infoLabel.addFocusListener(new FocusAdapter() {
+
+ @Override
+ public void focusGained(FocusEvent e) {
+
+ if (shortText) {
+ infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY_FOCUS));
+ } else {
+ infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_FOCUS));
+ }
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+
+ if (shortText) {
+ infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY));
+ } else {
+ infoLabel.setText(getMessage(MESSAGE_HASHDATALINK));
+ }
+
+ }
+
+ });
+
+ helpMouseListener.setHelpTopic(HELP_SIGNPIN);
+ helpKeyListener.setHelpTopic(HELP_SIGNPIN);
+
+ //TODO message panel
+
+// String msgPattern = getMessage(MESSAGE_ENTERPIN_PINPAD);
+// String msg = MessageFormat.format(msgPattern, new Object[] {
+// pinSpec.getLocalizedName(), pinSpec.getLocalizedLength() });
+//
+// JLabel msgLabel = new JLabel();
+// msgLabel.setFont(msgLabel.getFont().deriveFont(msgLabel.getFont().getStyle() & ~Font.BOLD));
+// msgLabel.setText(msg);
+
+ GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
+ mainPanel.setLayout(mainPanelLayout);
+
+ GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup()
+ .addComponent(infoLabel);
+ GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addComponent(infoLabel);
+
+ if (!renderHeaderPanel) {
+ infoHorizontal
+ .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ ;
+ infoVertical
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ ;
+ }
+
+ mainPanelLayout.setHorizontalGroup(
+ infoHorizontal);
+// mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+// .addGroup(infoHorizontal)
+// .addComponent(msgLabel));
+
+ mainPanelLayout.setVerticalGroup(
+ infoVertical);
+// mainPanelLayout.createSequentialGroup()
+// .addGroup(infoVertical)
+// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+// .addComponent(msgLabel));
+
+
+ GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel);
+ buttonPanel.setLayout(buttonPanelLayout);
+
+ GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup();
+ GroupLayout.Group buttonVertical;
+
+ JButton enterPINButton = new JButton();
+ enterPINButton.setFont(enterPINButton.getFont().deriveFont(enterPINButton.getFont().getStyle() & ~java.awt.Font.BOLD));
+ enterPINButton.setText(getMessage(BUTTON_SIGN));
+ enterPINButton.setActionCommand(enterPINCommand);
+ enterPINButton.addActionListener(enterPINListener);
+
+ if (renderCancelButton) {
+ JButton cancelButton = new JButton();
+ cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD));
+ cancelButton.setText(getMessage(BUTTON_CANCEL));
+ cancelButton.setActionCommand(cancelCommand);
+ cancelButton.addActionListener(cancelListener);
+
+ buttonHorizontal
+ .addComponent(enterPINButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)
+ ;
+ buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(enterPINButton)
+ .addComponent(cancelButton)
+ ;
+ } else {
+ buttonHorizontal
+ .addComponent(enterPINButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)
+ ;
+ buttonVertical = buttonPanelLayout.createSequentialGroup()
+ .addComponent(enterPINButton)
+ ;
+ }
+
+ buttonPanelLayout.setHorizontalGroup(buttonHorizontal);
+ buttonPanelLayout.setVerticalGroup(buttonVertical);
+
+ contentPanel.validate();
+ }
+ });
+ }
+
+ @Override
+ public void correctionButtonPressed() {
+ log.debug("[" + Thread.currentThread().getName() + "] correction button pressed");
+
+ if (pinpadPIN != null) {
+ try {
+ pinpadPIN.remove(0, 1);
+ } catch (BadLocationException ex) {
+ }
+ }
+ }
+
+ @Override
+ public void allKeysCleared() {
+ log.debug("[" + Thread.currentThread().getName() + "] all keys cleared");
+
+ if (pinpadPIN != null) {
+ try {
+ pinpadPIN.remove(0, pinpadPIN.getLength());
+ } catch (BadLocationException ex) {
+ }
+ }
+ }
+
+ @Override
+ public void validKeyPressed() {
+ log.debug("[" + Thread.currentThread().getName() + "] valid key pressed");
+
+ if (pinpadPIN != null) {
+ try {
+ pinpadPIN.insertString(0, "*", null);
+ } catch (BadLocationException ex) {
+ }
+ }
+ }
+
+ @Override
+ public void showSignaturePINDialog(final PINSpec pinSpec, final int numRetries,
+ final ActionListener signListener, final String signCommand,
+ final ActionListener cancelListener, final String cancelCommand,
+ final ActionListener hashdataListener, final String hashdataCommand) {
+
+ log.debug("scheduling signature-pin dialog");
+
+ SwingUtilities.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+
+ log.debug("[" + Thread.currentThread().getName() + "] show signature-pin dialog");
+
+ mainPanel.removeAll();
+ buttonPanel.removeAll();
+
+ if (renderHeaderPanel) {
+ if (numRetries < 0) {
+ titleLabel.setText(getMessage(TITLE_SIGN));
+ } else {
+ titleLabel.setText(getMessage(TITLE_RETRY));
+ }
+ }
+
+ final JLabel infoLabel = new JLabel();
+ if (numRetries < 0) {
+ infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
+ if (shortText) {
+ infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY));
+ } else {
+ infoLabel.setText(getMessage(MESSAGE_HASHDATALINK));
+ }
+ infoLabel.setFocusable(true);
+ infoLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ infoLabel.setForeground(HYPERLINK_COLOR);
+ infoLabel.addMouseListener(new MouseAdapter() {
+
+ @Override
+ public void mouseClicked(MouseEvent me) {
+ ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand);
+ hashdataListener.actionPerformed(e);
+ }
+ });
+
+ infoLabel.addKeyListener(new KeyAdapter() {
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+
+ if(e.getKeyCode() == KeyEvent.VK_ENTER) {
+ ActionEvent e1 = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, hashdataCommand);
+ hashdataListener.actionPerformed(e1);
+ }
+ }
+
+ });
+
+ infoLabel.addFocusListener(new FocusAdapter() {
+
+ @Override
+ public void focusGained(FocusEvent e) {
+
+
+ if (shortText) {
+ infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY_FOCUS));
+ } else {
+ infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_FOCUS));
+ }
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+
+
+ if (shortText) {
+ infoLabel.setText(getMessage(MESSAGE_HASHDATALINK_TINY));
+ } else {
+ infoLabel.setText(getMessage(MESSAGE_HASHDATALINK));
+ }
+
+ }
+
+ });
+
+ helpMouseListener.setHelpTopic(HELP_SIGNPIN);
+ helpKeyListener.setHelpTopic(HELP_SIGNPIN);
+ } else {
+ String retryPattern;
+ if (numRetries < 2) {
+ retryPattern = getMessage(MESSAGE_LAST_RETRY);
+ } else {
+ retryPattern = getMessage(MESSAGE_RETRIES);
+ }
+ infoLabel.setFocusable(true);
+ infoLabel.setText(MessageFormat.format(retryPattern, new Object[]{String.valueOf(numRetries)}));
+ infoLabel.setFont(infoLabel.getFont().deriveFont(infoLabel.getFont().getStyle() | java.awt.Font.BOLD));
+ infoLabel.setForeground(ERROR_COLOR);
+ helpMouseListener.setHelpTopic(HELP_RETRY);
+ helpKeyListener.setHelpTopic(HELP_RETRY);
+ }
+
+ JButton signButton = new JButton();
+ signButton.setFont(signButton.getFont().deriveFont(signButton.getFont().getStyle() & ~java.awt.Font.BOLD));
+ signButton.setText(getMessage(BUTTON_SIGN));
+ signButton.setEnabled(pinSpec.getMinLength() <= 0);
+ signButton.setActionCommand(signCommand);
+ signButton.addActionListener(signListener);
+
+ JLabel signPinLabel = new JLabel();
+ signPinLabel.setFont(signPinLabel.getFont().deriveFont(signPinLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
+ String pinLabel = getMessage(LABEL_PIN);
+ signPinLabel.setText(MessageFormat.format(pinLabel, new Object[]{pinSpec.getLocalizedName()}));
+
+ pinField = new JPasswordField();
+ pinField.setText("");
+ pinField.setDocument(new PINDocument(pinSpec.getMinLength(), pinSpec.getMaxLength(), pinSpec.getRexepPattern(), signButton));
+ pinField.setActionCommand(signCommand);
+ pinField.addActionListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (pinField.getPassword().length >= pinSpec.getMinLength()) {
+ signListener.actionPerformed(e);
+ }
+ }
+ });
+
+
+ JLabel pinsizeLabel = new JLabel();
+ pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~java.awt.Font.BOLD, pinsizeLabel.getFont().getSize()-2));
+ pinsizeLabel.setText(MessageFormat.format(getMessage(LABEL_PINSIZE), pinSpec.getLocalizedLength()));
+
+ GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
+ mainPanel.setLayout(mainPanelLayout);
+
+ GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup()
+ .addComponent(infoLabel);
+ GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addComponent(infoLabel);
+
+ if (!renderHeaderPanel) {
+ infoHorizontal
+ .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ ;
+ infoVertical
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ ;
+ }
+
+ // align pinfield and pinsize to the right
+ GroupLayout.Group pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.TRAILING);
+ GroupLayout.SequentialGroup pinVertical = mainPanelLayout.createSequentialGroup();
+
+ if (pinLabelPos == PinLabelPosition.ABOVE) {
+ pinHorizontal
+ .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addComponent(signPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+ .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);
+ pinVertical
+ .addComponent(signPinLabel)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pinsizeLabel);
+ } else { // PinLabelPosition.LEFT
+ pinHorizontal
+ .addGroup(mainPanelLayout.createSequentialGroup()
+ .addComponent(signPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);
+ pinVertical
+ .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(signPinLabel)
+ .addComponent(pinField))
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(pinsizeLabel);
+ }
+
+ mainPanelLayout.setHorizontalGroup(
+ mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addGroup(infoHorizontal)
+ .addGroup(pinHorizontal));
+
+ mainPanelLayout.setVerticalGroup(
+ mainPanelLayout.createSequentialGroup()
+ .addGroup(infoVertical)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(pinVertical));
+
+ GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel);
+ buttonPanel.setLayout(buttonPanelLayout);
+
+ GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup();
+ GroupLayout.Group buttonVertical;
+
+ if (renderCancelButton) {
+ JButton cancelButton = new JButton();
+ cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD));
+ cancelButton.setText(getMessage(BUTTON_CANCEL));
+ cancelButton.setActionCommand(cancelCommand);
+ cancelButton.addActionListener(cancelListener);
+
+ buttonHorizontal
+ .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)
+ ;
+ buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)
+ .addComponent(signButton)
+ .addComponent(cancelButton)
+ ;
+ } else {
+ buttonHorizontal
+ .addComponent(signButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)
+ ;
+ buttonVertical = buttonPanelLayout.createSequentialGroup()
+ .addComponent(signButton)
+ ;
+ }
+
+ buttonPanelLayout.setHorizontalGroup(buttonHorizontal);
+ buttonPanelLayout.setVerticalGroup(buttonVertical);
+
+// pinField.requestFocusInWindow();
+// helpLabel.requestFocus();
+ pinField.requestFocus();
+ contentPanel.validate();
+
+ }
+ });
+ }
+
+ @Override
+ public void showErrorDialog(
+ final String errorMsgKey, final Object[] errorMsgParams,
+ final ActionListener okListener, final String okCommand) {
+
+ showMessageDialog(TITLE_ERROR, ERROR_COLOR,
+ errorMsgKey, errorMsgParams, BUTTON_OK, okListener, okCommand);
+ }
+
+ @Override
+ public void showErrorDialog(
+ final String errorMsgKey, final Object[] errorMsgParams) {
+
+ showMessageDialog(TITLE_ERROR, ERROR_COLOR,
+ errorMsgKey, errorMsgParams, null, null, null);
+ }
+
+ @Override
+ public void showMessageDialog(
+ final String titleKey,
+ final String msgKey, final Object[] msgParams,
+ final String buttonKey,
+ final ActionListener okListener, final String okCommand) {
+
+ showMessageDialog(titleKey, null,
+ msgKey, msgParams, buttonKey, okListener, okCommand);
+ }
+
+ @Override
+ public void showMessageDialog(
+ final String titleKey,
+ final String msgKey, final Object[] msgParams) {
+
+ showMessageDialog(titleKey, null,
+ msgKey, msgParams, null, null, null);
+ }
+
+ @Override
+ public void showMessageDialog(
+ final String titleKey, final String msgKey) {
+
+ showMessageDialog(titleKey, null,
+ msgKey, null, null, null, null);
+ }
+
+ /**
+ *
+ * @param buttonKey if null defaults to BUTTON_OK
+ */
+ private void showMessageDialog(
+ final String titleKey, final Color titleColor,
+ final String msgKey, final Object[] msgParams,
+ final String buttonKey,
+ final ActionListener okListener, final String okCommand) {
+
+ log.debug("scheduling message dialog");
+
+ SwingUtilities.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+
+ log.debug("[" + Thread.currentThread().getName() + "] show message dialog");
+
+ mainPanel.removeAll();
+ buttonPanel.removeAll();
+
+ if (renderHeaderPanel) {
+ titleLabel.setText(getMessage(titleKey));
+ }
+
+ helpMouseListener.setHelpTopic(msgKey);
+ helpKeyListener.setHelpTopic(msgKey);
+
+ String msgPattern = getMessage(msgKey);
+ String msg = MessageFormat.format(msgPattern, msgParams);
+
+ JLabel msgLabel = new JLabel();
+ msgLabel.setFont(msgLabel.getFont().deriveFont(msgLabel.getFont().getStyle() & ~Font.BOLD));
+ msgLabel.setText(msg);
+
+ GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
+ mainPanel.setLayout(mainPanelLayout);
+
+ GroupLayout.ParallelGroup mainHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING);
+ GroupLayout.SequentialGroup mainVertical = mainPanelLayout.createSequentialGroup();
+
+ log.debug("focus to contentPanel");
+ contentPanel.requestFocus();
+
+ if (!renderHeaderPanel) {
+ JLabel titleLabel = new JLabel();
+ titleLabel.setFont(titleLabel.getFont().deriveFont(titleLabel.getFont().getStyle() | Font.BOLD));
+ titleLabel.setText(getMessage(titleKey));
+ if (titleColor != null) {
+ titleLabel.setForeground(titleColor);
+ }
+
+ mainHorizontal
+ .addGroup(mainPanelLayout.createSequentialGroup()
+ .addComponent(titleLabel)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ );
+ mainVertical
+ .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addComponent(titleLabel)
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ );
+
+ log.debug("focus to helpLabel");
+ helpLabel.requestFocus();
+ }
+
+ mainPanelLayout.setHorizontalGroup(mainHorizontal
+ .addComponent(msgLabel));
+ mainPanelLayout.setVerticalGroup(mainVertical
+ .addComponent(msgLabel));
+
+ if (okListener != null) {
+
+ JButton okButton = new JButton();
+ okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD));
+ okButton.setText(getMessage((buttonKey != null) ? buttonKey : BUTTON_OK));
+ okButton.setActionCommand(okCommand);
+ okButton.addActionListener(okListener);
+
+ GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel);
+ buttonPanel.setLayout(buttonPanelLayout);
+
+ buttonPanelLayout.setHorizontalGroup(
+ buttonPanelLayout.createSequentialGroup()
+ .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE));
+ buttonPanelLayout.setVerticalGroup(
+ buttonPanelLayout.createSequentialGroup()
+ .addComponent(okButton));
+
+ log.debug("focus to ok-button");
+ okButton.requestFocus();
+ }
+
+ contentPanel.validate();
+ }
+ });
+ }
+
+
+ @Override
+ public char[] getPin() {
+ if (pinField != null) {
+ char[] pin = pinField.getPassword(); //returns a copy
+ pinField = null; //garbage collect original pin (make sure to clear char[] after use)
+ return pin;
+ }
+ return null;
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // SECURE VIEWER
+ ////////////////////////////////////////////////////////////////////////////
+
+
+ /**
+ * @param signedReferences
+ * @param backListener gets notified if pin-dialog has to be redrawn
+ * (signedRefencesList returns via BACK button)
+ * @param okCommand
+ */
+ @Override
+ public void showSecureViewer(final List<HashDataInput> dataToBeSigned,
+ final ActionListener backListener, final String backCommand) {
+
+ if (dataToBeSigned == null) {
+ showErrorDialog(getMessage(ERR_NO_HASHDATA),
+ new Object[] {"no signature data provided"},
+ backListener, backCommand);
+ } else if (dataToBeSigned.size() == 1) {
+ //TODO pull out (see also SignedReferencesSelectionListener)
+ if (SecureViewerDialog.SUPPORTED_MIME_TYPES.contains(dataToBeSigned.get(0).getMimeType())) {
+ try {
+ log.debug("[" + Thread.currentThread().getName() + "] scheduling secure viewer");
+
+ SwingUtilities.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_HASHDATA_VIEWER);
+ showSecureViewer(dataToBeSigned.get(0), backListener, backCommand);
+ } catch (FontProviderException ex) {
+ log.error("failed to display secure viewer", ex);
+ showErrorDialog(ERR_VIEWER, new Object[] {ex.getMessage()}, backListener, backCommand);
+ }
+ }
+ });
+
+ } catch (Exception ex) { //InterruptedException InvocationTargetException
+ log.error("Failed to display secure viewer: " + ex.getMessage());
+ log.trace(ex);
+ showErrorDialog(ERR_UNKNOWN, null, backListener, backCommand);
+ }
+ } else {
+ log.debug("[" + Thread.currentThread().getName() + "] mime-type not supported by secure viewer, scheduling save dialog");
+ showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_UNSUPPORTED_MIMETYPE);
+ SecureViewerSaveDialog.showSaveDialog(dataToBeSigned.get(0), messages, backListener, backCommand);
+ }
+ } else {
+ showSignedReferencesListDialog(dataToBeSigned, backListener, backCommand);
+ }
+ }
+
+ /**
+ * has to be called from event dispatcher thread
+ */
+ private void showSecureViewer(HashDataInput dataToBeSigned, ActionListener closeListener, String closeCommand) throws FontProviderException {
+
+ log.debug("[" + Thread.currentThread().getName() + "] show secure viewer");
+ SecureViewerDialog secureViewer = new SecureViewerDialog(null, messages,
+ closeListener, closeCommand,
+ fontProvider, helpMouseListener.getActionListener());
+
+ // workaround for [#439]
+ // avoid AlwaysOnTop at least in applet, otherwise make secureViewer AlwaysOnTop since MOCCA Dialog (JFrame created in LocalSTALFactory) is always on top.
+ Window window = SwingUtilities.getWindowAncestor(contentPane);
+ if (window != null && window.isAlwaysOnTop()) {
+ log.debug("make secureViewer alwaysOnTop");
+ secureViewer.setAlwaysOnTop(true);
+ }
+ secureViewer.setContent(dataToBeSigned);
+ log.trace("viewer setContent returned");
+ }
+
+
+
+ private void showSignedReferencesListDialog(final List<HashDataInput> signedReferences,
+ final ActionListener backListener, final String backCommand) {
+
+ log.debug("[" + Thread.currentThread().getName() + "] scheduling signed references list dialog");
+
+ SwingUtilities.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+
+ log.debug("[" + Thread.currentThread().getName() + "] show signed references list dialog");
+
+ mainPanel.removeAll();
+ buttonPanel.removeAll();
+
+ if (renderHeaderPanel) {
+ titleLabel.setText(getMessage(TITLE_SIGNATURE_DATA));
+ }
+
+ helpMouseListener.setHelpTopic(HELP_HASHDATALIST);
+ helpKeyListener.setHelpTopic(HELP_HASHDATALIST);
+
+ JLabel refIdLabel = new JLabel();
+ refIdLabel.setFont(refIdLabel.getFont().deriveFont(refIdLabel.getFont().getStyle() & ~java.awt.Font.BOLD));
+ String refIdLabelPattern = getMessage(MESSAGE_HASHDATALIST);
+ refIdLabel.setText(MessageFormat.format(refIdLabelPattern, new Object[]{signedReferences.size()}));
+
+ HashDataTableModel tableModel = new HashDataTableModel(signedReferences, renderRefId);
+ final JTable hashDataTable = new JTable(tableModel);
+ hashDataTable.setDefaultRenderer(HashDataInput.class, new HyperlinkRenderer(renderRefId));
+ hashDataTable.setTableHeader(null);
+
+ hashDataTable.addMouseMotionListener(new SignedReferencesMouseMotionListener(hashDataTable));
+
+ hashDataTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ hashDataTable.getSelectionModel().addListSelectionListener(new SignedReferencesSelectionListener(signedReferences, backListener, backCommand));
+
+ JScrollPane hashDataScrollPane = new JScrollPane(hashDataTable);
+
+ GroupLayout mainPanelLayout = new GroupLayout(mainPanel);
+ mainPanel.setLayout(mainPanelLayout);
+
+ GroupLayout.SequentialGroup messageHorizontal = mainPanelLayout.createSequentialGroup()
+ .addComponent(refIdLabel);
+
+ GroupLayout.ParallelGroup messageVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addComponent(refIdLabel);
+
+ if (!renderHeaderPanel) {
+ messageHorizontal
+ .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE)
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ ;
+ messageVertical
+ .addComponent(switchFocusDummyLabel)
+ .addComponent(helpLabel)
+ ;
+ }
+
+ mainPanelLayout.setHorizontalGroup(
+ mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+ .addGroup(messageHorizontal)
+ .addComponent(hashDataScrollPane, 0, 0, Short.MAX_VALUE));
+
+ mainPanelLayout.setVerticalGroup(
+ mainPanelLayout.createSequentialGroup()
+ .addGroup(messageVertical)
+ .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(hashDataScrollPane, 0, 0, hashDataTable.getPreferredSize().height+3));
+
+ JButton backButton = new JButton();
+ backButton.setFont(backButton.getFont().deriveFont(backButton.getFont().getStyle() & ~java.awt.Font.BOLD));
+ backButton.setText(getMessage(BUTTON_BACK));
+ backButton.setActionCommand(backCommand);
+ backButton.addActionListener(backListener);
+
+ GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel);
+ buttonPanel.setLayout(buttonPanelLayout);
+
+ buttonPanelLayout.setHorizontalGroup(buttonPanelLayout.createSequentialGroup()
+ .addComponent(backButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE));
+ buttonPanelLayout.setVerticalGroup(buttonPanelLayout.createSequentialGroup()
+ .addComponent(backButton));
+
+ contentPanel.validate();
+ }
+ });
+ }
+
+
+
+ /**
+ * not possible to add mouse listener to TableCellRenderer
+ * to change cursor on specific columns only, use table.columnAtPoint(e.getPoint())
+ *
+ */
+ private class SignedReferencesMouseMotionListener extends MouseMotionAdapter {
+
+ JTable hashDataTable;
+
+ public SignedReferencesMouseMotionListener(JTable table) {
+ this.hashDataTable = table;
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+// if (hashDataTable.columnAtPoint(e.getPoint()) == 0) {
+ hashDataTable.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+ }
+ }
+
+ ///////////
+ // SignedReferencesList (TODO pull out)
+
+ public class SignedReferencesSelectionListener implements ListSelectionListener {
+
+ List<HashDataInput> signedReferences;
+ ActionListener backListener;
+ String backCommand;
+
+ public SignedReferencesSelectionListener(List<HashDataInput> signedReferences, ActionListener backListener, String backCommand) {
+ this.signedReferences = signedReferences;
+ this.backListener = backListener;
+ this.backCommand = backCommand;
+ }
+
+ @Override
+ public void valueChanged(ListSelectionEvent event) {
+
+ if (event.getValueIsAdjusting()) {
+ return;
+ }
+
+ ListSelectionModel lsm = (ListSelectionModel) event.getSource();
+ int selectionIdx = lsm.getMinSelectionIndex();
+
+ log.debug("[" + Thread.currentThread().getName() + "] reference " + selectionIdx + " selected");
+
+ if (selectionIdx >= 0) {
+ final HashDataInput selection = signedReferences.get(selectionIdx);
+ final SignedReferencesListDisplayer backToListListener = new SignedReferencesListDisplayer(signedReferences, backListener, backCommand);
+
+ if (SecureViewerDialog.SUPPORTED_MIME_TYPES.contains(selection.getMimeType())) {
+ log.debug("[" + Thread.currentThread().getName() + "] scheduling secure viewer dialog");
+ SwingUtilities.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_HASHDATA_VIEWER);
+ showSecureViewer(selection, backToListListener, null);
+// SecureViewerDialog.showSecureViewer(selection, messages, fontProvider, helpMouseListener.getActionListener(), false);
+ } catch (FontProviderException ex) {
+ log.error("failed to display secure viewer", ex);
+ showErrorDialog(BKUGUIFacade.ERR_VIEWER, new Object[] {ex.getMessage()}, backToListListener, null);
+ }
+
+ }
+ });
+ } else {
+ log.debug("[" + Thread.currentThread().getName() + "] mime-type not supported by secure viewer, scheduling save dialog");
+ showMessageDialog(BKUGUIFacade.TITLE_SIGNATURE_DATA, BKUGUIFacade.MESSAGE_UNSUPPORTED_MIMETYPE);
+ SecureViewerSaveDialog.showSaveDialog(selection, messages, backToListListener, null);
+ }
+ }
+ }
+
+ /**
+ * ActionListener that returns to signed references list
+ */
+ private class SignedReferencesListDisplayer implements ActionListener {
+ List<HashDataInput> sr;
+ ActionListener bl;
+ String bc;
+
+ public SignedReferencesListDisplayer(List<HashDataInput> signedReferences, ActionListener backListener, String backCommand) {
+ sr = signedReferences;
+ bl = backListener;
+ bc = backCommand;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+// log.debug("[" + Thread.currentThread().getName() + "] displaying signed references list");
+ showSignedReferencesListDialog(sr, bl, bc);
+ }
+ }
+ }
+
+
+ ////////////////////////////////////////////////////////////////////////////
+ // UTILITY METHODS
+ ////////////////////////////////////////////////////////////////////////////
+
+ private void registerHelpListener(ActionListener helpListener) {
+ if (helpListener != null) {
+ this.helpMouseListener = new HelpMouseListener(helpListener);
+ this.helpKeyListener = new HelpKeyListener(helpListener);
+ } else {
+ log.error("no help listener provided, will not be able to display help");
+ this.helpMouseListener = new HelpMouseListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.error("no help listener registered (requested help topic: " + e.getActionCommand() + ")");
+ }
+ });
+ this.helpKeyListener = new HelpKeyListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.error("no help listener registered (requested help topic: " + e.getActionCommand() + ")");
+ }
+ });
+ }
+ }
+
+ private void registerSwitchFocusListener(ActionListener switchFocusListener) {
+ if (switchFocusListener != null) {
+ this.switchFocusKeyListener = new SwitchFocusFocusListener(switchFocusListener);
+
+ } else {
+
+ this.switchFocusKeyListener = new SwitchFocusFocusListener(new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.warn("no switch focus listener registered");
+ }
+ });
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // INITIALIZERS (MAY BE OVERRIDDEN BY SUBCLASSES)
+ ////////////////////////////////////////////////////////////////////////////
+
+ /**
+ * Load applet messages bundle. Note that getBundle looks for classes based
+ * on the default Locale before it selects the base class!
+ *
+ * Called from constructor.
+ * Subclasses may override this method to ensure the message bundle is loaded
+ * once initButtonSize (called from constructor as well) is called.
+ * (Only relevant if initButtonSize is overridden as well)
+ * @param locale
+ */
+ protected void loadMessageBundle(Locale locale) {
+ if (locale != null) {
+ // see [#378] Ignoring post parameter 'locale': bundle resolve-order not correct?!
+ Locale lang = new Locale(locale.getLanguage().substring(0, 2));
+ log.debug("loading applet resources for language: " + lang.toString());
+ messages = ResourceBundle.getBundle(MESSAGES_BUNDLE, lang);
+ } else {
+ log.debug("loading default language applet resources");
+ messages = ResourceBundle.getBundle(MESSAGES_BUNDLE);
+ }
+ // how the f*** you know the default Messages.properties is de?!
+ log.debug("applet messages loaded: " + messages.getLocale());
+ }
+
+ protected int initButtonSize() {
+ int bs = 0;
+
+ JButton b = new JButton();
+ b.setText(getMessage(BUTTON_OK));
+ if (b.getPreferredSize().width > bs) {
+ bs = b.getPreferredSize().width;
+ }
+ // need cancel button for message dialog,
+ // even if renderCancelButton == false
+ b.setText(getMessage(BUTTON_CANCEL));
+ if (b.getPreferredSize().width > bs) {
+ bs = b.getPreferredSize().width;
+ }
+ b.setText(getMessage(BUTTON_SIGN));
+ if (b.getPreferredSize().width > bs) {
+ bs = b.getPreferredSize().width;
+ }
+ b.setText(getMessage(BUTTON_BACK));
+ if (b.getPreferredSize().width > bs) {
+ bs = b.getPreferredSize().width;
+ }
+ b.setText(getMessage(BUTTON_SAVE));
+ if (b.getPreferredSize().width > bs) {
+ bs = b.getPreferredSize().width;
+ }
+ return bs;
+ }
+
+ @Override
+ public void getFocusFromBrowser() {
+
+ // This method puts the focus to the helpLabel as this
+ // element is supposed to appear in each dialogue.
+ helpLabel.requestFocus();
+
+ }
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUIcons.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUIcons.java
new file mode 100644
index 00000000..92d6897b
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUIcons.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package at.gv.egiz.bku.gui;
+
+import java.awt.Image;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import javax.imageio.ImageIO;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class BKUIcons {
+
+ protected static final Log log = LogFactory.getLog(BKUIcons.class);
+
+ /** 16x16, 24x24, 32x32, 48x48, 128x128 pixels */
+ public static final ArrayList<Image> icons = new ArrayList<Image>();
+
+ static {
+ String[] iconResources = new String[] {
+ "/at/gv/egiz/bku/gui/chip16.png",
+ "/at/gv/egiz/bku/gui/chip24.png",
+ "/at/gv/egiz/bku/gui/chip32.png",
+ "/at/gv/egiz/bku/gui/chip48.png",
+ "/at/gv/egiz/bku/gui/chip128.png" };
+ for (String ir : iconResources) {
+ URL resource = BKUIcons.class.getResource(ir);
+ if (ir != null) {
+ try {
+ icons.add(ImageIO.read(resource));
+ } catch (IOException ex) {
+ log.warn("failed to load mocca icon " + ir, ex);
+ }
+ }
+ }
+ }
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/DefaultHelpListener.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/DefaultHelpListener.java
new file mode 100644
index 00000000..032c8fe5
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/DefaultHelpListener.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.gui;
+
+import java.applet.AppletContext;
+import java.net.URL;
+import java.util.Locale;
+import javax.swing.SwingUtilities;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class DefaultHelpListener extends AbstractHelpListener {
+
+ /**
+ * applet context to open external links in help pages,
+ * if null, no external links will be opened
+ */
+ protected AppletContext ctx;
+
+ /**
+ *
+ * @param ctx open external links via applet context
+ * @param helpURL
+ * @param locale
+ */
+ public DefaultHelpListener(AppletContext ctx, URL helpURL, Locale locale) {
+ super(helpURL, locale);
+ this.ctx = ctx;
+ }
+
+ /**
+ * external links in help document are not opened
+ * @param helpURL
+ * @param locale
+ */
+ public DefaultHelpListener(URL helpURL, Locale locale) {
+ super(helpURL, locale);
+ this.ctx = null;
+ }
+
+ /**
+ * blocks until help viewer returns (is closed)
+ * @param helpURL
+ * @param helpTopic ignored
+ */
+ @Override
+ public void showDocument(final URL helpURL, final String helpTopic) {
+ log.debug("schedule help dialog");
+
+ SwingUtilities.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+
+ log.debug("show help dialog");
+
+ if (ctx == null) {
+ HelpViewer.showHelpDialog(helpURL, messages);
+ } else {
+ HelpViewer.showHelpDialog(ctx, helpURL, messages);
+ }
+ }
+ });
+ }
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataTableModel.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataTableModel.java
new file mode 100644
index 00000000..70842102
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HashDataTableModel.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.gui;
+
+import at.gv.egiz.stal.HashDataInput;
+import java.util.List;
+import javax.swing.table.DefaultTableModel;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+class HashDataTableModel extends DefaultTableModel {
+
+ protected static final Log log = LogFactory.getLog(HashDataTableModel.class);
+
+ /** HashDataInput in first column, register hyperlinkrenderer only here */
+ protected Class[] types;
+ protected List<HashDataInput> hashDataInputs;
+
+ public HashDataTableModel(List<HashDataInput> hashDataInputs, boolean twoColLayout) {
+ super(0, (twoColLayout) ? 2 : 1);
+ this.hashDataInputs = hashDataInputs;
+
+ if (twoColLayout) {
+ types = new Class[] { HashDataInput.class, String.class };
+ for (HashDataInput hdi : hashDataInputs) {
+ addRow(new Object[] { hdi, hdi.getMimeType() });
+ }
+ } else {
+ types = new Class[] { HashDataInput.class };
+ for (HashDataInput hdi : hashDataInputs) {
+ addRow(new Object[] { hdi });
+ }
+ }
+ }
+
+ @Override
+ public Class getColumnClass(int columnIndex) {
+ return types[columnIndex];
+ }
+
+ @Override
+ public boolean isCellEditable(int rowIndex, int columnIndex) {
+ return false;
+ }
+} \ No newline at end of file
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpKeyListener.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpKeyListener.java
new file mode 100644
index 00000000..4ca20f7e
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpKeyListener.java
@@ -0,0 +1,46 @@
+package at.gv.egiz.bku.gui;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author Thomas Zefferer <thomas.zefferer@iaik.tugraz.at>
+ */
+public class HelpKeyListener extends KeyAdapter {
+
+ protected static final Log log = LogFactory.getLog(HelpKeyListener.class);
+
+ protected ActionListener helpListener;
+ protected String locale;
+ protected String topic;
+
+ public HelpKeyListener(ActionListener externalHelpListener) {
+ super();
+ this.helpListener = externalHelpListener;
+ }
+
+ public void setHelpTopic(String topic) {
+ log.trace("setting help topic: " + topic);
+ this.topic = topic;
+ }
+
+ public ActionListener getActionListener() {
+ return helpListener;
+ }
+
+ @Override
+ public void keyPressed(KeyEvent arg0) {
+
+ if(arg0.getKeyCode() == KeyEvent.VK_ENTER) {
+ ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, topic);
+ helpListener.actionPerformed(e);
+ }
+ }
+
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpLinkFocusManager.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpLinkFocusManager.java
new file mode 100644
index 00000000..f5882b3d
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpLinkFocusManager.java
@@ -0,0 +1,138 @@
+package at.gv.egiz.bku.gui;
+
+import java.awt.Color;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.net.URL;
+
+import javax.accessibility.AccessibleHyperlink;
+import javax.accessibility.AccessibleHypertext;
+import javax.swing.JEditorPane;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.text.DefaultStyledDocument;
+import javax.swing.text.Element;
+import javax.swing.text.MutableAttributeSet;
+import javax.swing.text.SimpleAttributeSet;
+import javax.swing.text.StyleConstants;
+
+/**
+ *
+ * @author Thomas Zefferer <thomas.zefferer@iaik.tugraz.at>
+ */
+public final class HelpLinkFocusManager extends KeyAdapter {
+
+ private static final int FOCUS_UNDEFINED = -1;
+
+ private int focusedHyperlinkIndex = FOCUS_UNDEFINED;
+ private JEditorPane displayPane;
+
+ public HelpLinkFocusManager(JEditorPane displayPane) {
+
+ super();
+ this.displayPane = displayPane;
+ }
+
+ public void keyPressed(KeyEvent e) {
+
+ AccessibleHypertext accessibleHypertext = (AccessibleHypertext) this.displayPane
+ .getAccessibleContext().getAccessibleText();
+
+ if (accessibleHypertext.getLinkCount() > 0) {
+ switch (e.getKeyCode()) {
+
+ case KeyEvent.VK_RIGHT:
+ if (this.focusedHyperlinkIndex != FOCUS_UNDEFINED) {
+ removeHyperlinkFocus();
+ }
+
+ this.focusedHyperlinkIndex++;
+
+ if (this.focusedHyperlinkIndex >= accessibleHypertext
+ .getLinkCount()) {
+
+ this.focusedHyperlinkIndex = 0;
+ }
+
+ setHyperlinkFocus();
+ break;
+
+ case KeyEvent.VK_LEFT:
+ if (this.focusedHyperlinkIndex != FOCUS_UNDEFINED) {
+ removeHyperlinkFocus();
+ }
+
+ this.focusedHyperlinkIndex--;
+
+ if (this.focusedHyperlinkIndex < 0) {
+ this.focusedHyperlinkIndex = accessibleHypertext
+ .getLinkCount() - 1;
+ }
+
+ setHyperlinkFocus();
+ break;
+
+ case KeyEvent.VK_SPACE:
+ case KeyEvent.VK_ENTER:
+
+
+ AccessibleHyperlink link = accessibleHypertext
+ .getLink(this.focusedHyperlinkIndex);
+ if (link != null) {
+ URL url = (URL) link.getAccessibleActionObject(0);
+ Element element = ((DefaultStyledDocument) this.displayPane
+ .getDocument()).getCharacterElement(link
+ .getStartIndex());
+ HyperlinkEvent linkEvent = new HyperlinkEvent(
+ this.displayPane,
+ HyperlinkEvent.EventType.ACTIVATED, url, null,
+ element);
+ this.displayPane.fireHyperlinkUpdate(linkEvent);
+ }
+
+ removeHyperlinkFocus();
+ this.focusedHyperlinkIndex = FOCUS_UNDEFINED;
+ break;
+ default:
+ // nothig to do
+ break;
+ }
+ }
+ }
+
+ private void setHyperlinkFocus() {
+
+ AccessibleHypertext accessibleHypertext = (AccessibleHypertext) this.displayPane
+ .getAccessibleContext().getAccessibleText();
+ AccessibleHyperlink link = accessibleHypertext
+ .getLink(this.focusedHyperlinkIndex);
+
+ if (link != null) {
+
+ MutableAttributeSet style = new SimpleAttributeSet();
+ StyleConstants.setForeground(style, Color.RED);
+ ((DefaultStyledDocument) this.displayPane.getDocument())
+ .setCharacterAttributes(link.getStartIndex(), link
+ .getEndIndex()
+ - link.getStartIndex(), style, false);
+ }
+ }
+
+ private void removeHyperlinkFocus() {
+ Color textColor = Color.BLUE;
+ AccessibleHypertext accessibleHypertext = (AccessibleHypertext) this.displayPane
+ .getAccessibleContext().getAccessibleText();
+ AccessibleHyperlink link = accessibleHypertext
+ .getLink(this.focusedHyperlinkIndex);
+
+ if (link != null) {
+
+ MutableAttributeSet style = new SimpleAttributeSet();
+ StyleConstants.setForeground(style, textColor);
+ ((DefaultStyledDocument) this.displayPane.getDocument())
+ .setCharacterAttributes(link.getStartIndex(), link
+ .getEndIndex()
+ - link.getStartIndex(), style, false);
+ }
+ }
+
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpMouseListener.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpMouseListener.java
new file mode 100644
index 00000000..b7bbe971
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpMouseListener.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package at.gv.egiz.bku.gui;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+public class HelpMouseListener extends MouseAdapter {
+
+ protected static final Log log = LogFactory.getLog(HelpMouseListener.class);
+
+ protected ActionListener helpListener;
+ protected String locale;
+ protected String topic;
+
+ public HelpMouseListener(ActionListener externalHelpListener) {
+ super();
+ this.helpListener = externalHelpListener;
+ }
+
+ public void setHelpTopic(String topic) {
+ log.trace("setting help topic: " + topic);
+ this.topic = topic;
+ }
+
+ public ActionListener getActionListener() {
+ return helpListener;
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent arg0) {
+ ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, topic);
+ helpListener.actionPerformed(e);
+ }
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpViewer.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpViewer.java
new file mode 100644
index 00000000..0f887f78
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HelpViewer.java
@@ -0,0 +1,218 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.gui;
+
+import java.applet.AppletContext;
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.net.URL;
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+import javax.swing.GroupLayout;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JEditorPane;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.LayoutStyle;
+import javax.swing.SwingUtilities;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class HelpViewer extends JDialog
+ implements ActionListener {
+
+ protected static final Log log = LogFactory.getLog(HelpViewer.class);
+ private static HelpViewer dialog;
+ protected ResourceBundle messages;
+ protected AppletContext ctx;
+
+ /**
+ *
+ * @param ctx external links are opened via ctx.showDocument()
+ * @param helpURL
+ * @param helpTopic
+ * @param messages
+ */
+ public static void showHelpDialog(AppletContext ctx,
+ URL helpURL,
+// String helpTopic,
+ ResourceBundle messages) {
+ showHelpDialog(null, ctx, helpURL, messages); //helpTopic, messages);
+ }
+
+ public static void showHelpDialog(URL helpURL,
+// String helpTopic,
+ ResourceBundle messages) {
+ showHelpDialog(null, null, helpURL, messages); // helpTopic, messages);
+ }
+
+ public static void showHelpDialog(Component owner,
+ AppletContext ctx,
+ URL helpURL,
+// String helpTopic,
+ ResourceBundle messages) {
+
+ Frame frame = null;
+ if (owner != null) {
+ JOptionPane.getFrameForComponent(owner);
+ }
+ dialog = new HelpViewer(frame, messages, ctx, helpURL); //, helpTopic);
+ dialog.setVisible(true);
+ dialog.toFront();
+ }
+
+ private HelpViewer(Frame frame,
+ ResourceBundle messages,
+ AppletContext ctx,
+ URL helpURL) { //, String helpTopic) {
+ super(frame, messages.getString(BKUGUIFacade.WINDOWTITLE_HELP), true);
+ this.messages = messages;
+ this.ctx = ctx;
+
+// String p = messages.getString(BKUGUIFacade.MESSAGE_HELP);
+// String helpItem = messages.getString(helpTopic);
+// String viewerLabel = MessageFormat.format(p, new Object[]{helpItem});
+
+ JPanel helpPanel = createViewerPanel(helpURL); //viewerLabel, helpURL);
+ JPanel buttonPanel = createButtonPanel();
+
+ initContentPane(new Dimension(600, 600), helpPanel, buttonPanel);
+ pack();
+ if (frame != null) {
+ setLocationRelativeTo(frame);
+ } else {
+ setLocationByPlatform(true);
+ }
+ }
+
+ private void initContentPane(Dimension preferredSize, JPanel viewerPanel, JPanel buttonPanel) {
+ Container contentPane = getContentPane();
+ contentPane.setPreferredSize(preferredSize);
+
+ GroupLayout mainLayout = new GroupLayout(contentPane);
+ contentPane.setLayout(mainLayout);
+
+ mainLayout.setHorizontalGroup(
+ mainLayout.createSequentialGroup().addContainerGap().addGroup(
+ mainLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(viewerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)).addContainerGap());
+ mainLayout.setVerticalGroup(
+ mainLayout.createSequentialGroup().addContainerGap().addComponent(viewerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED).addComponent(buttonPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addContainerGap());
+ }
+
+ private JPanel createViewerPanel(URL helpURL) { //String viewerLabelText,
+ log.debug("viewer dialog: " + helpURL.toString());
+
+ final JEditorPane viewer = new JEditorPane();
+ viewer.setEditable(false);
+ try {
+ viewer.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+ viewer.setPage(helpURL);
+
+ HelpLinkFocusManager editorFocusManager = new HelpLinkFocusManager (viewer);
+ viewer.addKeyListener(editorFocusManager );
+
+ viewer.addHyperlinkListener(new HyperlinkListener() {
+
+ @Override
+ public void hyperlinkUpdate(HyperlinkEvent e) {
+ final URL url = e.getURL();
+ if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
+ if (ctx != null) {
+ log.debug("open external link in help viewer: " + url);
+ ctx.showDocument(url, "_blank");
+ } else {
+ SwingUtilities.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+ String msgP = messages.getString(BKUGUIFacade.ERR_EXTERNAL_LINK);
+ String msg = MessageFormat.format(msgP, url);
+ String title = messages.getString(BKUGUIFacade.TITLE_ERROR);
+ JOptionPane.showMessageDialog(rootPane, msg, title, JOptionPane.ERROR_MESSAGE);
+ }
+ });
+ }
+ }
+ }
+ });
+ } catch (IOException ex) {
+ String p = messages.getString(BKUGUIFacade.ERR_VIEWER);
+ viewer.setText(MessageFormat.format(p, new Object[]{ex.getMessage()}));
+ }
+ viewer.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+ JScrollPane scrollPane = new JScrollPane(viewer);
+ scrollPane.setPreferredSize(viewer.getPreferredSize());
+ scrollPane.setAlignmentX(LEFT_ALIGNMENT);
+ viewer.setCaretPosition(0);
+
+// JLabel viewerLabel = new JLabel();
+// viewerLabel.setText(viewerLabelText);
+// viewerLabel.setFont(viewerLabel.getFont().deriveFont(viewerLabel.getFont().getStyle() | java.awt.Font.BOLD));
+// viewerLabel.setLabelFor(viewer);
+
+ JPanel viewerPanel = new JPanel();
+ GroupLayout viewerPanelLayout = new GroupLayout(viewerPanel);
+ viewerPanel.setLayout(viewerPanelLayout);
+
+ viewerPanelLayout.setHorizontalGroup(
+ viewerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING)
+// .addComponent(viewerLabel)
+ .addComponent(scrollPane));
+ viewerPanelLayout.setVerticalGroup(
+ viewerPanelLayout.createSequentialGroup()
+// .addComponent(viewerLabel)
+// .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(scrollPane));
+
+ return viewerPanel;
+ }
+
+ private JPanel createButtonPanel() {
+ JButton closeButton = new JButton();
+ closeButton.setText(messages.getString(BKUGUIFacade.BUTTON_CLOSE));
+ closeButton.addActionListener(this);
+
+ JPanel buttonPanel = new JPanel();
+ GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel);
+ buttonPanel.setLayout(buttonPanelLayout);
+
+ buttonPanelLayout.setHorizontalGroup(
+ buttonPanelLayout.createSequentialGroup().addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(closeButton));
+ buttonPanelLayout.setVerticalGroup(
+ buttonPanelLayout.createSequentialGroup().addComponent(closeButton));
+ return buttonPanel;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ HelpViewer.dialog.setVisible(false);
+ }
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HyperlinkRenderer.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HyperlinkRenderer.java
new file mode 100644
index 00000000..6af22815
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/HyperlinkRenderer.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package at.gv.egiz.bku.gui;
+
+import at.gv.egiz.stal.HashDataInput;
+import javax.swing.table.DefaultTableCellRenderer;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class HyperlinkRenderer extends DefaultTableCellRenderer {
+
+ protected boolean renderReferenceId;
+
+ public HyperlinkRenderer(boolean renderReferenceId) {
+ this.renderReferenceId = renderReferenceId;
+ }
+
+ /**
+ * cannot change mouse cursor here, do in jTable
+ * @param value
+ */
+ @Override
+ protected void setValue(Object value) {
+ String hrefText;
+ if (((HashDataInput) value).getFilename() != null) {
+ hrefText = ((HashDataInput) value).getFilename();
+ } else {
+ if (renderReferenceId) {
+ hrefText = ((HashDataInput) value).getReferenceId();
+ } else {
+ hrefText = ((HashDataInput) value).getMimeType();
+ }
+ }
+ super.setText("<html><u>" + hrefText + "</u></html>");
+ setForeground(BKUGUIFacade.HYPERLINK_COLOR);
+ }
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/ImagePanel.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/ImagePanel.java
new file mode 100644
index 00000000..6a738acb
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/ImagePanel.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package at.gv.egiz.bku.gui;
+
+import java.awt.Graphics;
+import java.awt.Image;
+import java.net.URL;
+import javax.swing.ImageIcon;
+import javax.swing.JPanel;
+
+/**
+ * paints the background image in the lower left corner of the component
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class ImagePanel extends JPanel {
+
+ protected Image backgroundImg;
+
+ public ImagePanel(URL background) {
+ this(new ImageIcon(background).getImage());
+ }
+
+ public ImagePanel(Image img) {
+ this.backgroundImg = img;
+ this.setOpaque(false);
+ }
+
+ @Override
+ public void paintComponent(Graphics g) {
+ super.paintComponent(g);
+ g.drawImage(backgroundImg, 0, this.getHeight() - backgroundImg.getHeight(null), null);
+ }
+
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java
new file mode 100644
index 00000000..52a3d5fe
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.gui;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.swing.JButton;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.PlainDocument;
+
+/**
+ *
+ * @author clemens
+ */
+class PINDocument extends PlainDocument {
+
+ private static final long serialVersionUID = 1L;
+ protected Pattern pinPattern;
+ protected int minLength;
+ protected int maxLength;
+ protected JButton enterButton;
+
+ public PINDocument(int minLength, int maxLength, String pattern, JButton enterButton) {
+ if (enterButton == null) {
+ throw new NullPointerException("OK button null");
+ }
+ if (pattern != null) {
+ pinPattern = Pattern.compile(pattern);
+ } else {
+ pinPattern = Pattern.compile(".");
+ }
+ this.minLength = minLength;
+ this.maxLength = maxLength;
+ this.enterButton = enterButton;
+ }
+
+ @Override
+ public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {
+ if (maxLength < 0 || maxLength >= (getLength() + str.length())) {
+ boolean matches = true;
+ for (int i = 0; i < str.length(); i++) {
+ Matcher m = pinPattern.matcher(str.substring(i, i + 1));
+ if (!m.matches()) {
+ matches = false;
+ }
+ }
+ if (matches) {
+ super.insertString(offs, str, a);
+ enterButton.setEnabled(getLength() >= minLength);
+ }
+ }
+ }
+
+ @Override
+ public void remove(int offs, int len) throws BadLocationException {
+ super.remove(offs, len);
+ enterButton.setEnabled(getLength() >= minLength);
+ }
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java
new file mode 100644
index 00000000..7db70c46
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SecureViewerDialog.java
@@ -0,0 +1,360 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package at.gv.egiz.bku.gui;
+
+import at.gv.egiz.bku.gui.viewer.FontProvider;
+import at.gv.egiz.bku.gui.viewer.SecureViewerSaveDialog;
+import at.gv.egiz.stal.HashDataInput;
+import java.awt.Container;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.nio.charset.Charset;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ResourceBundle;
+import javax.swing.GroupLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JEditorPane;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.LayoutStyle;
+import javax.swing.WindowConstants;
+import javax.swing.text.Document;
+import javax.swing.text.EditorKit;
+import javax.swing.text.StyledEditorKit;
+import javax.swing.text.html.HTMLEditorKit;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class SecureViewerDialog extends JDialog {
+
+ /** don't import BKUFonts in order not to load BKUFonts.jar
+ * BKUApplet includes BKUFonts as runtime dependency only, the jar is copied to the applet dir in BKUOnline with dependency-plugin
+ * BKUViewer has compile dependency BKUFonts, transitive in BKUOnline and BKULocal
+ */
+ public static final Dimension VIEWER_DIMENSION = new Dimension(600, 400);
+
+ public static final List<String> SUPPORTED_MIME_TYPES = new ArrayList<String>();
+ static {
+ SUPPORTED_MIME_TYPES.add("text/plain");
+ SUPPORTED_MIME_TYPES.add("application/xhtml+xml");
+ }
+ protected static final Log log = LogFactory.getLog(SecureViewerDialog.class);
+// private static SecureViewerDialog dialog;
+ protected ResourceBundle messages;
+ protected JEditorPane viewer;
+ protected JLabel viewerLabel;
+ protected JScrollPane scrollPane;
+ protected HashDataInput content; //remember for save dialog
+ protected FontProvider fontProvider;
+
+ /**
+ * Create and display a modal SecureViewer dialog.
+ * This method blocks until the dialog's close button is pressed.
+ *
+ * @param owner, dialog is positioned relative to its owner
+ * (if null, at default location of native windowing system)
+ */
+ public SecureViewerDialog(Frame owner, ResourceBundle messages,
+ ActionListener closeListener, String closeCommand,
+ FontProvider fontProvider, ActionListener helpListener) {
+ super(owner, messages.getString(BKUGUIFacade.WINDOWTITLE_VIEWER), true);
+ this.setIconImages(BKUIcons.icons);
+ this.messages = messages;
+ this.fontProvider = fontProvider;
+
+ initContentPane(VIEWER_DIMENSION,
+ createViewerPanel(helpListener),
+ createButtonPanel(closeListener, closeCommand));
+
+ // also leave defaultWindowClosing HIDE_ON_CLOSE
+ this.addWindowListener(new WindowCloseListener(closeListener, closeCommand));
+ this.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+
+ pack();
+ if (owner != null) {
+ setLocationRelativeTo(owner);
+ } else {
+ setLocationByPlatform(true);
+ }
+ }
+
+ private void initContentPane(Dimension preferredSize,
+ JPanel viewerPanel, JPanel buttonPanel) {
+ Container contentPane = getContentPane();
+ contentPane.setPreferredSize(preferredSize);
+
+ GroupLayout mainLayout = new GroupLayout(contentPane);
+ contentPane.setLayout(mainLayout);
+
+ mainLayout.setHorizontalGroup(
+ mainLayout.createSequentialGroup().addContainerGap().addGroup(
+ mainLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addComponent(viewerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(buttonPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)).addContainerGap());
+ mainLayout.setVerticalGroup(
+ mainLayout.createSequentialGroup().addContainerGap().addComponent(viewerPanel, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED).addComponent(buttonPanel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE).addContainerGap());
+ }
+
+ /**
+ * @param helpListener may be null
+ */
+ private JPanel createViewerPanel(final ActionListener helpListener) {
+ viewer = new JEditorPane();
+ viewer.setEditable(false);
+ viewer.putClientProperty(JEditorPane.HONOR_DISPLAY_PROPERTIES, Boolean.TRUE);
+
+ scrollPane = new JScrollPane();
+
+ JPanel viewerPanel = new JPanel();
+ GroupLayout viewerPanelLayout = new GroupLayout(viewerPanel);
+ viewerPanel.setLayout(viewerPanelLayout);
+
+ GroupLayout.SequentialGroup infoHorizontal = viewerPanelLayout.createSequentialGroup();
+ GroupLayout.ParallelGroup infoVertical = viewerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING);
+
+ viewerLabel = new JLabel();
+ viewerLabel.setFont(viewerLabel.getFont().deriveFont(viewerLabel.getFont().getStyle() | java.awt.Font.BOLD));
+// viewerLabel.setLabelFor(viewer);
+
+ infoHorizontal.addComponent(viewerLabel);
+ infoVertical.addComponent(viewerLabel);
+
+ if (helpListener != null) {
+ final JLabel helpLabel = new JLabel();
+ helpLabel.setFocusable(true);
+ helpLabel.setIcon(new ImageIcon(getClass().getResource(BKUGUIFacade.HELP_IMG)));
+ helpLabel.getAccessibleContext().setAccessibleName(messages.getString(BKUGUIFacade.ALT_HELP));
+ helpLabel.addMouseListener(new MouseAdapter() {
+
+ @Override
+ public void mouseClicked(MouseEvent arg0) {
+ ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, BKUGUIFacade.HELP_HASHDATAVIEWER);
+ helpListener.actionPerformed(e);
+ }
+ });
+ helpLabel.addKeyListener(new KeyAdapter() {
+
+ @Override
+ public void keyPressed(KeyEvent arg0) {
+
+ if (arg0.getKeyCode() == KeyEvent.VK_ENTER) {
+ ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, BKUGUIFacade.HELP_HASHDATAVIEWER);
+ helpListener.actionPerformed(e);
+ }
+ }
+ });
+
+ helpLabel.addFocusListener(new FocusAdapter() {
+
+ @Override
+ public void focusGained(FocusEvent e) {
+
+ helpLabel.setIcon(new ImageIcon(getClass().getResource(BKUGUIFacade.HELP_IMG_FOCUS)));
+ }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+
+ helpLabel.setIcon(new ImageIcon(getClass().getResource(BKUGUIFacade.HELP_IMG)));
+ }
+ });
+ helpLabel.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
+
+ infoHorizontal.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE).addComponent(helpLabel);
+ infoVertical.addComponent(helpLabel);
+ }
+
+ viewerPanelLayout.setHorizontalGroup(
+ viewerPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING).addGroup(infoHorizontal).addComponent(scrollPane));
+ viewerPanelLayout.setVerticalGroup(
+ viewerPanelLayout.createSequentialGroup().addGroup(infoVertical).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(scrollPane));
+
+ return viewerPanel;
+ }
+
+ /**
+ * Sets the hashdataInput to be displayed and makes the dialog visible.
+ * This method blocks until the dialog's close button is pressed.
+ *
+ * @param mimeType defaults to text/plain if null
+ * @param encoding must be null if document contains charset declaration (e.g. HTML page), otherwise the parser crashes
+
+ * @param hashDataInput
+ */
+ public void setContent(HashDataInput hashDataInput) { //throws FontProviderException {
+
+ log.debug("[" + Thread.currentThread().getName() + "] set viewer content");
+
+ this.content = null;
+ viewer.setText(null);
+
+ String mimeType = hashDataInput.getMimeType();
+ if (mimeType == null) {
+ mimeType = "text/plain";
+ }
+ log.debug("secure viewer mime type: " + mimeType);
+ // loads editorkit for text/plain if unrecognized
+ viewer.setContentType(mimeType);
+
+ try {
+
+ if ("text/plain".equals(mimeType)) {
+ viewer.setEditorKit(new StyledEditorKit());
+ viewer.setFont(fontProvider.getFont().deriveFont(Font.PLAIN, viewer.getFont().getSize()));
+ } else if ("application/xhtml+xml".equals(mimeType)) {
+ viewer.setEditorKit(new HTMLEditorKit());
+ //reset font if fontprovider font was set before (TODO also html font from fontprovider)
+ viewer.setFont(new Font("Dialog", Font.PLAIN, viewer.getFont().getSize())); //UIManager.getFont("Label.font"));
+ }
+
+ EditorKit editorKit = viewer.getEditorKit();
+ Document document = editorKit.createDefaultDocument();
+ // document.putProperty("IgnoreCharsetDirective", new Boolean(true));
+
+ Charset cs = (hashDataInput.getEncoding() == null) ? Charset.forName("UTF-8") : Charset.forName(hashDataInput.getEncoding());
+ log.debug("secure viewer encoding: " + cs.toString());
+
+ InputStreamReader isr = new InputStreamReader(hashDataInput.getHashDataInput(), cs);
+ Reader contentReader = new BufferedReader(isr);
+ viewer.read(contentReader, document);
+ contentReader.close();
+
+ this.content = hashDataInput;
+
+// } catch (Exception ex) // fontProvider
+// } catch (IllegalCharsetNameException ex) {
+// } catch (UnsupportedCharsetException ex) {
+// } catch (FontProviderException ex) {
+ } catch (Exception ex) {
+ log.error(ex.getMessage(), ex);
+ String p = messages.getString(BKUGUIFacade.ERR_VIEWER);
+ viewer.setContentType("text/plain");
+ viewer.setText(MessageFormat.format(p, ex.getMessage()));
+ }
+ viewer.setCaretPosition(0);
+
+ scrollPane.setViewportView(viewer);
+ scrollPane.setPreferredSize(viewer.getPreferredSize());
+ scrollPane.setAlignmentX(LEFT_ALIGNMENT);
+
+ if ("application/xhtml+xml".equals(mimeType)) {
+ viewerLabel.setText(messages.getString(BKUGUIFacade.WARNING_XHTML));
+ } else {
+ viewerLabel.setText("");
+ }
+
+ log.debug("VIEWER FONT: " + viewer.getFont());
+ setVisible(true);
+ toFront();
+ }
+
+ private JPanel createButtonPanel(ActionListener closeListener, String closeCommand) {
+ JButton closeButton = new JButton();
+ closeButton.setText(messages.getString(BKUGUIFacade.BUTTON_CLOSE));
+ closeButton.setActionCommand(closeCommand);
+ closeButton.addActionListener(new CloseButtonListener(closeListener));
+
+ JButton saveButton = new JButton();
+ saveButton.setText(messages.getString(BKUGUIFacade.BUTTON_SAVE));
+ saveButton.addActionListener(new SaveButtonListener());
+
+ int buttonSize = closeButton.getPreferredSize().width;
+ if (saveButton.getPreferredSize().width > buttonSize) {
+ buttonSize = saveButton.getPreferredSize().width;
+ }
+
+ JPanel buttonPanel = new JPanel();
+ GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel);
+ buttonPanel.setLayout(buttonPanelLayout);
+
+ buttonPanelLayout.setHorizontalGroup(
+ buttonPanelLayout.createSequentialGroup().addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE).addComponent(saveButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE).addPreferredGap(LayoutStyle.ComponentPlacement.RELATED).addComponent(closeButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE));
+ buttonPanelLayout.setVerticalGroup(
+ buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE).addComponent(saveButton).addComponent(closeButton));
+
+ return buttonPanel;
+ }
+
+ public class WindowCloseListener extends WindowAdapter {
+
+ ActionListener closeListener;
+ String closeCommand;
+
+ public WindowCloseListener(ActionListener closeListener, String closeCommand) {
+ this.closeListener = closeListener;
+ this.closeCommand = closeCommand;
+ }
+
+ @Override
+ public void windowClosing(WindowEvent e) {
+ log.trace("[" + Thread.currentThread().getName() + "] closing secure viewer");
+ setVisible(false);
+ if (closeListener != null) {
+ closeListener.actionPerformed(new ActionEvent(e.getSource(), e.getID(), closeCommand));
+ }
+ }
+ }
+
+ public class CloseButtonListener implements ActionListener {
+
+ ActionListener closeListener;
+
+ public CloseButtonListener(ActionListener closeListener) {
+ this.closeListener = closeListener;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.trace("[" + Thread.currentThread().getName() + "] closing secure viewer");
+ setVisible(false);
+ if (closeListener != null) {
+ closeListener.actionPerformed(e);
+ }
+ }
+ }
+
+ public class SaveButtonListener implements ActionListener {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.trace("[" + Thread.currentThread().getName() + "] display secure viewer save dialog");
+ SecureViewerSaveDialog.showSaveDialog(content, messages, null, null);
+ }
+ }
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusFocusListener.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusFocusListener.java
new file mode 100644
index 00000000..06e37a89
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusFocusListener.java
@@ -0,0 +1,38 @@
+package at.gv.egiz.bku.gui;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusAdapter;
+import java.awt.event.FocusEvent;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author Thomas Zefferer <thomas.zefferer@iaik.tugraz.at>
+ */
+public class SwitchFocusFocusListener extends FocusAdapter {
+
+ protected static final Log log = LogFactory.getLog(SwitchFocusFocusListener.class);
+
+ protected ActionListener swichFocusListener;
+
+ public SwitchFocusFocusListener(ActionListener externalSwitchFocusListener) {
+ super();
+ this.swichFocusListener = externalSwitchFocusListener;
+ }
+
+ public ActionListener getActionListener() {
+ return swichFocusListener;
+ }
+
+ @Override
+ public void focusGained(FocusEvent arg0) {
+
+ ActionEvent e = new ActionEvent(this, ActionEvent.ACTION_PERFORMED, null);
+ swichFocusListener.actionPerformed(e);
+ }
+
+
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusListener.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusListener.java
new file mode 100644
index 00000000..48b641e2
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/SwitchFocusListener.java
@@ -0,0 +1,44 @@
+package at.gv.egiz.bku.gui;
+
+import java.applet.AppletContext;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author Thomas Zefferer <thomas.zefferer@iaik.tugraz.at>
+ */
+public class SwitchFocusListener implements ActionListener {
+
+ protected final static Log log = LogFactory.getLog(SwitchFocusListener.class);
+
+ protected AppletContext ctx;
+ protected String javascriptFunction;
+
+ public SwitchFocusListener(AppletContext ctx, String javascriptFunction) {
+
+ this.ctx = ctx;
+ this.javascriptFunction = javascriptFunction;
+ }
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+
+ try {
+ ctx.showDocument
+ (new URL("javascript:" + javascriptFunction));
+ }
+ catch (MalformedURLException me) {
+
+ log.warn("Unable to call external javascript function.", me);
+ }
+
+
+ }
+
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/html/RestrictedHTMLEditorKit.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/html/RestrictedHTMLEditorKit.java
new file mode 100644
index 00000000..680bf1a4
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/html/RestrictedHTMLEditorKit.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package at.gv.egiz.bku.gui.html;
+
+import javax.swing.text.Element;
+import javax.swing.text.StyleConstants;
+import javax.swing.text.View;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.HTMLEditorKit;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class RestrictedHTMLEditorKit extends HTMLEditorKit {
+
+
+ public static class RestrictedHTMLFactory extends HTMLFactory {
+
+ @Override
+ public View create(Element elem) {
+ Object o =
+ elem.getAttributes().getAttribute(StyleConstants.NameAttribute);
+ if (o instanceof HTML.Tag) {
+ HTML.Tag kind = (HTML.Tag) o;
+ if (kind == HTML.Tag.IMG)
+ return new RestrictedImageView(elem);
+ }
+ return super.create( elem );
+ }
+
+ }
+
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/html/RestrictedImageView.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/html/RestrictedImageView.java
new file mode 100644
index 00000000..b1aa35db
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/html/RestrictedImageView.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package at.gv.egiz.bku.gui.html;
+
+import javax.swing.text.Element;
+import javax.swing.text.html.HTML;
+import javax.swing.text.html.ImageView;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+/**
+ * ImageViewer.refreshImage() (and loadImage()) is private :-(
+ */
+ public class RestrictedImageView extends ImageView {
+
+ public RestrictedImageView(Element elem) {
+ super(elem);
+ }
+
+// @Override
+// public Image getImage() {
+// int s = state;
+// if ((s & RELOAD_IMAGE_FLAG) != 0) {
+// refreshImage();
+// }
+// s = state;
+// if ((s & RELOAD_FLAG) != 0) {
+// synchronized(this) {
+// state = (state | RELOAD_FLAG) ^ RELOAD_FLAG;
+// }
+// setPropertiesFromAttributes();
+// }
+// return super.getImage();
+// }
+
+ /**
+ * check whether this URL corresponds to the data URI scheme
+ * (and the referenced content is directly included in the document).
+ * @return
+ */
+ private boolean isDataURI() {
+ String src = (String)getElement().getAttributes().
+ getAttribute(HTML.Attribute.SRC);
+ if (src == null) {
+ return false;
+ }
+
+ return src.toLowerCase().startsWith("data");
+ }
+ } \ No newline at end of file
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/FontProvider.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/FontProvider.java
new file mode 100644
index 00000000..8fb815b0
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/FontProvider.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package at.gv.egiz.bku.gui.viewer;
+
+import java.awt.Font;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public interface FontProvider {
+
+ /** will be replaced by more sophisticated font selection mechanism
+ * (see java.awt.Font int/String constants) */
+ String SANSMONO_FONT_RESOURCE = "DejaVuLGCSansMono.ttf";
+
+ /**
+ *
+ * @return
+ * @throws InterruptedException
+ * @throws FileNotFoundException if remote font file cannot be retrieved
+ */
+ Font getFont() throws FontProviderException;
+
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/FontProviderException.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/FontProviderException.java
new file mode 100644
index 00000000..5a6a277e
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/FontProviderException.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package at.gv.egiz.bku.gui.viewer;
+
+/**
+ * Encapsulates the reason why a font could not be loaded.
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class FontProviderException extends Exception {
+
+ public FontProviderException(String msg, Throwable cause) {
+ super(msg, cause);
+ }
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/MimeFilter.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/MimeFilter.java
new file mode 100644
index 00000000..5d64eb4f
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/MimeFilter.java
@@ -0,0 +1,65 @@
+/*
+* Copyright 2008 Federal Chancellery Austria and
+* Graz University of Technology
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package at.gv.egiz.bku.gui.viewer;
+
+import java.io.File;
+import java.util.ResourceBundle;
+import javax.swing.filechooser.FileFilter;
+
+/**
+ *
+ * @author clemens
+ */
+class MimeFilter extends FileFilter {
+
+ protected String mimeType;
+ protected ResourceBundle messages;
+
+ public MimeFilter(String mimeType, ResourceBundle messages) {
+ this.mimeType = mimeType;
+ this.messages = messages;
+ }
+
+ @Override
+ public boolean accept(File f) {
+
+ if (f.isDirectory()) {
+ return true;
+ }
+ return MimeTypes.getExtension(mimeType).equalsIgnoreCase(getExtension(f));
+ }
+
+ private String getExtension(File f) {
+ String ext = null;
+ String s = f.getName();
+ int i = s.lastIndexOf('.');
+
+ if (i > 0 && i < s.length() - 1) {
+ ext = s.substring(i + 1).toLowerCase();
+ }
+ return ext;
+ }
+
+ @Override
+ public String getDescription() {
+ return messages.getString(MimeTypes.getDescriptionKey(mimeType));
+ }
+
+ public static String getExtension(String mimeType) {
+ return MimeTypes.getExtension(mimeType);
+ }
+} \ No newline at end of file
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/MimeTypes.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/MimeTypes.java
new file mode 100644
index 00000000..4500fa71
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/MimeTypes.java
@@ -0,0 +1,53 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package at.gv.egiz.bku.gui.viewer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ *
+ * @author clemens
+ */
+public class MimeTypes {
+
+ private static final Map<String , String> FILE_EXTENSIONS = new HashMap<String, String>() {{
+ put("application/msword", ".doc");
+ put("application/octet-stream", ".bin");
+ put("application/pdf", ".pdf");
+ put("application/xhtml+xml", ".xhtml");
+ put("text/html", ".html");
+ put("text/plain", ".txt");
+ put("text/xml", ".xml");
+ }};
+
+ private static final Map<String , String> DESCRIPTIONS = new HashMap<String, String>() {{
+ put("application/msword", "mimetype.desc.doc");
+ put("application/octet-stream", "mimetype.desc.bin");
+ put("application/pdf", "mimetype.desc.pdf");
+ put("application/xhtml+xml", "mimetype.desc.xhtml");
+ put("text/html", "mimetype.desc.html");
+ put("text/plain", "mimetype.desc.txt");
+ put("text/xml", "mimetype.desc.xml");
+ }};
+
+ public static String getExtension(String mimetype) {
+ if (FILE_EXTENSIONS.containsKey(mimetype)) {
+ return FILE_EXTENSIONS.get(mimetype);
+ }
+ return "";
+ }
+
+ /**
+ * @return bundle key to be resolved in message resource bundle
+ */
+ public static String getDescriptionKey(String mimetype) {
+ if (DESCRIPTIONS.containsKey(mimetype)) {
+ return DESCRIPTIONS.get(mimetype);
+ }
+ return "mimetype.desc.unknown";
+ }
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/SecureViewerSaveDialog.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/SecureViewerSaveDialog.java
new file mode 100644
index 00000000..3303d4ef
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/SecureViewerSaveDialog.java
@@ -0,0 +1,121 @@
+package at.gv.egiz.bku.gui.viewer;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import javax.swing.JFileChooser;
+import javax.swing.JOptionPane;
+import javax.swing.SwingUtilities;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.bku.gui.BKUGUIFacade;
+import at.gv.egiz.stal.HashDataInput;
+
+public class SecureViewerSaveDialog {
+
+ protected static final Log log = LogFactory.getLog(SecureViewerSaveDialog.class);
+
+ public static void showSaveDialog(final HashDataInput hashDataInput, final ResourceBundle messages,
+ final ActionListener okListener, final String okCommand) {
+
+ log.debug("[" + Thread.currentThread().getName()
+ + "] scheduling save dialog");
+
+ SwingUtilities.invokeLater(new Runnable() {
+
+ @Override
+ public void run() {
+
+ log
+ .debug("[" + Thread.currentThread().getName()
+ + "] show save dialog");
+
+ String userHome = System.getProperty("user.home");
+
+ JFileChooser fileDialog = new JFileChooser(userHome);
+ fileDialog.setMultiSelectionEnabled(false);
+ fileDialog.setDialogType(JFileChooser.SAVE_DIALOG);
+ fileDialog.setFileHidingEnabled(true);
+ fileDialog.setDialogTitle(messages
+ .getString(BKUGUIFacade.WINDOWTITLE_SAVE));
+ fileDialog.setFileSelectionMode(JFileChooser.FILES_ONLY);
+ String mimeType = hashDataInput.getMimeType();
+ MimeFilter mimeFilter = new MimeFilter(mimeType, messages);
+ fileDialog.setFileFilter(mimeFilter);
+ String filename = (hashDataInput.getFilename() != null) ?
+ hashDataInput.getFilename() :
+ messages.getString(BKUGUIFacade.SAVE_HASHDATAINPUT_PREFIX)
+ + MimeFilter.getExtension(mimeType);
+ fileDialog.setSelectedFile(new File(userHome, filename));
+
+ // parent contentPane -> placed over applet
+ switch (fileDialog.showSaveDialog(fileDialog)) {
+ case JFileChooser.APPROVE_OPTION:
+ File file = fileDialog.getSelectedFile();
+ String id = hashDataInput.getReferenceId();
+ if (file.exists()) {
+ String msgPattern = messages
+ .getString(BKUGUIFacade.MESSAGE_OVERWRITE);
+ int overwrite = JOptionPane.showConfirmDialog(fileDialog,
+ MessageFormat.format(msgPattern, file), messages
+ .getString(BKUGUIFacade.WINDOWTITLE_OVERWRITE),
+ JOptionPane.OK_CANCEL_OPTION);
+ if (overwrite != JOptionPane.OK_OPTION) {
+ break;
+ }
+ }
+ if (log.isDebugEnabled()) {
+ log.debug("writing hashdata input " + id + " (" + mimeType
+ + ") to file " + file);
+ }
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(file);
+ BufferedOutputStream bos = new BufferedOutputStream(fos);
+ InputStream hdi = hashDataInput.getHashDataInput();
+ int b;
+ while ((b = hdi.read()) != -1) {
+ bos.write(b);
+ }
+ bos.flush();
+ bos.close();
+ } catch (IOException ex) {
+ log.error("Failed to write " + file + ": " + ex.getMessage());
+ log.debug(ex);
+ String errPattern = messages
+ .getString(BKUGUIFacade.ERR_WRITE_HASHDATA);
+ JOptionPane.showMessageDialog(fileDialog, MessageFormat.format(
+ errPattern, ex.getMessage()), messages
+ .getString(BKUGUIFacade.WINDOWTITLE_ERROR),
+ JOptionPane.ERROR_MESSAGE);
+ } finally {
+ try {
+ if (fos != null) {
+ fos.close();
+ }
+ } catch (IOException ex) {
+ }
+ }
+ break;
+ case JFileChooser.CANCEL_OPTION:
+ log.debug("cancelled save dialog");
+ break;
+ }
+ if (okListener != null) {
+ okListener.actionPerformed(new ActionEvent(fileDialog,
+ ActionEvent.ACTION_PERFORMED, okCommand));
+ }
+ }
+ });
+ }
+}
diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java b/BKUCommonGUI/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java
new file mode 100644
index 00000000..b9416845
--- /dev/null
+++ b/BKUCommonGUI/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java
@@ -0,0 +1,107 @@
+/*
+* Copyright 2008 Federal Chancellery Austria and
+* Graz University of Technology
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package at.gv.egiz.stal.impl;
+
+import at.gv.egiz.stal.HashDataInput;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author clemens
+ */
+public class ByteArrayHashDataInput implements HashDataInput {
+
+ private static final Log log = LogFactory.getLog(ByteArrayHashDataInput.class);
+
+ protected byte[] hashData;
+ protected String id;
+ protected String mimeType;
+ protected String encoding;
+ protected String filename;
+
+ public ByteArrayHashDataInput(byte[] hashData, String id, String mimeType, String encoding, String filename) {
+ if (hashData == null) {
+ throw new NullPointerException("HashDataInput not provided.");
+ }
+ this.hashData = hashData;
+ this.id = id;
+ this.mimeType = mimeType;
+ this.encoding = encoding;
+ this.filename = filename;
+ }
+
+ /**
+ * caches the hashdata input's stream
+ * @param hdi to be cached
+ */
+ public ByteArrayHashDataInput(HashDataInput hdi) {
+ if (hdi == null) {
+ throw new NullPointerException("HashDataInput not provided.");
+ }
+ InputStream is = hdi.getHashDataInput();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ try {
+ byte[] buffer = new byte[1024];
+ for (int i = is.read(buffer); i > -1; i = is.read(buffer)) {
+ baos.write(buffer, 0, i);
+ }
+ this.hashData = baos.toByteArray();
+ } catch (IOException ex) {
+ log.error("Failed to cache provided HashDataInput: " + ex.getMessage(), ex);
+ this.hashData = new byte[0];
+ }
+ this.id = hdi.getReferenceId();
+ this.mimeType = hdi.getMimeType();
+ this.encoding = hdi.getEncoding();
+ }
+
+ @Override
+ public String getReferenceId() {
+ return id;
+ }
+
+ @Override
+ public String getMimeType() {
+ return mimeType;
+ }
+
+ @Override
+ public InputStream getHashDataInput() {
+ return new ByteArrayInputStream(hashData);
+ }
+
+ /**
+ * may be null
+ * @return
+ */
+ @Override
+ public String getEncoding() {
+ return encoding;
+ }
+
+ @Override
+ public String getFilename() {
+ return filename;
+ }
+
+
+}
diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties
new file mode 100644
index 00000000..c09433de
--- /dev/null
+++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties
@@ -0,0 +1,109 @@
+# Copyright 2008 Federal Chancellery Austria and
+# Graz University of Technology
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+title.welcome=<html>Willkommen</html>
+title.insertcard=<html>Keine B\u00FCrgerkarte gefunden</html>
+title.cardnotsupported=<html>Die Karte wird nicht unterst\u00FCtzt</html>
+title.verify.pin=<html>Karte wird gelesen</html>
+title.sign=<html>Signatur erstellen</html>
+title.verify.pinpad=<html>PIN eingeben
+title.error=<html>Fehler</html>
+title.warning=<html>Achtung
+title.entry.timeout=<html>Zeit\u00FCberschreitung</html>
+title.retry=<html>Falsche PIN</html>
+title.wait=<html>Bitte warten</html>
+title.signature.data=<html>Signaturdaten</html>
+windowtitle.save=Signaturdaten speichern
+windowtitle.error=Fehler
+windowtitle.savedir=Signaturdaten in Verzeichnis speichern
+windowtitle.overwrite=Datei \u00FCberschreiben?
+windowtitle.viewer=Signaturdaten
+windowtitle.help=Hilfe zur B\u00FCrgerkarte
+
+# removed message.* prefix to reuse keys as help keys
+welcome=<html>Bitte warten...</html>
+wait=<html>Bitte warten...</html>
+cardnotsupported=<html>Bitte die B\u00FCrgerkarte in den Kartenleser stecken</html>
+insertcard=<html>Bitte die B\u00FCrgerkarte in den Kartenleser stecken</html>
+enterpin=<html>{0} eingeben</html>
+enterpin.pinpad=<html>PIN am Kartenleser eingeben</html>
+enterpin.pinpad.direct=<html>{0} ({1} stellig) am Kartenleser eingeben</html>
+hashdatalink=<html><a href=\"anzeige\">Signaturdaten anzeigen</a></html>
+hashdatalink.tiny=<html><a href=\"anzeige\">Signaturdaten</a></html>
+hashdatalink.focus=<html><a href=\"anzeige\">[Signaturdaten anzeigen]</a></html>
+hashdatalink.tiny.focus=<html><a href=\"anzeige\">[Signaturdaten]</a></html>
+#message.hashdata=<html>Hinweis: Dies ist eine Voransicht des zu signierenden Inhalts. F\u00FCr eine standardkonforme Darstellung siehe Hilfe (i).</html>
+#message.hashdata=<html>Dies ist eine Voransicht des zu signierenden Inhaltes. F\u00FCr Details siehe Hilfe (i).</html>
+#verwenden sie bitte die von ihrem System zur Verf\u00FCgung gestellte {0} Anwendung.
+hashdatalist=<html>{0} Signaturdaten:</html>
+hashdata.viewer=<html>Signaturdaten werden im Betrachter angezeigt
+unsupported.mimetype=<html>Signaturdaten k\u00F6nnen nicht angezeigt werden
+retries.last=<html>Letzter Versuch!</html>
+retries=<html>Noch {0} Versuche</html>
+retries.pinpad.last=<html>Eingabe wiederholen, letzter Versuch!</html>
+retries.pinpad=<html>Eingabe wiederholen, noch {0} Versuche</html>
+overwrite=<html>M\u00F6chten Sie das existierende Dokument {0} \u00FCberschreiben?</html>
+help=<html>Hilfe zu {0}</html>
+
+warning.xhtml=<html>Hinweis: Dies ist eine Voransicht des zu signierenden Inhalts. F\u00FCr eine standardkonforme Darstellung siehe Hilfe (i).</html>
+label.pin=<html>{0}:</html>
+label.pinsize=<html>({0} stellig)</html>
+button.ok=OK
+button.cancel=Abbrechen
+button.back=Zur\u00FCck
+button.sign=Signieren
+button.save=Speichern...
+button.close=Schlie\u00DFen
+mimetype.desc.xml=XML-Dateien (.xml)
+mimetype.desc.html=HTML-Dateien (.html, .htm)
+mimetype.desc.xhtml=XHTML-Dateien (.xhtml)
+mimetype.desc.txt=Textdateien (.txt)
+mimetype.desc.pdf=Adobe PDF-Dateien (.pdf)
+mimetype.desc.bin=Bin\u00E4rdateien (.bin)
+mimetype.desc.doc=Microsoft Word-Dateien (.doc)
+mimetype.desc.unknown=Alle Dateien (.*)
+save.hashdatainput.prefix=Signaturdaten
+alt.help=Hilfe
+
+# Error Messages
+error.no.hashdata=<html>Keine Signaturdaten verf\u00FCgbar: {0}</html>
+error.display.hashdata=<html>Signaturdaten konnten nicht dargestellt werden: {0}</html>
+error.write.hashdata=<html>Die Signaturdaten konnten nicht gespeichert werden: {0}</html>
+error.invalid.hash=<html>Die Signaturdaten sind ung\u00FCltig: {0}</html>
+error.ws.unreachable=<html>Der Server ist nicht erreichbar</html>
+#error.ws.unreachable=<html>Das Web-Service ist nicht erreichbar: {0}</html>
+error.pcsc=<html>Es konnte keine PC/SC Schnittstelle gefunden werden</html>
+error.cardterminal=<html>Es konnte kein Smartcard-Leser gefunden werden</html>
+error.unknown.param=<html>Ein Fehler trat auf: {0}</html>
+error.unknown=<html>Ein Fehler trat auf</html>
+error.test=<html>Fehler1 {0} - Fehler2 {1}</html>
+error.card.locked=<html>B\u00FCrgerkarte ist gesperrt</html>
+error.card.notactivated=<html>Die B\u00FCrgerkarte ist nicht aktiviert</html>
+error.pin.timeout=<html>Zeit\u00FCberschreitung bei Eingabe der PIN</html>
+error.viewer=<html>Der Inhalt kann nicht dargestellt werden: {0}
+error.external.link=<html>Externer Link {0} wird nicht ge\u00F6ffnet</html>
+error.config=<html>Fehlerhafte Konfiguration des Systems: {0}</html>
+
+# Help Topics
+help.welcome=Startseite
+help.wait=Bitte Warten Bildschirm
+help.cardnotsupported=Nicht unterst\u00FCtzte B\u00FCrgerkarte
+help.insertcard=Keine B\u00FCrgerkarte im Kartenleser
+help.cardpin=Pineingabe
+help.signpin=Signatur-Pineingabe
+help.retry=Falsche Pin
+help.hashdata=Signierte Inhalte
+help.hashdatalist=Signierte Inhalte
+help.hashdataviewer=Anzeige signierter Inhalte \ No newline at end of file
diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties
new file mode 100644
index 00000000..4d86d21b
--- /dev/null
+++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties
@@ -0,0 +1,107 @@
+# Copyright 2008 Federal Chancellery Austria and
+# Graz University of Technology
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+title.welcome=<html>Welcome</html>
+title.insertcard=<html>No citizen card found</html>
+title.cardnotsupported=<html>This card is not supported</html>
+title.verify.pin=<html>Reading card</html>
+title.sign=<html>Create signature</html>
+title.verify.pinpad=<html>Enter PIN
+title.error=<html>Error</html>
+title.warning=<html>Warning
+title.entry.timeout=<html>Timeout</html>
+title.retry=<html>Wrong PIN</html>
+title.wait=<html>Please wait</html>
+title.signature.data=<html>Signature data</html>
+windowtitle.save=Save signature data
+windowtitle.error=Error
+windowtitle.savedir=Save signature data to directory
+windowtitle.overwrite=Overwrite file?
+windowtitle.viewer=Signature data
+windowtitle.help=Citizen card help
+
+# removed message.* prefix to reuse keys as help keys
+welcome=<html>Please wait...</html>
+wait=<html>Please wait...</html>
+insertcard=<html>Please insert your citizen card into the reader</html>
+cardnotsupported=<html>Please insert your citizen card into the reader</html>
+enterpin=<html>Enter {0}</html>
+enterpin.pinpad=<html>Enter PIN on card reader pinpad</html>
+enterpin.pinpad.direct=<html>Enter {0} ({1} digits) on card reader pinpad</html>
+hashdatalink=<html><a href=\"anzeige\">Display signature data</a></html>
+hashdatalink.tiny=<html><a href=\"anzeige\">signature data</a></html>
+hashdatalink.focus=<html><a href=\"anzeige\">[Display signature data]</a></html>
+hashdatalink.tiny.focus=<html><a href=\"anzeige\">[signature data]</a></html>
+#message.hashdata=<html>Remark: This is a preview of the data to-be signed. For standards compliant display see help.</html>
+hashdatalist=<html>{0} signature data objects:</html>
+hashdata.viewer=<html>Signature data is being displayed in viewer
+unsupported.mimetype=<html>Signature data cannot be displayed
+retries.last=<html>Last try!</html>
+retries=<html>{0} tries left</html>
+retries.pinpad.last=<html>Re-enter pin, last try!</html>
+retries.pinpad=<html>Re-enter pin, {0} tries left</html>
+overwrite=<html>Overwrite {0}?</html>
+help=<html>Help topic {0}</html>
+
+warning.xhtml=<html>Remark: This is a preview of the data to-be signed. For standard-compliant display see help.</html>
+label.pin=<html>{0}:</html>
+label.pinsize=<html>({0} digits)</html>
+button.ok=OK
+button.cancel=Cancel
+button.back=Back
+button.sign=Sign
+button.save=Save...
+button.close=Close
+mimetype.desc.xml=XML-files (.xml)
+mimetype.desc.html=HTML-files (.html, .htm)
+mimetype.desc.xhtml=XHTML-files (.xhtml)
+mimetype.desc.txt=Textfiles (.txt)
+mimetype.desc.pdf=Adobe PDF-files (.pdf)
+mimetype.desc.bin=Binary files (.bin)
+mimetype.desc.doc=Microsoft Word-files (.doc)
+mimetype.desc.unknown=All files (.*)
+save.hashdatainput.prefix=signaturedata
+alt.help=help
+
+# Error Messages
+error.no.hashdata=<html>No signature data available: {0}</html>
+error.display.hashdata=<html>Could not display signature data: {0}</html>
+error.write.hashdata=<html>Could not save signature data: {0}</html>
+error.invalid.hash=<html>Invalid signature data: {0}</html>
+error.ws.unreachable=<html>Server unreachable</html>
+#error.ws.unreachable=<html>Web-service unreachable: {0}</html>
+error.pcsc=<html>No PC/SC interface for smartcard access provided</html>
+error.cardterminal=<html>Could not find smartcard reader</html>
+error.unknown.param=<html>An error occured: {0}</html>
+error.unknown=<html>An error occured</html>
+error.test=<html>Error1 {0} - Error2 {1}</html>
+error.card.locked=<html>Citizen card is locked</html>
+error.card.notactivated=<html>Citizen card not activated</html>
+error.pin.timeout=<html>Timeout during PIN entry</html>
+error.viewer=<html>Failed to display contents: {0}
+error.external.link=<html>Cannot open external link {0}</html>
+error.config=<html>Incorrect system configuration: {0}</html>
+
+# Help Topics
+help.welcome=Welcome page
+help.wait=Wait screen
+help.cardnotsupported=Unsupported citizen card
+help.insertcard=No citizen card found
+help.cardpin=Pin entry
+help.signpin=Signature pin entry
+help.retry=Wrong Pin
+help.hashdata=Signed contents
+help.hashdatalist=Signed contents
+help.hashdataviewer=Display of signed contents \ No newline at end of file
diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip128.png b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip128.png
new file mode 100644
index 00000000..c36d8079
--- /dev/null
+++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip128.png
Binary files differ
diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip16.png b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip16.png
new file mode 100644
index 00000000..96b580e9
--- /dev/null
+++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip16.png
Binary files differ
diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip24.png b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip24.png
new file mode 100644
index 00000000..efd6dbeb
--- /dev/null
+++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip24.png
Binary files differ
diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip32.png b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip32.png
new file mode 100644
index 00000000..e7efb020
--- /dev/null
+++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip32.png
Binary files differ
diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip48.png b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip48.png
new file mode 100644
index 00000000..491fbcac
--- /dev/null
+++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chip48.png
Binary files differ
diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chiperling105.png b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chiperling105.png
new file mode 100644
index 00000000..eee4be4f
--- /dev/null
+++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/chiperling105.png
Binary files differ
diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/help.png b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/help.png
new file mode 100644
index 00000000..d1c36c33
--- /dev/null
+++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/help.png
Binary files differ
diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/help_focus.png b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/help_focus.png
new file mode 100644
index 00000000..d650bea2
--- /dev/null
+++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/help_focus.png
Binary files differ
diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java
new file mode 100644
index 00000000..fdd58850
--- /dev/null
+++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUITest.java
@@ -0,0 +1,62 @@
+/*
+* Copyright 2008 Federal Chancellery Austria and
+* Graz University of Technology
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package at.gv.egiz.bku.gui;
+
+import java.awt.Container;
+import java.awt.Dimension;
+import javax.swing.JFrame;
+import org.junit.Ignore;
+import org.junit.Test;
+
+
+/**
+ *
+ * @author clemens
+ */
+@Ignore
+public class BKUGUITest {
+
+ @Test
+ public void testBKUGUI() {
+ JFrame testFrame = new JFrame("BKUGUITest");
+ Container contentPane = testFrame.getContentPane();
+// contentPane.setPreferredSize(new Dimension(170, 150));
+ contentPane.setPreferredSize(new Dimension(290, 190));
+ BKUGUIFacade gui = new BKUGUIImpl(contentPane, null, BKUGUIFacade.Style.advanced, null, new DummyFontLoader(), null, null);
+ BKUGUIWorker worker = new BKUGUIWorker();
+ worker.init(gui);
+ testFrame.pack();
+ testFrame.setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+ testFrame.setVisible(true);
+ new Thread(worker).start();
+
+ while(true) ;
+ }
+
+ @Test
+ public void dummyTest() {
+ }
+
+// public static void main(String[] args) {
+// new BKUGUITest().testBKUGUI();
+// }
+}
diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java
new file mode 100644
index 00000000..a2a84d6e
--- /dev/null
+++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package at.gv.egiz.bku.gui;
+
+import at.gv.egiz.smcc.PINSpec;
+import at.gv.egiz.smcc.STARCOSCard;
+import at.gv.egiz.stal.HashDataInput;
+import at.gv.egiz.stal.impl.ByteArrayHashDataInput;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ *
+ * @author clemens
+ */
+public class BKUGUIWorker implements Runnable {
+
+ BKUGUIFacade gui;
+
+ public void init(BKUGUIFacade gui) {
+ this.gui = gui;
+ }
+
+ @Override
+ public void run() {
+ try {
+
+ final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Test-PIN", (byte) 0x81, null);
+ final PINSpec cardPinSpec = new PINSpec(4, 4, "[0-9]", "Test-PIN", (byte) 0x01, null);
+
+
+ final ActionListener cancelListener = new ActionListener() {
+
+ public void actionPerformed(ActionEvent e) {
+ System.out.println("CANCEL EVENT OCCURED: " + e);
+ }
+ };
+ ActionListener okListener = new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ System.out.println("OK EVENT OCCURED: " + e);
+ }
+ };
+ final ActionListener signListener = new ActionListener() {
+
+ public void actionPerformed(ActionEvent e) {
+ System.out.println("SIGN EVENT OCCURED: " + e);
+ }
+ };
+ ActionListener hashdataListener = new ActionListener() {
+
+ public void actionPerformed(ActionEvent e) {
+ System.out.println("HASHDATA EVENT OCCURED: " + e);
+ ActionListener returnListener = new ActionListener() {
+
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", null, "hashdata");
+ }
+ };
+ HashDataInput signedRef1 = new ByteArrayHashDataInput(
+ "Ich bin ein einfacher Text mit Umlauten: öäüßéç@€\n123\n456\n\tHello, world!\n\nlkjsd\nnksdjf".getBytes(),
+ "ref-id-0000000000000000000000001",
+ "text/plain",
+ "UTF-8",
+ "file.txt");
+
+ HashDataInput signedRef2 = new ByteArrayHashDataInput(
+ "<xml>HashDataInput_002</xml>".getBytes(),
+ "ref-id-000000002",
+ "application/xhtml+xml",
+ "UTF-8",
+ "file.xhtml");
+
+ HashDataInput signedRef3 = new ByteArrayHashDataInput(
+ "<xml>HashDataInput_003</xml>".getBytes(),
+ "ref-id-000000003",
+ "application/xhtml+xml",
+ "UTF-8",
+ "file2.xhtml");
+
+ HashDataInput signedRef4 = new ByteArrayHashDataInput(
+ "<xml>HashDataInput_004</xml>".getBytes(),
+ "ref-id-000000004",
+ "text/xml",
+ "UTF-8",
+ "file.xml");
+
+ //
+ List<HashDataInput> signedRefs = new ArrayList();
+ signedRefs.add(signedRef1);
+// signedRefs.add(signedRef2);
+// signedRefs.add(signedRef3);
+// signedRefs.add(signedRef4);
+// signedRefs.add(signedRef4);
+// signedRefs.add(signedRef4);
+// signedRefs.add(signedRef4);
+// signedRefs.add(signedRef4);
+// signedRefs = Collections.singletonList(signedRef1);
+ gui.showSecureViewer(signedRefs, returnListener, "return");
+ }
+ };
+
+
+
+// gui.showWelcomeDialog();
+//
+// Thread.sleep(2000);
+//
+// gui.showWaitDialog(null);
+//
+// Thread.sleep(1000);
+//
+// gui.showWaitDialog("test");
+//
+// Thread.sleep(1000);
+//
+//
+// gui.showInsertCardDialog(cancelListener, "cancel");
+//
+// Thread.sleep(2000);
+//
+// gui.showCardNotSupportedDialog(cancelListener, "cancel");
+//
+// Thread.sleep(2000);
+//
+// PINSpec cardPinSpec = new PINSpec(4, 4, "[0-9]", "Karten-PIN");
+//
+// gui.showCardPINDialog(cardPinSpec, okListener, "ok", cancelListener, "cancel");
+//
+// Thread.sleep(2000);
+//
+// gui.showSignaturePINDialog(signPinSpec, -1, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata");
+
+ gui.showSignatureDataDialog(signPinSpec, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata");
+ Thread.sleep(2000);
+
+ gui.showEnterPINDirect(signPinSpec, -1);
+//
+// Thread.sleep(4000);
+//
+
+// gui.showErrorDialog(BKUGUIFacade.ERR_NO_PCSC, null, null, null);
+
+// gui.showSignaturePINRetryDialog(signPinSpec, 2, signListener, "sign", cancelListener, "cancel", hashdataListener, "hashdata");
+//
+// Thread.sleep(2000);
+//
+// gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, new Object[] {"Testfehler"}, null, null);
+//
+// Thread.sleep(2000);
+//
+// gui.showErrorDialog("error.test", new Object[] {"Testfehler", "noch ein TestFehler"});
+//
+// Thread.sleep(2000);
+//
+// gui.showErrorDialog("error.no.hashdata", null);
+//
+// Thread.sleep(2000);
+//
+// gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, new Object[] {"Testfehler"});
+//
+// Thread.sleep(2000);
+//
+// gui.showErrorDialog("error.unknown", null);
+
+
+// gui.showTextPlainHashDataInput("hallo,\n welt!", "12345", null, "cancel", null, "save");
+// gui.showTextPlainHashDataInput("hallo,\n welt!", "12345", null, "cancel", null, "save");
+// Thread.sleep(2000);
+
+ } catch (InterruptedException ex) {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/DummyFontLoader.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/DummyFontLoader.java
new file mode 100644
index 00000000..505c4247
--- /dev/null
+++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/DummyFontLoader.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package at.gv.egiz.bku.gui;
+
+import at.gv.egiz.bku.gui.viewer.FontProviderException;
+import at.gv.egiz.bku.gui.viewer.FontProvider;
+import java.awt.Font;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class DummyFontLoader implements FontProvider {
+
+ protected final static Log log = LogFactory.getLog(DummyFontLoader.class);
+
+ @Override
+ public Font getFont() throws FontProviderException {
+ log.debug("return font");
+ return new Font("monospaced", Font.PLAIN, 10);
+ }
+
+}
diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/SecureViewerDialogTest.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/SecureViewerDialogTest.java
new file mode 100644
index 00000000..9bbc1b1a
--- /dev/null
+++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/SecureViewerDialogTest.java
@@ -0,0 +1,167 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package at.gv.egiz.bku.gui;
+
+import at.gv.egiz.stal.impl.ByteArrayHashDataInput;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.BufferedInputStream;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.util.ResourceBundle;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+/**
+ *
+ * @author clemens
+ */
+@Ignore
+public class SecureViewerDialogTest {
+
+ static SecureViewerDialog secureViewer;
+ static ResourceBundle messages;
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ messages = ResourceBundle.getBundle("at/gv/egiz/bku/gui/Messages");
+ secureViewer = new SecureViewerDialog(null, messages,null, null, new DummyFontLoader(), null);
+ }
+
+ @AfterClass
+ public static void tearDownClass() throws Exception {
+ }
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ }
+
+
+ @Test
+ @Ignore
+ public void testLatin1Supplement() throws UnsupportedEncodingException, FileNotFoundException, IOException {
+// StringBuilder data = new StringBuilder();
+// data.append("\nhttp://www.unicode.org/charts/PDF/U0080.pdf\n");
+// for (int i = 0x0080; i <= 0x00ff; i++) {
+// data.append((char) i);
+// }
+// System.out.println(data.toString());
+ BufferedInputStream bis = new BufferedInputStream(new FileInputStream("/home/clemens/IAIK/MOCCA/encoding/test_iso-8859-1.txt"));
+ byte[] bytes = new byte[bis.available()];
+ bis.read(bytes);
+ String s = new String(bytes, "iso-8859-1");
+ System.out.println("read iso-8859-1 bytes " + s);
+
+ secureViewer.setContent(new ByteArrayHashDataInput(s.getBytes("UTF-8"), "id-1", "text/plain", "iso-8859-1", "file.txt"));
+
+ }
+
+ @Test
+ @Ignore
+ public void testGreek() throws UnsupportedEncodingException {
+// Font fm = new Font(Font.MONOSPACED, Font.PLAIN, 10);
+ Font fm = new Font("Lucida Sans Typewriter", Font.PLAIN, 18); //GothicBBB-MediumH", Font.PLAIN, 10);
+ System.out.println(fm.getFontName() + ", " + fm.getPSName() + ", " + fm);
+
+ StringBuilder data = new StringBuilder();
+ data.append("\nhttp://www.unicode.org/charts/PDF/U0370.pdf\n");
+ for (int i = 0x0370; i <= 0x03ff; i++) {
+ if (!fm.canDisplay((char) i)) {
+ System.out.println("cannot display " + Integer.toHexString(i) );
+ }
+ data.append((char) i);
+ }
+
+ System.out.println(data.toString());
+ secureViewer.setContent(new ByteArrayHashDataInput(data.toString().getBytes("UTF-8"), "id-1", "text/plain", "UTF-8", "file.txt"));
+
+ }
+
+ /**
+ * Test of setContent method, of class SecureViewerDialog.
+ */
+ @Test
+// @Ignore
+ public void testCyrillic() throws UnsupportedEncodingException {
+
+ StringBuilder data = new StringBuilder("\n");
+
+ int[] mocca = new int[] {0x041c, 0x04a8, 0x0480, 0x0480, 0x0466 };
+
+ for (int i = 0; i < mocca.length; i++) {
+ data.append((char) mocca[i]);
+ }
+ data.append(" goes cyrillic\n");
+
+ data.append("\nCyrillic - http://www.unicode.org/charts/PDF/U0400.pdf\n");
+ for (int i = 0x0400; i <= 0x04ff; i++) {
+// System.out.printf("%c%04x=%c\t", (i & 7) == 0 ? '\n' : '\0', i, (char)i);
+// System.out.print((char) i);
+ data.append((char)i);
+ }
+
+ data.append("\n\nCyrillic Supplement - http://www.unicode.org/charts/PDF/U0500.pdf\n");
+ for (int i = 0x0500; i <= 0x0525; i++) {
+// System.out.printf("%c%04x=%c\t", (i & 7) == 0 ? '\n' : '\0', i, (char)i);
+// System.out.print((char) i);
+ data.append((char) i);
+ }
+
+ for (int i = 0; i < data.length(); i++) {
+ char c = data.charAt(i);
+ if (c >= '\u0400' && c <= '\u0525') {
+ System.out.println(c + "\tcyrillic");
+ } else if (c < '\u007f') {
+ System.out.println(c + "\tlatin");
+ } else {
+ System.out.println(c + "\tunknown");
+ }
+ }
+
+ System.out.println(data.toString());
+
+// char[] cyrillicChars = new char[] {(char) 0x0411, (char) 0x0444};
+// System.out.println(new String(cyrillicChars)); // + ": " + SMCCHelper.toString(cyrillicBytes));
+// byte[] cyrillicBytes = new byte[] {(byte) 0x11, (byte) 0x04, (byte) 0x0444};
+// System.out.println(new String(cyrillicBytes, "UTF-8") + ": " + SMCCHelper.toString(cyrillicBytes));
+
+// String encoding = "cp1252";
+// String data = "öäü߀";
+// byte[] bytes = data.getBytes(encoding);
+// System.out.println(data + "\t" + SMCCHelper.toString(bytes));
+// byte[] bytes2 = data.getBytes("cp1252");
+// System.out.println(data + "\t" + SMCCHelper.toString(bytes2));
+
+ secureViewer.setContent(new ByteArrayHashDataInput(data.toString().getBytes("UTF-8"), "id-1", "text/plain", "UTF-8", "file.txt"));
+
+ System.out.println("\n\n=============================\n");
+//
+//// int[] mocca = new int[] {0x0428, 0x0429, 0x04a8, 0x04e8, 0x047a, 0x042d, 0x042d, 0x0421, 0x0421, 0x04d0, 0x0466 };
+// int[] mocca = new int[] {0x0429, 0x04a8, 0x0480, 0x0480, 0x0466 };
+ for (int i = 0; i < mocca.length; i++) {
+ System.out.print((char) mocca[i]);
+ }
+// for (int i = 0; i < mocca.length; i++) {
+// System.out.printf(" 0x%04x", mocca[i]);
+// }
+//
+ System.out.println("\n=============================\n");
+
+ }
+
+
+} \ No newline at end of file
diff --git a/BKUCommonGUI/src/test/resources/commons-logging.properties b/BKUCommonGUI/src/test/resources/commons-logging.properties
new file mode 100644
index 00000000..29292562
--- /dev/null
+++ b/BKUCommonGUI/src/test/resources/commons-logging.properties
@@ -0,0 +1 @@
+org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
diff --git a/BKUCommonGUI/src/test/resources/log4j.properties b/BKUCommonGUI/src/test/resources/log4j.properties
new file mode 100644
index 00000000..053eac17
--- /dev/null
+++ b/BKUCommonGUI/src/test/resources/log4j.properties
@@ -0,0 +1,19 @@
+# loglever DEBUG, appender STDOUT
+log4j.rootLogger=TRACE, STDOUT
+#log4j.logger.at.gv.egiz.slbinding.RedirectEventFilter=DEBUG, STDOUT
+
+# STDOUT appender
+log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
+log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
+#log4j.appender.STDOUT.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %20c | %10t | %m%n
+#log4j.appender.STDOUT.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
+log4j.appender.STDOUT.layout.ConversionPattern=%-5p |%d | %t | %c %x- %m%n
+
+### FILE appender
+#log4j.appender.file=org.apache.log4j.RollingFileAppender
+#log4j.appender.file.maxFileSize=100KB
+#log4j.appender.file.maxBackupIndex=9
+#log4j.appender.file.File=egovbus_ca.log
+#log4j.appender.file.threshold=info
+#log4j.appender.file.layout=org.apache.log4j.PatternLayout
+#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n \ No newline at end of file