| /* |
| * 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.show(); |
| } |
| |
| /** |
| * @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; |
| } |
| } |
| } |