/* * Copyright (C) 2014 KAIST * @author Janggwan Im <limg00n@kaist.ac.kr> * * Copyright (C) 2007 ETH Zurich * * This file is part of Fosstrak (www.fosstrak.org). * * Fosstrak is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License version 2.1, as published by the Free Software Foundation. * * Fosstrak is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with Fosstrak; if not, write to the Free * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301 USA */ package org.fosstrak.ale.client.tabs; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.FileDialog; import java.awt.Font; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.io.IOException; import java.io.InputStream; import java.lang.reflect.Method; import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.PropertyResourceBundle; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JComboBox; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JLayeredPane; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JSeparator; import javax.swing.JTextArea; import javax.swing.JTextField; import javax.swing.border.EmptyBorder; import org.apache.cxf.endpoint.Client; import org.apache.cxf.endpoint.Endpoint; import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor; import org.apache.ws.security.WSConstants; import org.apache.ws.security.WSPasswordCallback; import org.apache.ws.security.handler.WSHandlerConstants; import org.fosstrak.ale.client.FosstrakAleClient; import org.fosstrak.ale.client.exception.FosstrakAleClientException; import org.fosstrak.ale.client.exception.FosstrakAleClientServiceDownException; import org.fosstrak.ale.wsdl.aletm.epcglobal.ALETMServicePortType; /** * @author swieland * * abstract super class for all the sub tabs in the GUI. the class provides helper * methods to maintain the service proxy, default panels, ... */ public abstract class AbstractTab extends JPanel { /** * serial version uid. */ private static final long serialVersionUID = 1L; /** * system default language. */ private static final Locale SYSTEM_DEFAULT_LOCALE = Locale.getDefault(); /** * default language (if language is not defined in property file and system default language does not exists). */ private static final Locale DEFAULT_LOCALE = Locale.ENGLISH; /** * index of the undefined command. */ protected static final int CMD__UNDEFINED_COMMAND = -1; /** * the proxy object. */ protected Object m_proxy; /** * test method to call for the connection establishment test. */ final protected Method m_testMethod; /** * parameter object for the test method call. */ final protected Object m_testMethodParameter; /** * class of the proxy stub. */ protected final Class<?> m_clzz; /** * key to the endpoint in the properties. */ protected final String m_endpointKey; /** * parent frame. */ protected final JFrame m_parent; /** * resource bundle containing all user visible texts in specified language. */ protected PropertyResourceBundle m_guiText; /** * text area which contains the results. */ protected final JTextArea m_resultTextArea = new JTextArea(17, 30); /** * panel which contains the command panel. */ protected final JPanel m_commandSuperPanel = new JPanel(); /** * scroll pane which contains the result text area. */ protected final JScrollPane m_resultScrollPane = new JScrollPane(m_resultTextArea, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED); /** * command panel. */ protected final JPanel m_commandPanel = new JPanel(); /** * combobox which contains all defined specification names. */ protected JComboBox m_specNameComboBox; /** * combobox which contains all possible commands. */ protected final JComboBox m_commandSelection = new JComboBox(); /** * panel which contains the execute button. */ protected JPanel m_execButtonPanel = null; /** * text field which contains the file path. */ protected JTextField m_filePathField; /** * the font to be used for all components. */ protected final Font m_font; /** * * @param clzz the class of the proxy stub. * @param endpointKey key to the endpoint in the properties. * @param parent the parent frame. */ public AbstractTab(Class<?> clzz, String endpointKey, JFrame parent, Method testMethod, Object testMethodParameter) { m_clzz = clzz; m_endpointKey = endpointKey; m_parent = parent; m_testMethod = testMethod; m_testMethodParameter = testMethodParameter; m_font = FosstrakAleClient.instance().getConfiguration().getFont(); } /** * @return the proxy object. if null, display the connect dialog. */ protected Object getProxy() throws FosstrakAleClientException { if (null == m_proxy) { // display the connect dialog String address = FosstrakAleClient.instance().showConnectDialog(m_endpointKey); // create the proxy object. String userId = FosstrakAleClient.instance().getConfiguration().getProperty("userId"); JaxWsProxyFactoryBean factory; factory = new JaxWsProxyFactoryBean(); factory.setServiceClass(ALETMServicePortType.class); factory.setAddress(address); Object toReturn = factory.create(); CallbackHandler cpc = new CallbackHandler() { @Override public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { WSPasswordCallback pc = (WSPasswordCallback)callbacks[0]; String password = FosstrakAleClient.instance().getConfiguration().getProperty("password"); pc.setPassword(password); } }; Map<String, Object> outProps = new HashMap<String, Object>(); outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN); outProps.put(WSHandlerConstants.USER, userId); outProps.put(WSHandlerConstants.PW_CALLBACK_REF, cpc); outProps.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT); WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(outProps); Client c = ClientProxy.getClient(toReturn); Endpoint cxfEndpoint = c.getEndpoint(); cxfEndpoint.getOutInterceptors().add(wssOut); m_proxy = toReturn; // we try to perform a test method call. // if that call fails, we assume the connection to be daad. try { m_testMethod.invoke(m_proxy, m_testMethodParameter); } catch (Exception e) { m_proxy = null; throw new FosstrakAleClientServiceDownException(e); } } return m_proxy; } /** * @return the key for the base name of the language files (eg /props/ALEClient). */ abstract protected String getBaseNameKey(); /** * This method initializes the class, by loading properties and texts. * * @throws FosstrakAleClientException when the language files could not be loaded. */ public void initialize() throws FosstrakAleClientException { String baseNameKey = getBaseNameKey(); try { // get the base name (eg /props/ALEClient String baseName = FosstrakAleClient.instance().getConfiguration().getProperty(baseNameKey); // load text InputStream languageStream = null; // try to get language form property file String language = FosstrakAleClient.instance().getConfiguration().getLanguage(); if (null != language) { languageStream = this.getClass().getResourceAsStream(String.format("%s_%s.lang", baseName, language)); } // try system default language if (languageStream == null) { languageStream = this.getClass().getResourceAsStream(String.format("%s_%s.lang", baseName, SYSTEM_DEFAULT_LOCALE.getLanguage())); } // try default language if (languageStream == null) { languageStream = this.getClass().getResourceAsStream(String.format("%s_%s.lang", baseName, DEFAULT_LOCALE.getLanguage())); } if (languageStream == null) { throw new IllegalArgumentException("Could not load language package from classpath (" + DEFAULT_LOCALE + ")"); } m_guiText = new PropertyResourceBundle(languageStream); initializeGUI(); } catch (Exception e) { throw new FosstrakAleClientException(e); } } /** * This method initializes the gui and set it visible. */ protected void initializeGUI() { this.setLayout(new GridLayout()); JLayeredPane contentPane = new JLayeredPane(); contentPane.setFont(m_font); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); add(contentPane); contentPane.setLayout(new BorderLayout(0, 0)); JLayeredPane leftPane = new JLayeredPane(); contentPane.add(leftPane, BorderLayout.WEST); leftPane.setFont(m_font); leftPane.setLayout(new BorderLayout()); leftPane.add(createCommandSelectionPanel(), BorderLayout.NORTH); leftPane.add(m_commandSuperPanel, BorderLayout.CENTER); contentPane.add(m_resultScrollPane, BorderLayout.CENTER); m_commandSuperPanel.setLayout(new BorderLayout()); m_commandSuperPanel.add(m_commandPanel, BorderLayout.NORTH); m_resultScrollPane.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(m_guiText.getString("ResultPanelTitle")), BorderFactory.createEmptyBorder(5,5,5,5))); m_resultTextArea.setEditable(false); m_commandSuperPanel.setFont(m_font); m_commandPanel.setFont(m_font); m_resultTextArea.setFont(m_font); this.setVisible(true); } /** * This method creates the command selection panel. * * @return command selection panel */ protected JPanel createCommandSelectionPanel() { JPanel selectionPanel = new JPanel(); selectionPanel.setLayout(new GridLayout(1,1)); selectionPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createTitledBorder(m_guiText.getString("SelectionPanelTitle")), BorderFactory.createEmptyBorder(5,5,5,5))); selectionPanel.setFont(m_font); m_commandSelection.addItem(null); m_commandSelection.setFont(m_font); for (String item : getCommands()) { m_commandSelection.addItem(item); } m_commandSelection.addActionListener(new ActionListener(){ public void actionPerformed(ActionEvent e) { if ("comboBoxChanged".equals(e.getActionCommand())) { setCommandPanel(m_commandSelection.getSelectedIndex()); } } }); selectionPanel.add(m_commandSelection); selectionPanel.setPreferredSize(new Dimension(200, 55)); return selectionPanel; } /** * This method sets the command selection panel depending on the command id. * * @param command id */ abstract protected void setCommandPanel(int command); /** * This method returns the names of all commands. * * @return command names */ abstract protected String[] getCommands(); /** * This method adds a execute button to the panel. * * @param panel to which the execute button should be added */ protected void addExecuteButton(JPanel panel) { if (m_execButtonPanel == null) { JButton execButton = new JButton(m_guiText .getString("ExecuteButtonLabel")); execButton.setFont(m_font); execButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { executeCommand(); } }); m_execButtonPanel = new JPanel(); m_execButtonPanel.setFont(m_font); m_execButtonPanel.setLayout(new GridLayout(1, 3)); m_execButtonPanel.add(new JPanel()); m_execButtonPanel.add(execButton); m_execButtonPanel.add(new JPanel()); } panel.add(m_execButtonPanel); } /** * This method executes the command which is selected in the command * selection combobox with the parameters which are set in the corresponding * fields. To execute the commands, the methods of the proxy will be * invoked. */ abstract protected void executeCommand(); /** * This method adds a choose file field to the panel. * * @param panel to which the choose file field should be added */ protected void addChooseFileField(JPanel panel) { m_filePathField = new JTextField(); m_filePathField.setFont(m_font); final FileDialog fileDialog = new FileDialog(m_parent); fileDialog.setModal(true); fileDialog.addComponentListener( new ComponentAdapter() { public void componentHidden(ComponentEvent e) { if (fileDialog.getFile() != null) { m_filePathField.setText(fileDialog.getDirectory() + fileDialog.getFile()); } } }); final JButton chooseFileButton = new JButton(m_guiText.getString("ChooseFileButtonLabel")); chooseFileButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { fileDialog.setVisible(true); } }); chooseFileButton.setFont(m_font); JLabel lbl = new JLabel(m_guiText.getString("FilePathLabel")); lbl.setFont(m_font); panel.add(lbl); panel.add(m_filePathField); panel.add(chooseFileButton); } /** * This method adds a separator to the panel. * * @param panel to which the separator should be added */ protected void addSeparator(JPanel panel) { panel.add(new JPanel()); panel.add(new JSeparator()); } /** * This method displays the result in the result text area. * * @param result to display */ protected void showResult(Object result) { m_resultTextArea.setText(null); if (result instanceof String) { m_resultTextArea.append((String) result); } if (result instanceof Exception) { Exception e = (Exception) result; StringBuffer sb = new StringBuffer(); for (StackTraceElement line : e.getStackTrace()) { sb.append(line.toString()); sb.append("\n"); } m_resultTextArea.append(sb.toString()); }else { StringBuffer sb = new StringBuffer(); decodeResult(sb, result); m_resultTextArea.append(sb.toString()); } } /** * decodes the result object into the provided string buffer. * @param sb the string buffer where to store the result. * @param result the result object. */ abstract protected void decodeResult(StringBuffer sb, Object result); }