001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 * 
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 * 
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.log4j.chainsaw;
018
019import java.awt.event.ActionEvent;
020import java.io.File;
021import java.io.IOException;
022import java.io.StringReader;
023import javax.swing.AbstractAction;
024import javax.swing.JFileChooser;
025import javax.swing.JFrame;
026import javax.swing.JOptionPane;
027import javax.xml.parsers.ParserConfigurationException;
028import javax.xml.parsers.SAXParserFactory;
029import org.apache.log4j.Logger;
030import org.xml.sax.InputSource;
031import org.xml.sax.SAXException;
032import org.xml.sax.XMLReader;
033
034/**
035 * Encapsulates the action to load an XML file.
036 *
037 * @author <a href="mailto:oliver@puppycrawl.com">Oliver Burn</a>
038 * @version 1.0
039 */
040class LoadXMLAction
041    extends AbstractAction
042{
043    /** use to log messages **/
044    private static final Logger LOG = Logger.getLogger(LoadXMLAction.class);
045
046    /** the parent frame **/
047    private final JFrame mParent;
048
049    /**
050     * the file chooser - configured to allow only the selection of a
051     * single file.
052     */
053    private final JFileChooser mChooser = new JFileChooser();
054    {
055        mChooser.setMultiSelectionEnabled(false);
056        mChooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
057    }
058
059    /** parser to read XML files **/
060    private final XMLReader mParser;
061    /** the content handler **/
062    private final XMLFileHandler mHandler;
063
064
065    /**
066     * Creates a new <code>LoadXMLAction</code> instance.
067     *
068     * @param aParent the parent frame
069     * @param aModel the model to add events to
070     * @exception SAXException if an error occurs
071     * @throws ParserConfigurationException if an error occurs
072     */
073    LoadXMLAction(JFrame aParent, MyTableModel aModel)
074        throws SAXException, ParserConfigurationException
075    {
076        mParent = aParent;
077        mHandler = new XMLFileHandler(aModel);
078        mParser = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
079        mParser.setContentHandler(mHandler);
080    }
081
082    /**
083     * Prompts the user for a file to load events from.
084     * @param aIgnore an <code>ActionEvent</code> value
085     */
086    public void actionPerformed(ActionEvent aIgnore) {
087        LOG.info("load file called");
088        if (mChooser.showOpenDialog(mParent) == JFileChooser.APPROVE_OPTION) {
089            LOG.info("Need to load a file");
090            final File chosen = mChooser.getSelectedFile();
091            LOG.info("loading the contents of " + chosen.getAbsolutePath());
092            try {
093                final int num = loadFile(chosen.getAbsolutePath());
094                JOptionPane.showMessageDialog(
095                    mParent,
096                    "Loaded " + num + " events.",
097                    "CHAINSAW",
098                    JOptionPane.INFORMATION_MESSAGE);
099            } catch (Exception e) {
100                LOG.warn("caught an exception loading the file", e);
101                JOptionPane.showMessageDialog(
102                    mParent,
103                    "Error parsing file - " + e.getMessage(),
104                    "CHAINSAW",
105                    JOptionPane.ERROR_MESSAGE);
106            }
107        }
108    }
109
110    /**
111     * Loads the contents of file into the model
112     *
113     * @param aFile the file to extract events from
114     * @return the number of events loaded
115     * @throws SAXException if an error occurs
116     * @throws IOException if an error occurs
117     */
118    private int loadFile(String aFile)
119        throws SAXException, IOException
120    {
121        synchronized (mParser) {
122            // Create a dummy document to parse the file
123            final StringBuffer buf = new StringBuffer();
124            buf.append("<?xml version=\"1.0\" standalone=\"yes\"?>\n");
125            buf.append("<!DOCTYPE log4j:eventSet ");
126            buf.append("[<!ENTITY data SYSTEM \"file:///");
127            buf.append(aFile);
128            buf.append("\">]>\n");
129            buf.append("<log4j:eventSet xmlns:log4j=\"Claira\">\n");
130            buf.append("&data;\n");
131            buf.append("</log4j:eventSet>\n");
132
133            final InputSource is =
134                new InputSource(new StringReader(buf.toString()));
135            mParser.parse(is);
136            return mHandler.getNumEvents();
137        }
138    }
139}