diff options
Diffstat (limited to 'BKUCommonGUI/src/main/java')
5 files changed, 343 insertions, 29 deletions
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 index 5de6a9e0..c128ceab 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIFacade.java @@ -24,8 +24,10 @@ package at.gv.egiz.bku.gui; - import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.bku.gui.hashdata.HashDataInputLoader; import at.gv.egiz.smcc.PinInfo; + import at.gv.egiz.stal.HashDataInput; + import java.awt.Color; import java.awt.event.ActionListener; import java.util.List; @@ -67,6 +69,7 @@ public interface BKUGUIFacade { 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_OVERRULE_PINPAD = "title.overrule.pinpad"; 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"; @@ -74,6 +77,7 @@ public interface BKUGUIFacade { 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_BULKSIGNATURE = "title.bulksign"; 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"; @@ -89,6 +93,7 @@ public interface BKUGUIFacade { 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_OVERRULE_PINPAD = "overrule.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"; @@ -103,6 +108,7 @@ public interface BKUGUIFacade { 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 MESSAGE_BULKSIGN = "bulksign"; public static final String WARNING_XHTML = "warning.xhtml"; public static final String WARNING_CERT_NOTYETVALID = "warning.cert.notyetvalid"; @@ -165,6 +171,11 @@ public interface BKUGUIFacade { ActionListener cancelListener, String cancelCommand, ActionListener viewerListener, String viewerCommand); + public void showSignaturePINDialog(PinInfo pinSpec, int numRetries, int numSignatures, + ActionListener signListener, String signCommand, + ActionListener cancelListener, String cancelCommand, + ActionListener viewerListener, String viewerCommand); + public char[] getPin(); /** @@ -176,7 +187,7 @@ public interface BKUGUIFacade { * @param backCommand */ public void showSecureViewer(List<HashDataInput> dataToBeSigned, - ActionListener backListener, String backCommand); + ActionListener backListener, String backCommand, HashDataInputLoader hashDataInputLoader); public void showErrorDialog(String errorMsgKey, Object[] errorMsgParams, ActionListener okListener, String okCommand); @@ -196,8 +207,14 @@ public interface BKUGUIFacade { public void showMessageDialog(String titleKey, String msgKey, Object[] msgParams); + void updateMessageDialog(String titleKey, + String msgKey, Object[] msgParams, String buttonKey, ActionListener okListener, String okCommand); + public void showMessageDialog(String titleKey, String msgKey); public void getFocusFromBrowser(); + + public void showPinPadDeactivationDialog(ActionListener okListener, String okCommand, + ActionListener cancelListener, String cancelCommand); } 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 index 82513a0e..13e330bf 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java @@ -25,6 +25,7 @@ package at.gv.egiz.bku.gui; +import at.gv.egiz.bku.gui.hashdata.HashDataInputLoader; import at.gv.egiz.bku.gui.viewer.FontProviderException; import at.gv.egiz.bku.gui.viewer.FontProvider; import at.gv.egiz.bku.gui.viewer.SecureViewerSaveDialog; @@ -67,6 +68,7 @@ import javax.swing.JPasswordField; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.LayoutStyle; +import javax.swing.LayoutStyle.ComponentPlacement; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.UIManager; @@ -90,7 +92,7 @@ public class BKUGUIImpl implements BKUGUIFacade { } protected Component primaryFocusHolder; - protected SecureViewerDialog secureViewer; + protected SecureViewerDialog secureViewerDialog; protected HelpListener helpListener; protected FontProvider fontProvider; @@ -155,7 +157,9 @@ public class BKUGUIImpl implements BKUGUIFacade { // protected HashDataInput storedSelection; protected List<HashDataInput> signedReferences; protected Integer referenceIndex; - private at.gv.egiz.bku.gui.BKUGUIImpl.SignedReferencesSelectionListener.SignedReferencesListDisplayer storedBackToListListener; + protected at.gv.egiz.bku.gui.BKUGUIImpl.SignedReferencesSelectionListener.SignedReferencesListDisplayer storedBackToListListener; + + protected HashDataInputLoader hashDataInputLoader; /** * set contentPane init message bundle configure the style register the help @@ -1205,6 +1209,15 @@ public class BKUGUIImpl implements BKUGUIFacade { final ActionListener signListener, final String signCommand, final ActionListener cancelListener, final String cancelCommand, final ActionListener hashdataListener, final String hashdataCommand) { + showSignaturePINDialog(pinSpec, numRetries, 1, signListener, signCommand, cancelListener, cancelCommand, + hashdataListener, hashdataCommand); + } + + @Override + public void showSignaturePINDialog(final PinInfo pinSpec, final int numRetries, final int numSignatures, + final ActionListener signListener, final String signCommand, + final ActionListener cancelListener, final String cancelCommand, + final ActionListener hashdataListener, final String hashdataCommand) { log.debug("Scheduling signature-pin dialog."); @@ -1228,7 +1241,9 @@ public class BKUGUIImpl implements BKUGUIFacade { if (renderHeaderPanel) { if (numRetries < 0) { - titleLabel.setText(getMessage(TITLE_SIGN)); + String msgPattern = getMessage(TITLE_SIGN); + String msg = MessageFormat.format(msgPattern, numSignatures); + titleLabel.setText(msg); } else { titleLabel.setText(getMessage(TITLE_RETRY)); } @@ -1571,6 +1586,35 @@ public class BKUGUIImpl implements BKUGUIFacade { showMessageDialog(titleKey, null, msgKey, msgParams, null, null, null); } + + @Override + public void updateMessageDialog(final String titleKey, final String msgKey, + final Object[] msgParams, String buttonKey, + final ActionListener okListener, final String okCommand) { + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + log.debug("[{}] Update message dialog.", Thread.currentThread().getName()); + + + if (renderHeaderPanel) { + titleLabel.setText(getMessage(titleKey)); + } + + helpListener.setHelpTopic(msgKey); + + String msgPattern = getMessage(msgKey); + String msg = MessageFormat.format(msgPattern, msgParams); + + msgLabel.setText(msg); + + } + }); + } + @Override public void showMessageDialog(final String titleKey, final String msgKey) { @@ -1718,6 +1762,158 @@ public class BKUGUIImpl implements BKUGUIFacade { }); } + + private void showOptionDialog(final String titleKey, final String msgKey, final Object[] msgParams, + final String cancelButtonKey, final String okButtonKey, final ActionListener cancelListener, + final String cancelCommand, final ActionListener okListener, final String okCommand) { + + log.debug("Scheduling message dialog."); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + + log.debug("[{}] Show option dialog.", Thread.currentThread().getName()); + + log.debug("ButtonKey: {}.", okButtonKey); + + log.debug("ButtonKey: {}.", cancelButtonKey); + + mainPanel.removeAll(); + buttonPanel.removeAll(); + + if (renderHeaderPanel) { + titleLabel.setText(getMessage(titleKey)); + } + + helpListener.setHelpTopic(msgKey); + + String msgPattern = getMessage(msgKey); + String msg = MessageFormat.format(msgPattern, msgParams); + + // we need to create a new JLabel object every time in order to + // ensure + // that screen reading software will read each updated label + msgLabel = new JLabel(); + + msgLabel.setFocusable(true); + + 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(); + + String accessibleData = ""; + + if (!renderHeaderPanel) { + msgTitleLabel = new JLabel(); + msgTitleLabel.setFont(msgTitleLabel.getFont().deriveFont( + msgTitleLabel.getFont().getStyle() | Font.BOLD)); + msgTitleLabel.setText(getMessage(titleKey)); + + accessibleData = accessibleData + getMessage(titleKey); + + GroupLayout.SequentialGroup titleHorizontal = mainPanelLayout + .createSequentialGroup() + .addComponent(msgTitleLabel); + + GroupLayout.ParallelGroup titleVertical = mainPanelLayout + .createParallelGroup(GroupLayout.Alignment.LEADING) + .addComponent(msgTitleLabel); + + if (helpListener.implementsListener()) { + titleHorizontal.addPreferredGap( + LayoutStyle.ComponentPlacement.UNRELATED, 0, + Short.MAX_VALUE).addComponent(helpLabel); + titleVertical.addComponent(helpLabel); + } + + mainHorizontal.addGroup(titleHorizontal); + mainVertical.addGroup(titleVertical); + + } else { + + accessibleData = accessibleData + titleLabel.getText(); + } + + msgLabel.getAccessibleContext().setAccessibleName( + accessibleData + msgLabel.getText()); + msgLabel.getAccessibleContext().setAccessibleDescription( + accessibleData + msgLabel.getText()); + + mainPanelLayout.setHorizontalGroup(mainHorizontal + .addComponent(msgLabel)); + mainPanelLayout.setVerticalGroup(mainVertical + .addComponent(msgLabel)); + + + cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + cancelButton.setText(getMessage((cancelButtonKey != null) ? cancelButtonKey : BUTTON_CANCEL)); + cancelButton.setActionCommand(okCommand); + cancelButton.addActionListener(okListener); + + okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); + okButton.setText(getMessage((okButtonKey != null) ? okButtonKey : BUTTON_OK)); + okButton.setActionCommand(cancelCommand); + okButton.addActionListener(okListener); + + primaryFocusHolder = okButton; + + renderShowOptionDialogueButtonPanel(); + + 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)); + + // okListener might be null (up to windowCloseAdapter what to do) + if (windowCloseAdapter != null) { + windowCloseAdapter.registerListener(okListener, okCommand); + } + + updateMethodToRunAtResize("at.gv.egiz.bku.gui.BKUGUIImpl", + "renderShowOptionDialogueButtonPanel"); + + // put focus to msgLabel to guarantee that label is read by + // screen reader upon loading + msgLabel.requestFocus(); + msgLabel.setFocusable(false); + + contentPanel.validate(); + + resize(); + } + }); + } + + + public void renderShowOptionDialogueButtonPanel() { + + GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); + buttonPanel.setLayout(buttonPanelLayout); + + buttonPanelLayout.setHorizontalGroup(buttonPanelLayout.createSequentialGroup() + .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(ComponentPlacement.UNRELATED)); + + buttonPanelLayout.setVerticalGroup(buttonPanelLayout.createParallelGroup().addComponent(cancelButton).addComponent(okButton)); + +} + public void renderShowMessageDialogueButtonPanel() { if (showMessageOKButton) { @@ -1757,7 +1953,9 @@ public class BKUGUIImpl implements BKUGUIFacade { */ @Override public void showSecureViewer(final List<HashDataInput> dataToBeSigned, - final ActionListener backListener, final String backCommand) { + final ActionListener backListener, final String backCommand, HashDataInputLoader hashDataInputLoader) { + + this.hashDataInputLoader = hashDataInputLoader; if (dataToBeSigned == null) { showErrorDialog(getMessage(ERR_NO_HASHDATA), @@ -1819,7 +2017,7 @@ public class BKUGUIImpl implements BKUGUIFacade { throws FontProviderException { log.debug("[{}] Show secure viewer.", Thread.currentThread().getName()); - secureViewer = new SecureViewerDialog(null, messages, closeListener, + secureViewerDialog = new SecureViewerDialog(null, messages, closeListener, closeCommand, fontProvider, helpListener, getResizeFactor()); // workaround for [#439] @@ -1829,56 +2027,55 @@ public class BKUGUIImpl implements BKUGUIFacade { //Window window = SwingUtilities.getWindowAncestor(contentPane); //if (window != null && window.isAlwaysOnTop()) { log.debug("Make secureViewer alwaysOnTop."); - secureViewer.setAlwaysOnTop(true); + secureViewerDialog.setAlwaysOnTop(true); //} - secureViewer.setContent(dataToBeSigned); + secureViewerDialog.setContent(dataToBeSigned); log.trace("Viewer setContent returned."); } private void openSecureViewerDialog() { - final HashDataInput storedSelection = signedReferences.get(referenceIndex); + try { + + log.trace("Opening SecureViewer dialog for list entry {}", referenceIndex); + final HashDataInput storedSelection = hashDataInputLoader.getHashDataInput(signedReferences.get(referenceIndex)); - if (SecureViewerDialog.SUPPORTED_MIME_TYPES.contains(storedSelection - .getMimeType())) { + if (SecureViewerDialog.SUPPORTED_MIME_TYPES.contains(storedSelection.getMimeType())) { log.debug("[{}] Scheduling secure viewer dialog.", Thread.currentThread().getName()); - showMessageDialog(TITLE_SIGNATURE_DATA, - MESSAGE_HASHDATA_VIEWER); + showMessageDialog(TITLE_SIGNATURE_DATA, MESSAGE_HASHDATA_VIEWER); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { try { - showSecureViewer(storedSelection, storedBackToListListener, - null); + showSecureViewer(storedSelection, storedBackToListListener, 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() }, - storedBackToListListener, null); + showErrorDialog(BKUGUIFacade.ERR_VIEWER, new Object[] { ex.getMessage() }, storedBackToListListener, null); } } }); } else { - log.debug("[{}] Mime-type not supported by secure viewer, " + - "scheduling save dialog.", Thread.currentThread().getName()); - showMessageDialog(BKUGUIFacade.TITLE_SIGNATURE_DATA, - BKUGUIFacade.MESSAGE_UNSUPPORTED_MIMETYPE, + log.debug("[{}] Mime-type not supported by secure viewer, " + "scheduling save dialog.", Thread.currentThread() + .getName()); + showMessageDialog(BKUGUIFacade.TITLE_SIGNATURE_DATA, BKUGUIFacade.MESSAGE_UNSUPPORTED_MIMETYPE, new Object[] { storedSelection.getMimeType() }); - SecureViewerSaveDialog.showSaveDialog(contentPane, storedSelection, messages, - storedBackToListListener, null, + SecureViewerSaveDialog.showSaveDialog(contentPane, storedSelection, messages, storedBackToListListener, null, (int) (baseFontSize * getResizeFactor())); } - + } catch (Exception ex) { + log.error("Failed to display secure viewer.", ex); + showErrorDialog(BKUGUIFacade.ERR_VIEWER, new Object[] { ex.getMessage() }, storedBackToListListener, null); + } } private void showSignedReferencesListDialog( @@ -2446,9 +2643,9 @@ public class BKUGUIImpl implements BKUGUIFacade { } - if (secureViewer != null && secureViewer.isVisible()) { + if (secureViewerDialog != null && secureViewerDialog.isVisible()) { - secureViewer.resize(factor); + secureViewerDialog.resize(factor); } try { @@ -2682,4 +2879,12 @@ public class BKUGUIImpl implements BKUGUIFacade { } } } + + @Override + public void showPinPadDeactivationDialog(ActionListener okListener, String okCommand, ActionListener cancelListener, + String cancelCommand) { + + showOptionDialog(TITLE_OVERRULE_PINPAD, MESSAGE_OVERRULE_PINPAD, null, null, null, cancelListener, cancelCommand, okListener, okCommand); + + } } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/hashdata/HashDataInputLoader.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/hashdata/HashDataInputLoader.java new file mode 100644 index 00000000..1946dd2d --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/hashdata/HashDataInputLoader.java @@ -0,0 +1,16 @@ +package at.gv.egiz.bku.gui.hashdata; + +import at.gv.egiz.stal.HashDataInput; + +public interface HashDataInputLoader { + + + + /** + * Loads input data of referenced HashDataInput. + * @param hashDataInput HashDataInput without content that references a HashDataInput at server side with digest or referenceId. + * @return HashDataInput Referenced HashDataInput from server-side including content. + * @throws Exception + */ + HashDataInput getHashDataInput(HashDataInput hashDataInput) throws Exception; +} diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/SecureViewer.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/SecureViewer.java new file mode 100644 index 00000000..02e0ceb8 --- /dev/null +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/viewer/SecureViewer.java @@ -0,0 +1,58 @@ +/* + * Copyright 2011 by Graz University of Technology, Austria + * MOCCA has been developed by the E-Government Innovation Center EGIZ, a joint + * initiative of the Federal Chancellery Austria and Graz University of Technology. + * + * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by + * the European Commission - subsequent versions of the EUPL (the "Licence"); + * You may not use this work except in compliance with the Licence. + * You may obtain a copy of the Licence at: + * http://www.osor.eu/eupl/ + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the Licence is distributed on an "AS IS" basis, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the Licence for the specific language governing permissions and + * limitations under the Licence. + * + * This product combines work with different licenses. See the "NOTICE" text + * file for details on the various modules and licenses. + * The "NOTICE" text file is part of the distribution. Any derivative works + * that you distribute must include a readable copy of the "NOTICE" text file. + */ + + +package at.gv.egiz.bku.gui.viewer; + +import at.gv.egiz.stal.SignatureInfo; + +import java.awt.event.ActionListener; +import java.util.List; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public interface SecureViewer { + + /** + * Displays the hashdata inputs for all provided dsig:SignedReferences. + * Implementations may verify the digest value if necessary. + * (LocalSignRequestHandler operates on DataObjectHashDataInput, + * other SignRequestHandlers should cache the HashDataInputs obtained by webservice calls, + * or simply forward to a HashDataInputServlet.) + * @param signedReferences The caller may select a subset of the references in SignedInfo to be displayed. + * @throws java.security.DigestException if digest values are verified and do not correspond + * (or any other digest computation error occurs) + * @throws java.lang.Exception + */ + void displayDataToBeSigned(SignatureInfo signatureInfo, + ActionListener okListener, String okCommand) + throws Exception; + + + void displayDataToBeSigned(List<SignatureInfo> signatureInfo, + ActionListener okListener, String okCommand) + throws Exception; + +} 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 index a28b3b56..ecf5f364 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/stal/impl/ByteArrayHashDataInput.java @@ -41,6 +41,7 @@ public class ByteArrayHashDataInput implements HashDataInput { private final Logger log = LoggerFactory.getLogger(ByteArrayHashDataInput.class); protected byte[] hashData; + protected byte[] digest; protected String id; protected String mimeType; protected String encoding; @@ -57,6 +58,18 @@ public class ByteArrayHashDataInput implements HashDataInput { this.filename = filename; } + public ByteArrayHashDataInput(byte[] hashData, String id, String mimeType, String encoding, String filename, byte[] digest) { + if (hashData == null) { + throw new NullPointerException("HashDataInput not provided."); + } + this.hashData = hashData; + this.id = id; + this.mimeType = mimeType; + this.encoding = encoding; + this.filename = filename; + this.digest = digest; + } + /** * caches the hashdata input's stream * @param hdi to be cached @@ -65,9 +78,9 @@ public class ByteArrayHashDataInput implements HashDataInput { if (hdi == null) { throw new NullPointerException("HashDataInput not provided."); } + try { 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); @@ -111,5 +124,10 @@ public class ByteArrayHashDataInput implements HashDataInput { return filename; } + @Override + public byte[] getDigest() { + return digest; + } + } |