/*
* 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.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.CharArrayWriter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.swing.BorderFactory;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.xml.ws.soap.SOAPFaultException;
import kr.ac.kaist.resl.ClientPasswordCallback;
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.log4j.Logger;
import org.apache.ws.security.WSConstants;
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.util.DeserializerUtil;
import org.fosstrak.ale.util.SerializerUtil;
import org.fosstrak.ale.wsdl.aletm.epcglobal.ALETMServicePortType;
import org.fosstrak.ale.wsdl.aletm.epcglobal.ArrayOfString;
import org.fosstrak.ale.wsdl.aletm.epcglobal.DefineTMSpec;
import org.fosstrak.ale.wsdl.aletm.epcglobal.DuplicateNameExceptionResponse;
import org.fosstrak.ale.wsdl.aletm.epcglobal.EmptyParms;
import org.fosstrak.ale.wsdl.aletm.epcglobal.GetTMSpec;
import org.fosstrak.ale.wsdl.aletm.epcglobal.ImplementationExceptionResponse;
import org.fosstrak.ale.wsdl.aletm.epcglobal.NoSuchNameExceptionResponse;
import org.fosstrak.ale.wsdl.aletm.epcglobal.SecurityExceptionResponse;
import org.fosstrak.ale.wsdl.aletm.epcglobal.TMSpecValidationExceptionResponse;
import org.fosstrak.ale.wsdl.aletm.epcglobal.UndefineTMSpec;
import org.fosstrak.ale.xsd.ale.epcglobal.TMFixedFieldListSpec;
import org.fosstrak.ale.xsd.ale.epcglobal.TMSpec;
import org.fosstrak.ale.xsd.ale.epcglobal.TMVariableFieldListSpec;
/**
* This class implements a graphical user interface for the application level
* events client. The client send all commands as SOAP messages to the ale
* server. The configuration of this class is described in the file
* ALEClient.properties. The most important parameter is the parameter endpoint,
* which specifies the address of the ale webservice which runs on the server.
*
* @author regli
* @author swieland
*/
public class ALETMClient extends AbstractTab {
/** serial version uid */
private static final long serialVersionUID = 1L;
/**
* endpoint parameter for the configuration.
*/
public static final String CFG_ENDPOINT = "org.fosstrak.ale.client.aletm.endpoint";
/**
* text field which contains the notification uri.
*/
private JTextField m_notificationUriField;
/**
* if the user checks this combo box, then an event sink is created for the subscription.
*/
private JCheckBox m_createEventSink;
/**
* text field which contains the reader name.
*/
private JTextField m_specNameValueField;
/**
* combobox which contains all defined subscribers for a selected event cycle.
*/
private JComboBox m_subscribersComboBox;
// logger.
private static final Logger s_log = Logger.getLogger(ALETMClient.class);
private static final int CMD__DEFINE_TMSPEC = 1;
private static final int CMD__UNDEFINE_TMSPEC = 2;
private static final int CMD__GET_TMSPEC = 3;
private static final int CMD__GET_TMSPEC_NAMES = 4;
private static final int CMD__GET_STANDARD_VERSION = 5;
private static final int CMD__GET_VENDOR_VERSION = 6;
/**
* @param parent the parent frame.
* @throws NoSuchMethodException given to the fact that we need to pass in a test method via reflection.
* @throws SecurityException given to the fact that we need to pass in a test method via reflection.
*/
public ALETMClient(JFrame parent) throws SecurityException, NoSuchMethodException {
super(ALETMServicePortType.class, CFG_ENDPOINT, parent, ALETMServicePortType.class.getMethod("getStandardVersion", EmptyParms.class), new EmptyParms());
}
@Override
public String getBaseNameKey() {
return "org.fosstrak.ale.client.ale.lang.base";
}
@Override
protected void setCommandPanel(int command) {
if (command == CMD__UNDEFINED_COMMAND) {
m_commandPanel.removeAll();
m_commandPanel.setBorder(null);
this.setVisible(false);
this.setVisible(true);
return;
}
m_commandPanel.setBorder(BorderFactory.createCompoundBorder(BorderFactory
.createTitledBorder(m_guiText.getString("Command" + command)),
BorderFactory.createEmptyBorder(5, 5, 5, 5)));
m_commandPanel.removeAll();
switch (command) {
case CMD__GET_TMSPEC_NAMES: // getECSpecNames
case CMD__GET_STANDARD_VERSION: // getStandardVersion
case CMD__GET_VENDOR_VERSION: // getVendorVersion
m_commandPanel.setLayout(new GridLayout(1, 1, 5, 0));
break;
case CMD__UNDEFINE_TMSPEC: // undefine
case CMD__GET_TMSPEC: // getECSpec
m_commandPanel.setLayout(new GridLayout(5, 1, 5, 0));
addECSpecNameComboBox(m_commandPanel);
addSeparator(m_commandPanel);
break;
case CMD__DEFINE_TMSPEC: // define
m_commandPanel.setLayout(new GridLayout(8, 1, 5, 0));
addSpecNameValueField(m_commandPanel);
addChooseFileField(m_commandPanel);
addSeparator(m_commandPanel);
break;
}
m_commandPanel.setFont(m_font);
addExecuteButton(m_commandPanel);
validate();
this.setVisible(true);
}
/**
* This method adds a specification name combobox to the panel.
*
* @param panel to which the specification name combobox should be added
*/
private void addECSpecNameComboBox(JPanel panel) {
m_specNameComboBox = new JComboBox();
m_specNameComboBox.setFont(m_font);
m_specNameComboBox.setEditable(false);
List<String> ecSpecNames = null;
try {
ecSpecNames = getAletmServiceProxy().getTMSpecNames(new EmptyParms()).getString();
} catch (Exception e) {
}
if (ecSpecNames != null && ecSpecNames.size() > 0) {
for (String specName : ecSpecNames) {
m_specNameComboBox.addItem(specName);
}
} else {
m_specNameComboBox.addItem("no specs defined");
}
JLabel lbl = new JLabel(m_guiText.getString("SpecNameLabel"));
lbl.setFont(m_font);
panel.add(lbl);
panel.add(m_specNameComboBox);
}
/**
* This method adds a notification property value field to the panel.
*
* @param panel to which the property value field should be added
*/
private void addSpecNameValueField(JPanel panel) {
m_specNameValueField = new JTextField();
m_specNameValueField.setFont(m_font);
JLabel lbl = new JLabel(m_guiText.getString("SpecNameLabel"));
lbl.setFont(m_font);
panel.add(lbl);
panel.add(m_specNameValueField);
}
/**
* This method adds a notification uri field to the panel.
*
* @param panel to which the norification uri field should be added
*/
private void addNotificationURIField(JPanel panel) {
m_notificationUriField = new JTextField();
m_notificationUriField.setFont(m_font);
JLabel lbl = new JLabel(m_guiText.getString("NotificationURILabel"));
lbl.setFont(m_font);
panel.add(lbl);
panel.add(m_notificationUriField);
}
@Override
protected void executeCommand() {
Object result = null;
String specName = null;
String notificationURI = null;
Exception ex = null;
try {
switch (m_commandSelection.getSelectedIndex()) {
case CMD__GET_TMSPEC_NAMES: // getECSpecNames
result = getAletmServiceProxy().getTMSpecNames(new EmptyParms());
break;
case CMD__GET_STANDARD_VERSION: // getStandardVersion
result = getAletmServiceProxy().getStandardVersion(new EmptyParms());
break;
case CMD__GET_VENDOR_VERSION: // getVendorVersion
result = getAletmServiceProxy().getVendorVersion(new EmptyParms());
break;
case CMD__UNDEFINE_TMSPEC: // undefine
case CMD__GET_TMSPEC: // getECSpec
// get specName
specName = (String) m_specNameComboBox.getSelectedItem();
if (specName == null || "".equals(specName)) {
FosstrakAleClient.instance().showExceptionDialog(
m_guiText.getString("SpecNameNotSpecifiedDialog"));
break;
}
switch (m_commandSelection.getSelectedIndex()) {
case CMD__UNDEFINE_TMSPEC: // undefine
UndefineTMSpec undefineParms = new UndefineTMSpec();
undefineParms.setSpecName(specName);
getAletmServiceProxy().undefineTMSpec(undefineParms);
result = m_guiText.getString("SuccessfullyUndefinedMessage");
break;
case CMD__GET_TMSPEC: // getECSpec
GetTMSpec getTMSpecParms = new GetTMSpec();
getTMSpecParms.setSpecName(specName);
result = getAletmServiceProxy().getTMSpec(getTMSpecParms);
break;
}
break;
case CMD__DEFINE_TMSPEC: // defineTmspec
if (m_commandSelection.getSelectedIndex() == CMD__DEFINE_TMSPEC) {
// get specName
specName = m_specNameValueField.getText();
if (specName == null || "".equals(specName)) {
FosstrakAleClient.instance().showExceptionDialog(m_guiText.getString("SpecNameNotSpecifiedDialog"));
break;
}
}
// get filePath
String filePath = m_filePathField.getText();
if (filePath == null || "".equals(filePath)) {
FosstrakAleClient.instance().showExceptionDialog(m_guiText.getString("FilePathNotSpecifiedDialog"));
break;
}
// get ecSpec
TMSpec tmSpec;
try {
tmSpec = getTMSpecFromFile(filePath);
} catch (FileNotFoundException e) {
FosstrakAleClient.instance().showExceptionDialog(m_guiText.getString("FileNotFoundDialog"));
ex = e;
break;
} catch (Exception e) {
FosstrakAleClient.instance().showExceptionDialog(m_guiText.getString("UnexpectedFileFormatDialog"));
ex = e;
break;
}
if (m_commandSelection.getSelectedIndex() == CMD__DEFINE_TMSPEC) {
DefineTMSpec defineParms = new DefineTMSpec();
defineParms.setSpecName(specName);
defineParms.setSpec(tmSpec);
getAletmServiceProxy().defineTMSpec(defineParms);
result = m_guiText.getString("SuccessfullyDefinedMessage");
}
break;
}
} catch (Exception e) {
String reason = e.getMessage();
String text = "Unknown Error";
if (e instanceof DuplicateNameExceptionResponse) {
text = m_guiText.getString("DuplicateNameExceptionDialog");
} else if (e instanceof TMSpecValidationExceptionResponse) {
text = m_guiText.getString("ECSpecValidationExceptionDialog");
} else if (e instanceof ImplementationExceptionResponse) {
text = m_guiText.getString("ImplementationExceptionDialog");
} else if (e instanceof NoSuchNameExceptionResponse) {
text = m_guiText.getString("NoSuchNameExceptionDialog");
} else if (e instanceof SecurityExceptionResponse) {
text = m_guiText.getString("SecurityExceptionDialog");
} else if (e instanceof SOAPFaultException) {
text = "Service error";
} else if (e instanceof FosstrakAleClientServiceDownException) {
text = "Unable to execute command.";
reason = "Service is down or endpoint wrong.";
}
FosstrakAleClient.instance().showExceptionDialog(text, reason);
ex = e;
}
if (null == ex) {
showResult(result);
} else {
showResult(ex);
}
// update spec name combobox
List<String> ecSpecNames = null;
try {
ecSpecNames = getAletmServiceProxy().getTMSpecNames(new EmptyParms()).getString();
} catch (Exception e) {
}
if (ecSpecNames != null && m_specNameComboBox != null
&& m_specNameComboBox.getSelectedObjects() != null
&& m_specNameComboBox.getSelectedObjects().length > 0) {
String current = (String) m_specNameComboBox.getSelectedObjects()[0];
m_specNameComboBox.removeAllItems();
if (ecSpecNames != null && ecSpecNames.size() > 0) {
for (String name : ecSpecNames) {
m_specNameComboBox.addItem(name);
}
}
m_specNameComboBox.setSelectedItem(current);
}
}
/**
* creates an event sink from a given url.
* @param text
*/
private void createEventSink(String eventSinkURL) {
try {
EventSink sink = new EventSink(eventSinkURL);
FosstrakAleClient.instance().addTab(eventSinkURL, sink);
} catch (Exception e) {
s_log.error("Could not start requested event sink.");
e.printStackTrace();
}
}
/**
* This method loads the ec specification from a file.
*
* @param filename of ec specification file
* @return ec specification
* @throws Exception if specification could not be loaded
*/
private TMSpec getTMSpecFromFile(String filename) throws Exception {
FileInputStream inputStream = new FileInputStream(filename);
return DeserializerUtil.deserializeTMSpec(inputStream);
}
@Override
protected void decodeResult(StringBuffer sb, Object result) {
if (result instanceof ArrayOfString) {
ArrayOfString resultStringArray = (ArrayOfString) result;
if (resultStringArray.getString().size() == 0) {
sb.append(m_guiText.getString("EmptyArray"));
} else {
for (String s : resultStringArray.getString()) {
sb.append(s);
sb.append("\n");
}
}
} else if (result instanceof TMFixedFieldListSpec) {
CharArrayWriter writer = new CharArrayWriter();
try {
SerializerUtil.serializeTMFixedFieldListSpec((TMFixedFieldListSpec) result, writer);
} catch (Exception e) {
FosstrakAleClient.instance().showExceptionDialog(m_guiText.getString("SerializationExceptionMessage"));
}
sb.append(writer.toString());
} else if (result instanceof TMVariableFieldListSpec) {
CharArrayWriter writer = new CharArrayWriter();
try {
SerializerUtil.serializeTMVariableFieldListSpec((TMVariableFieldListSpec) result, writer);
} catch (Exception e) {
FosstrakAleClient.instance().showExceptionDialog(m_guiText.getString("SerializationExceptionMessage"));
}
sb.append(writer.toString());
}
}
@Override
protected String[] getCommands() {
String[] commands = new String[11];
for (int i = 1; i < 12; i++) {
commands[i - 1] = m_guiText.getString("Command" + i);
}
return commands;
}
/**
* @return returns the proxy object already casted.
*/
protected ALETMServicePortType getAletmServiceProxy() throws FosstrakAleClientException {
return (ALETMServicePortType) getProxy();
}
}