/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* 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 net.java.sip.communicator.plugin.loggingutils;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import net.java.sip.communicator.service.httputil.*;
import net.java.sip.communicator.service.notification.*;
import net.java.sip.communicator.util.Logger;
import net.java.sip.communicator.plugin.desktoputil.*;
import org.jitsi.service.packetlogging.*;
import org.jitsi.service.resources.*;
import org.jitsi.util.*;
/**
* The Logging configuration form.
* @author Damian Minkov
*/
public class LoggingConfigForm
extends TransparentPanel
implements ActionListener,
DocumentListener
{
/**
* Serial version UID.
*/
private static final long serialVersionUID = 0L;
/**
* Our Logger.
*/
private static final Logger logger
= Logger.getLogger(LoggingConfigForm.class);
/**
* Upload location property.
*/
private static final String UPLOAD_LOCATION_PROPETY =
"plugin.loggingutils.uploadlocation";
/**
* The enable packet logging check box.
*/
private JCheckBox enableCheckBox;
/**
* Check box to enable/disable packet debug of sip protocol.
*/
private JCheckBox sipProtocolCheckBox;
/**
* Check box to enable/disable packet debug of jabber protocol.
*/
private JCheckBox jabberProtocolCheckBox;
/**
* Check box to enable/disable packet debug of media protocol/RTP.
*/
private JCheckBox rtpProtocolCheckBox;
/**
* Check box to enable/disable packet debug of Ice4J.
*/
private JCheckBox ice4jProtocolCheckBox;
/**
* The file count label.
*/
private JLabel fileCountLabel;
/**
* The filed for file count value.
*/
private JTextField fileCountField = new JTextField();
/**
* The file size label.
*/
private JLabel fileSizeLabel;
/**
* The filed for file size value.
*/
private JTextField fileSizeField = new JTextField();
/**
* Notification event.
*/
private static final String LOGFILES_ARCHIVED = "LogFilesArchived";
/**
* Archive logs button.
*/
private JButton archiveButton;
/**
* Archive logs button.
*/
private JButton uploadLogsButton;
/**
* Creates Packet Logging Config form.
*/
public LoggingConfigForm()
{
super(new BorderLayout());
init();
loadValues();
// Register notification for saved calls.
if(LoggingUtilsActivator.getNotificationService() != null)
LoggingUtilsActivator.getNotificationService()
.registerDefaultNotificationForEvent(
LOGFILES_ARCHIVED,
NotificationAction.ACTION_POPUP_MESSAGE,
null,
null);
}
/**
* Creating the configuration form
*/
private void init()
{
ResourceManagementService resources =
LoggingUtilsActivator.getResourceService();
enableCheckBox = new SIPCommCheckBox(
resources.getI18NString("plugin.loggingutils.ENABLE_DISABLE"));
enableCheckBox.addActionListener(this);
sipProtocolCheckBox = new SIPCommCheckBox(
resources.getI18NString("plugin.sipaccregwizz.PROTOCOL_NAME"));
sipProtocolCheckBox.addActionListener(this);
jabberProtocolCheckBox = new SIPCommCheckBox(
resources.getI18NString("plugin.jabberaccregwizz.PROTOCOL_NAME"));
jabberProtocolCheckBox.addActionListener(this);
String rtpDescription = resources.getI18NString(
"plugin.loggingutils.PACKET_LOGGING_RTP_DESCRIPTION");
rtpProtocolCheckBox = new SIPCommCheckBox(
resources.getI18NString("plugin.loggingutils.PACKET_LOGGING_RTP")
+ " " + rtpDescription);
rtpProtocolCheckBox.addActionListener(this);
rtpProtocolCheckBox.setToolTipText(rtpDescription);
ice4jProtocolCheckBox = new SIPCommCheckBox(
resources.getI18NString("plugin.loggingutils.PACKET_LOGGING_ICE4J"));
ice4jProtocolCheckBox.addActionListener(this);
JPanel mainPanel = new TransparentPanel();
add(mainPanel, BorderLayout.NORTH);
mainPanel.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
enableCheckBox.setAlignmentX(Component.LEFT_ALIGNMENT);
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 1.0;
c.gridx = 0;
c.gridy = 0;
mainPanel.add(enableCheckBox, c);
String label = resources.getI18NString(
"plugin.loggingutils.PACKET_LOGGING_DESCRIPTION");
JLabel descriptionLabel = new JLabel(label);
descriptionLabel.setToolTipText(label);
enableCheckBox.setToolTipText(label);
descriptionLabel.setForeground(Color.GRAY);
descriptionLabel.setFont(descriptionLabel.getFont().deriveFont(8));
c.gridy = 1;
c.insets = new Insets(0, 25, 10, 0);
mainPanel.add(descriptionLabel, c);
final JPanel loggersButtonPanel
= new TransparentPanel(new GridLayout(0, 1));
loggersButtonPanel.setBorder(BorderFactory.createTitledBorder(
resources.getI18NString("service.gui.PROTOCOL")));
loggersButtonPanel.add(sipProtocolCheckBox);
loggersButtonPanel.add(jabberProtocolCheckBox);
loggersButtonPanel.add(rtpProtocolCheckBox);
loggersButtonPanel.add(ice4jProtocolCheckBox);
c.insets = new Insets(0, 20, 10, 0);
c.gridy = 2;
mainPanel.add(loggersButtonPanel, c);
final JPanel advancedPanel
= new TransparentPanel(new GridLayout(0, 2));
advancedPanel.setBorder(BorderFactory.createTitledBorder(
resources.getI18NString("service.gui.ADVANCED")));
fileCountField.getDocument().addDocumentListener(this);
fileSizeField.getDocument().addDocumentListener(this);
fileCountLabel = new JLabel(resources.getI18NString(
"plugin.loggingutils.PACKET_LOGGING_FILE_COUNT"));
advancedPanel.add(fileCountLabel);
advancedPanel.add(fileCountField);
fileSizeLabel = new JLabel(resources.getI18NString(
"plugin.loggingutils.PACKET_LOGGING_FILE_SIZE"));
advancedPanel.add(fileSizeLabel);
advancedPanel.add(fileSizeField);
c.gridy = 3;
mainPanel.add(advancedPanel, c);
archiveButton = new JButton(
resources.getI18NString("plugin.loggingutils.ARCHIVE_BUTTON"));
archiveButton.addActionListener(this);
c = new GridBagConstraints();
c.anchor = GridBagConstraints.LINE_START;
c.weightx = 0;
c.gridx = 0;
c.gridy = 4;
mainPanel.add(archiveButton, c);
if(!StringUtils.isNullOrEmpty(getUploadLocation()))
{
uploadLogsButton = new JButton(
resources.getI18NString("plugin.loggingutils.UPLOAD_LOGS_BUTTON"));
uploadLogsButton.addActionListener(this);
c.insets = new Insets(10, 0, 0, 0);
c.gridy = 5;
mainPanel.add(uploadLogsButton, c);
}
}
/**
* Checks the property in configuration service and if missing there get it
* from default settings.
* @return the upload location.
*/
static String getUploadLocation()
{
// check first in configuration it can be manually set
// or by provisioning
String uploadLocation =
LoggingUtilsActivator.getConfigurationService()
.getString(UPLOAD_LOCATION_PROPETY);
// if missing check default settings
if(uploadLocation == null || uploadLocation.length() == 0)
{
uploadLocation = LoggingUtilsActivator.getResourceService()
.getSettingsString(UPLOAD_LOCATION_PROPETY);
}
return uploadLocation;
}
/**
* Loading the values stored into configuration form
*/
private void loadValues()
{
PacketLoggingService packetLogging
= LoggingUtilsActivator.getPacketLoggingService();
PacketLoggingConfiguration cfg = packetLogging.getConfiguration();
enableCheckBox.setSelected(cfg.isGlobalLoggingEnabled());
sipProtocolCheckBox.setSelected(cfg.isSipLoggingEnabled());
jabberProtocolCheckBox.setSelected(cfg.isJabberLoggingEnabled());
rtpProtocolCheckBox.setSelected(cfg.isRTPLoggingEnabled());
ice4jProtocolCheckBox.setSelected(cfg.isIce4JLoggingEnabled());
fileCountField.setText(String.valueOf(cfg.getLogfileCount()));
fileSizeField.setText(String.valueOf(cfg.getLimit() / 1000));
updateButtonsState();
}
/**
* Update button enable/disable state according enableCheckBox.
*/
private void updateButtonsState()
{
sipProtocolCheckBox.setEnabled(enableCheckBox.isSelected());
jabberProtocolCheckBox.setEnabled(enableCheckBox.isSelected());
rtpProtocolCheckBox.setEnabled(enableCheckBox.isSelected());
ice4jProtocolCheckBox.setEnabled(enableCheckBox.isSelected());
fileCountField.setEnabled(enableCheckBox.isSelected());
fileSizeField.setEnabled(enableCheckBox.isSelected());
fileSizeLabel.setEnabled(enableCheckBox.isSelected());
fileCountLabel.setEnabled(enableCheckBox.isSelected());
}
/**
* Invoked when an action occurs.
*/
public void actionPerformed(ActionEvent e)
{
Object source = e.getSource();
PacketLoggingService packetLogging =
LoggingUtilsActivator.getPacketLoggingService();
if(source.equals(enableCheckBox))
{
// turn it on/off in activator
packetLogging.getConfiguration().setGlobalLoggingEnabled(
enableCheckBox.isSelected());
updateButtonsState();
}
else if(source.equals(sipProtocolCheckBox))
{
packetLogging.getConfiguration().setSipLoggingEnabled(
sipProtocolCheckBox.isSelected());
}
else if(source.equals(jabberProtocolCheckBox))
{
packetLogging.getConfiguration().setJabberLoggingEnabled(
jabberProtocolCheckBox.isSelected());
}
else if(source.equals(rtpProtocolCheckBox))
{
packetLogging.getConfiguration().setRTPLoggingEnabled(
rtpProtocolCheckBox.isSelected());
}
else if(source.equals(ice4jProtocolCheckBox))
{
packetLogging.getConfiguration().setIce4JLoggingEnabled(
ice4jProtocolCheckBox.isSelected());
}
else if(source.equals(archiveButton))
{
// don't block the UI thread
new Thread(new Runnable()
{
public void run()
{
collectLogs();
}
}).start();
}
else if(source.equals(uploadLogsButton))
{
// don't block the UI thread
new Thread(new Runnable()
{
public void run()
{
uploadLogs();
}
}).start();
}
}
/**
* Gives notification that there was an insert into the document. The
* range given by the DocumentEvent bounds the freshly inserted region.
*
* @param e the document event
*/
public void insertUpdate(DocumentEvent e)
{
documentChanged(e);
}
/**
* Gives notification that a portion of the document has been
* removed. The range is given in terms of what the view last
* saw (that is, before updating sticky positions).
*
* @param e the document event
*/
public void removeUpdate(DocumentEvent e)
{
documentChanged(e);
}
/**
* Not used.
*
* @param e the document event
*/
public void changedUpdate(DocumentEvent e)
{}
/**
* A change in the text fields.
* @param e the document event.
*/
private void documentChanged(DocumentEvent e)
{
if(e.getDocument().equals(fileCountField.getDocument()))
{
// set file count only if its un integer
try
{
int newFileCount = Integer.valueOf(fileCountField.getText());
fileCountField.setForeground(Color.black);
LoggingUtilsActivator.getPacketLoggingService()
.getConfiguration().setLogfileCount(newFileCount);
}
catch(Throwable t)
{
fileCountField.setForeground(Color.red);
}
}
else if(e.getDocument().equals(fileSizeField.getDocument()))
{
// set file size only if its un integer
try
{
int newFileSize = Integer.valueOf(fileSizeField.getText());
fileSizeField.setForeground(Color.black);
LoggingUtilsActivator.getPacketLoggingService()
.getConfiguration().setLimit(newFileSize * 1000);
}
catch(Throwable t)
{
fileSizeField.setForeground(Color.red);
}
}
}
/**
* Asks user for a location to save logs by poping up a file chooser.
* and archiving logs and saving them on the specified location.
*/
private void collectLogs()
{
ResourceManagementService resources =
LoggingUtilsActivator.getResourceService();
SipCommFileChooser fileChooser = GenericFileDialog.create(
null,
resources.getI18NString(
"plugin.loggingutils.ARCHIVE_FILECHOOSE_TITLE"),
SipCommFileChooser.SAVE_FILE_OPERATION);
fileChooser.setSelectionMode(
SipCommFileChooser.SAVE_FILE_OPERATION);
String defaultDir = "";
try
{
defaultDir = LoggingUtilsActivator.getFileAccessService()
.getDefaultDownloadDirectory().getAbsolutePath()
+ File.separator;
}
catch(IOException ex){}
fileChooser.setStartPath(
defaultDir + LogsCollector.getDefaultFileName());
File dest = fileChooser.getFileFromDialog();
if(dest == null)
return;
dest = LogsCollector.collectLogs(dest, null);
NotificationService notificationService
= LoggingUtilsActivator.getNotificationService();
if(notificationService != null)
{
String bodyMsgKey
= (dest == null)
? "plugin.loggingutils.ARCHIVE_MESSAGE_NOTOK"
: "plugin.loggingutils.ARCHIVE_MESSAGE_OK";
notificationService.fireNotification(
LOGFILES_ARCHIVED,
resources.getI18NString(
"plugin.loggingutils.ARCHIVE_BUTTON"),
resources.getI18NString(
bodyMsgKey,
new String[]{dest.getAbsolutePath()}),
null);
}
}
/**
* Shows a dialog with input for logs description.
*/
private void uploadLogs()
{
ResourceManagementService resources =
LoggingUtilsActivator.getResourceService();
final SIPCommDialog dialog = new SIPCommDialog(false)
{
/**
* Serial version UID.
*/
private static final long serialVersionUID = 0L;
/**
* Dialog is closed. Do nothing.
* @param escaped <tt>true</tt> if this dialog has been
* closed by pressing
*/
@Override
protected void close(boolean escaped)
{}
};
dialog.setModal(true);
dialog.setTitle(resources.getI18NString(
"plugin.loggingutils.UPLOAD_LOGS_BUTTON"));
Container container = dialog.getContentPane();
container.setLayout(new GridBagLayout());
JLabel descriptionLabel = new JLabel("Add a comment:");
final JTextArea commentTextArea = new JTextArea();
commentTextArea.setRows(4);
final JButton uploadButton = new JButton(
resources.getI18NString("plugin.loggingutils.UPLOAD_BUTTON"));
final SIPCommTextField emailField = new SIPCommTextField(resources
.getI18NString("plugin.loggingutils.ARCHIVE_UPREPORT_EMAIL"));
final JCheckBox emailCheckBox = new SIPCommCheckBox(
"Email me when more information is available");
emailCheckBox.setSelected(true);
emailCheckBox.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
if(!emailCheckBox.isSelected())
{
uploadButton.setEnabled(true);
emailField.setEnabled(false);
}
else
{
emailField.setEnabled(true);
if(emailField.getText() != null
&& emailField.getText().trim().length() > 0)
uploadButton.setEnabled(true);
else
uploadButton.setEnabled(false);
}
}
});
emailField.getDocument().addDocumentListener(new DocumentListener()
{
public void insertUpdate(DocumentEvent e)
{
updateButtonsState();
}
public void removeUpdate(DocumentEvent e)
{
updateButtonsState();
}
public void changedUpdate(DocumentEvent e){}
/**
* Check whether we should enable upload button.
*/
private void updateButtonsState()
{
if(emailCheckBox.isSelected() && emailField.getText() != null
&& emailField.getText().trim().length() > 0)
uploadButton.setEnabled(true);
else
uploadButton.setEnabled(false);
}
});
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.HORIZONTAL;
c.insets = new Insets(10, 10, 3, 10);
c.weightx = 1.0;
c.gridx = 0;
c.gridy = 0;
container.add(descriptionLabel, c);
c.insets = new Insets(0, 10, 10, 10);
c.gridy = 1;
container.add(new JScrollPane(commentTextArea), c);
c.insets = new Insets(0, 10, 0, 10);
c.gridy = 2;
container.add(emailCheckBox, c);
c.insets = new Insets(0, 10, 10, 10);
c.gridy = 3;
container.add(emailField, c);
JButton cancelButton = new JButton(
resources.getI18NString("service.gui.CANCEL"));
cancelButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
dialog.dispose();
}
});
uploadButton.setEnabled(false);
uploadButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
try
{
final ArrayList<String> paramNames = new ArrayList<String>();
final ArrayList<String> paramValues = new ArrayList<String>();
if(emailCheckBox.isSelected())
{
paramNames.add("Email");
paramValues.add(emailField.getText());
}
paramNames.add("Description");
paramValues.add(commentTextArea.getText());
// don't block the UI thread we may need to show
// some ui for password input if protected area on the way
new Thread(new Runnable()
{
public void run()
{
uploadLogs(
getUploadLocation(),
LogsCollector.getDefaultFileName(),
paramNames.toArray(new String[]{}),
paramValues.toArray(new String[]{}));
}
}).start();
}
finally
{
dialog.dispose();
}
}
});
JPanel buttonsPanel = new TransparentPanel(
new FlowLayout(FlowLayout.RIGHT));
buttonsPanel.add(uploadButton);
buttonsPanel.add(cancelButton);
c.anchor = GridBagConstraints.LINE_END;
c.weightx = 0;
c.gridy = 4;
container.add(buttonsPanel, c);
dialog.setVisible(true);
}
/**
* Upload files to pre-configured url.
* @param uploadLocation the location we are uploading to.
* @param fileName the filename we use for the resulting filename we upload.
* @param params the optional parameter names.
* @param values the optional parameter values.
*/
static void uploadLogs(
String uploadLocation,
String fileName,
String[] params,
String[] values)
{
try
{
File tempDir = LoggingUtilsActivator.getFileAccessService()
.getTemporaryDirectory();
File newDest = new File(tempDir, fileName);
File optionalFile = null;
// if we have some description params
// save them to file and add it to archive
if(params != null)
{
optionalFile = new File(
LoggingUtilsActivator.getFileAccessService().
getTemporaryDirectory(),
"description.txt");
OutputStream out = new FileOutputStream(optionalFile);
for(int i = 0; i < params.length; i++)
{
out.write((params[i] + " : "
+ values[i] + "\r\n").getBytes("UTF-8"));
}
out.flush();
out.close();
}
newDest = LogsCollector.collectLogs(newDest, optionalFile);
// don't leave any unneeded information
if(optionalFile != null)
optionalFile.delete();
if(uploadLocation == null)
return;
if(HttpUtils.postFile(uploadLocation, "logs", newDest) != null)
{
NotificationService notificationService
= LoggingUtilsActivator.getNotificationService();
if(notificationService != null)
{
ResourceManagementService resources
= LoggingUtilsActivator.getResourceService();
String bodyMsgKey = "plugin.loggingutils.ARCHIVE_MESSAGE_OK";
notificationService.fireNotification(
LOGFILES_ARCHIVED,
resources.getI18NString(
"plugin.loggingutils.ARCHIVE_BUTTON"),
resources.getI18NString(
bodyMsgKey,
new String[]{uploadLocation}),
null);
}
}
}
catch(Throwable e)
{
logger.error("Cannot upload file", e);
}
}
}