blob: 6ff6ccf3f4d6095424865c6f88f28b049f3ea1a5 [file] [log] [blame]
/*
* Copyright 1999,2004 The Apache Software Foundation.
*
* 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 org.apache.log4j.chainsaw;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import javax.swing.AbstractAction;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JTextArea;
import javax.swing.SwingUtilities;
import javax.swing.event.ListDataEvent;
import javax.swing.event.ListDataListener;
import javax.swing.filechooser.FileFilter;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.log4j.net.PortBased;
import org.apache.log4j.net.SocketAppender;
import org.apache.log4j.net.SocketHubReceiver;
import org.apache.log4j.net.SocketReceiver;
/**
* A dialog panel to inform the user that they do not have
* Receiver's defined, and prompting them to either
* load a Log4j Log file, search for a Log4j configuration file
* or use the GUI to define the Receivers
*
* @author Paul Smith
*/
class NoReceiversWarningPanel extends JPanel {
private final JComboBox previousConfigs = new JComboBox();
private final JRadioButton simpleReceiver = new JRadioButton(
"Let me use a simple Receiver:");
private final JRadioButton justLoadingFile = new JRadioButton(
"I'm fine thanks, don't worry");
private final JRadioButton searchOption = new JRadioButton(
"Let me search for a configuration file");
private final JRadioButton manualOption = new JRadioButton(
"Let me define Receivers manually");
private final JButton okButton = new JButton("Ok");
private final PanelModel model = new PanelModel();
final DefaultComboBoxModel configModel = new DefaultComboBoxModel();
final DefaultComboBoxModel simpleReceiverModel = new DefaultComboBoxModel();
final DefaultComboBoxModel simplePortModel = new DefaultComboBoxModel();
private boolean dontWarnMeAgain = false;
private final Logger logger = LogManager.getLogger(NoReceiversWarningPanel.class);
NoReceiversWarningPanel() {
initComponents();
}
/**
* Returns the current Model/state of the chosen options by the user.
* @return
*/
PanelModel getModel() {
return model;
}
/**
* Clients of this panel can configure the ActionListener to be used
* when the user presses the OK button, so they can read
* back this Panel's model top determine what to do.
* @param actionListener
*/
void setOkActionListener(ActionListener actionListener) {
okButton.addActionListener(actionListener);
}
/**
* Sets up all the GUI components for this paenl
*/
private void initComponents() {
setLayout(new GridBagLayout());
GridBagConstraints gc = new GridBagConstraints();
setBorder(BorderFactory.createEmptyBorder(15, 15, 15, 15));
gc.gridx = 1;
gc.fill = GridBagConstraints.BOTH;
gc.weightx = 1.0;
gc.weighty = 1.0;
JTextArea label = new JTextArea(
"You will not be able to receive events from a Remote source unless you define one in the Log4J configuration file.\n");
label.setWrapStyleWord(true);
label.setLineWrap(true);
label.setEditable(false);
label.setOpaque(false);
label.setFont(getFont());
add(label, gc);
gc.weightx = 0;
gc.weighty = 0;
gc.gridy = 2;
add(Box.createVerticalStrut(20), gc);
JPanel optionpanel = new JPanel();
optionpanel.setLayout(new GridLayout(4, 1, 3, 3));
optionpanel.setBackground(getBackground());
optionpanel.setBorder(BorderFactory.createEtchedBorder());
final ButtonGroup optionGroup = new ButtonGroup();
simpleReceiver.setToolTipText(
"Creates one of the standard Receivers on one of the standard port");
simpleReceiver.setMnemonic('p');
searchOption.setToolTipText(
"Allows you to choose a Log4J Configuration file that contains Receiver definitions");
searchOption.setMnemonic('S');
manualOption.setToolTipText(
"Opens the Receivers panel so you can define them via a GUI");
manualOption.setMnemonic('m');
justLoadingFile.setToolTipText(
"Use this if you just want to view a Log4J Log file stored somewhere");
justLoadingFile.setMnemonic('I');
// searchOption.setOpaque(false);
manualOption.setOpaque(false);
justLoadingFile.setOpaque(false);
optionGroup.add(searchOption);
optionGroup.add(manualOption);
optionGroup.add(justLoadingFile);
optionGroup.add(simpleReceiver);
gc.gridy = 3;
configModel.removeAllElements();
previousConfigs.setModel(configModel);
previousConfigs.setOpaque(false);
previousConfigs.setBackground(getBackground());
previousConfigs.setToolTipText(
"Previously loaded configurations can be chosen here");
previousConfigs.setEditable(true);
previousConfigs.getModel().addListDataListener(new ListDataListener() {
private void validateUrl() {
okButton.setEnabled(isValidConfigURL());
}
public void contentsChanged(ListDataEvent e) {
validateUrl();
}
public void intervalAdded(ListDataEvent e) {
validateUrl();
}
public void intervalRemoved(ListDataEvent e) {
validateUrl();
}
});
previousConfigs.setMaximumSize(new Dimension(200,
(int) previousConfigs.getPreferredSize().getHeight()));
previousConfigs.setPreferredSize(previousConfigs.getMaximumSize());
previousConfigs.getEditor().getEditorComponent().addFocusListener(
new FocusListener() {
public void focusGained(FocusEvent e) {
selectAll();
}
private void selectAll() {
previousConfigs.getEditor().selectAll();
}
public void focusLost(FocusEvent e) {
}
});
final JButton searchButton = new JButton(new AbstractAction(
"Browse...") {
public void actionPerformed(ActionEvent e) {
try {
URL url = browseForConfig();
if (url != null) {
getModel().configUrl = url;
configModel.addElement(url);
previousConfigs.getModel().setSelectedItem(
url);
}
} catch (Exception ex) {
logger.error(
"Error browswing for Configuration file", ex);
}
}
});
searchButton.setToolTipText(
"Shows a File Open dialog to allow you to find a configuration file");
simplePortModel.addElement(new PortBased() {
private void unsupported() {
throw new UnsupportedOperationException(
"Should not be used in this context");
}
public String getName() {
unsupported();
return null;
}
public boolean isActive() {
unsupported();
return false;
}
public int getPort() {
return 4445;
}
public String toString() {
return getPort() + " (Old style/standard Chainsaw port)";
}
});
simplePortModel.addElement(new PortBased() {
private void unsupported() {
throw new UnsupportedOperationException(
"Should not be used in this context");
}
public String getName() {
unsupported();
return null;
}
public boolean isActive() {
unsupported();
return false;
}
public int getPort() {
return SocketAppender.DEFAULT_PORT;
}
public String toString() {
return getPort() + " (Default SocketAppender port)";
}
});
JPanel simpleSocketPanel = new JPanel(new GridBagLayout());
GridBagConstraints simpleSocketGC = new GridBagConstraints();
simpleSocketPanel.add(simpleReceiver, simpleSocketGC);
final JComboBox socketCombo = new JComboBox(simplePortModel);
simpleReceiverModel.addElement(SocketReceiver.class);
simpleReceiverModel.addElement(SocketHubReceiver.class);
final JComboBox receiverCombo = new JComboBox(simpleReceiverModel);
receiverCombo.setEditable(false);
receiverCombo.setRenderer(new DefaultListCellRenderer() {
public Component getListCellRendererComponent(JList list,
Object value, int index, boolean isSelected,
boolean cellHasFocus) {
Component c = super.getListCellRendererComponent(list,
value, index, isSelected, cellHasFocus);
if (value instanceof Class) {
Class receiverClass = (Class) value;
JLabel cellLabel = (JLabel) c;
String shortenedName = receiverClass.getName()
.substring(
receiverClass.getName().lastIndexOf('.') + 1);
cellLabel.setText(shortenedName);
}
return c;
}
});
simpleSocketPanel.add(receiverCombo);
simpleSocketPanel.add(new JLabel(" on port "));
simpleSocketPanel.add(socketCombo, simpleSocketGC);
/**
* This listener activates/deactivates certain controls based on the current
* state of the options
*/
ActionListener al = new ActionListener() {
public void actionPerformed(ActionEvent e) {
previousConfigs.setEnabled(e.getSource() == searchOption);
searchButton.setEnabled(e.getSource() == searchOption);
socketCombo.setEnabled(e.getSource() == simpleReceiver);
receiverCombo.setEnabled(e.getSource() == simpleReceiver);
if (optionGroup.isSelected(searchOption.getModel())) {
okButton.setEnabled(isValidConfigURL());
} else {
okButton.setEnabled(true);
}
}
};
searchOption.addActionListener(al);
manualOption.addActionListener(al);
justLoadingFile.addActionListener(al);
simpleReceiver.addActionListener(al);
justLoadingFile.doClick();
JPanel searchOptionPanel = new JPanel(new GridBagLayout());
searchOptionPanel.setOpaque(false);
GridBagConstraints searchGCC = new GridBagConstraints();
searchGCC.fill = GridBagConstraints.HORIZONTAL;
searchGCC.gridx = 1;
searchGCC.weightx = 0.0;
searchGCC.anchor = GridBagConstraints.WEST;
searchOptionPanel.add(searchOption, searchGCC);
searchGCC.fill = GridBagConstraints.NONE;
searchGCC.weightx = 1.0;
searchGCC.gridx = 2;
searchOptionPanel.add(Box.createHorizontalStrut(5), searchGCC);
searchGCC.gridx = 3;
searchGCC.weightx = 0.0;
searchOptionPanel.add(previousConfigs, searchGCC);
searchGCC.weightx = 0.0;
searchGCC.gridx = 4;
searchOptionPanel.add(Box.createHorizontalStrut(5), searchGCC);
searchGCC.gridx = 5;
searchOptionPanel.add(searchButton, searchGCC);
// searchGCC.gridx = 6;
// searchGCC.fill = GridBagConstraints.HORIZONTAL;
// searchGCC.weightx = 1.0;
// searchOptionPanel.add(Box.createHorizontalGlue(), searchGCC);
optionpanel.add(justLoadingFile);
optionpanel.add(simpleSocketPanel);
optionpanel.add(searchOptionPanel);
optionpanel.add(manualOption);
add(optionpanel, gc);
gc.gridy = GridBagConstraints.RELATIVE;
gc.weightx = 0;
gc.fill = GridBagConstraints.NONE;
gc.anchor = GridBagConstraints.SOUTHEAST;
add(Box.createVerticalStrut(20), gc);
okButton.setMnemonic('O');
final JCheckBox dontwarnIfNoReceiver = new JCheckBox(
"Don't show me this again");
JPanel okPanel = new JPanel();
okPanel.add(dontwarnIfNoReceiver);
okPanel.add(okButton);
add(okPanel, gc);
okButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
dontWarnMeAgain = dontwarnIfNoReceiver.isSelected();
}
});
}
/**
* Returns the URL chosen by the user for a Configuration file
* or null if they cancelled.
*/
private URL browseForConfig() throws MalformedURLException {
JFileChooser chooser = new JFileChooser();
chooser.setDialogTitle("Search for Log4j configuration...");
chooser.setDialogType(JFileChooser.OPEN_DIALOG);
chooser.setFileFilter(new FileFilter() {
public boolean accept(File f) {
return f.isDirectory() ||
f.getName().endsWith(".properties") ||
f.getName().endsWith(".xml");
}
public String getDescription() {
return "Log4j Configuration file";
}
});
chooser.showOpenDialog(this);
File selectedFile = chooser.getSelectedFile();
if (selectedFile == null) {
return null;
}
if (!selectedFile.exists() || !selectedFile.canRead()) {
return null;
}
return chooser.getSelectedFile().toURL();
}
/**
* Determions if the Configuration URL is a valid url.
*/
private boolean isValidConfigURL() {
if (previousConfigs.getSelectedItem() == null) {
return false;
}
String urlString = previousConfigs.getSelectedItem().toString();
try {
getModel().configUrl = new URL(urlString);
return true;
} catch (Exception ex) {
}
return false;
}
public static void main(String[] args) {
JFrame frame = new JFrame();
frame.getContentPane().add(new NoReceiversWarningPanel());
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
/**
* @return Returns the dontWarnMeAgain.
*/
public final boolean isDontWarnMeAgain() {
return dontWarnMeAgain;
}
/**
* This class represents the model of the chosen options the user
* has configured.
*
*/
class PanelModel {
private URL configUrl;
boolean isLoadLogFile() {
return justLoadingFile.isSelected();
}
boolean isSimpleReceiverMode() {
return simpleReceiver.isSelected();
}
int getSimplePort() {
return ((PortBased) simplePortModel.getSelectedItem()).getPort();
}
Class getSimpleReceiverClass() {
return (Class) simpleReceiverModel.getSelectedItem();
}
boolean isLoadConfig() {
return searchOption.isSelected();
}
boolean isManualMode() {
return manualOption.isSelected();
}
public Object[] getRememberedConfigs() {
Object[] urls = new Object[configModel.getSize()];
for (int i = 0; i < configModel.getSize(); i++) {
urls[i] = configModel.getElementAt(i);
}
return urls;
}
public void setRememberedConfigs(final Object[] configs) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
configModel.removeAllElements();
for (int i = 0; i < configs.length; i++) {
configModel.addElement(configs[i]);
}
}
});
}
URL getConfigToLoad() {
return configUrl;
}
}
}