001    /*
002            Copyright (C) 2003 Adam Olsen
003    
004            This program is free software; you can redistribute it and/or modify
005            it under the terms of the GNU General Public License as published by
006            the Free Software Foundation; either version 1, or (at your option)
007            any later version.
008    
009            This program is distributed in the hope that it will be useful,
010            but WITHOUT ANY WARRANTY; without even the implied warranty of
011            MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
012            GNU General Public License for more details.
013    
014            You should have received a copy of the GNU General Public License
015            along with this program; if not, write to the Free Software
016            Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
017    */
018    
019    package com.valhalla.jbother;
020    
021    import java.awt.Component;
022    import java.awt.Dimension;
023    import java.awt.event.ActionEvent;
024    import java.awt.event.ActionListener;
025    import java.awt.event.MouseAdapter;
026    import java.awt.event.MouseEvent;
027    import java.io.BufferedReader;
028    import java.io.File;
029    import java.io.FileFilter;
030    import java.io.FileNotFoundException;
031    import java.io.FileReader;
032    import java.io.IOException;
033    import java.text.SimpleDateFormat;
034    import java.util.*;
035    
036    import javax.swing.BorderFactory;
037    import javax.swing.Box;
038    import javax.swing.BoxLayout;
039    import javax.swing.ImageIcon;
040    import javax.swing.JButton;
041    import javax.swing.JFrame;
042    import javax.swing.JLabel;
043    import javax.swing.JList;
044    import javax.swing.JOptionPane;
045    import javax.swing.JPanel;
046    import javax.swing.JScrollPane;
047    import javax.swing.JSplitPane;
048    import javax.swing.ListCellRenderer;
049    import javax.swing.ListSelectionModel;
050    import javax.swing.WindowConstants;
051    
052    import com.valhalla.gui.*;
053    import com.valhalla.jbother.*;
054    import com.valhalla.settings.Settings;
055    
056    /**
057     * Allows the user to view the log of any contact
058     * Displays a dialog that allows you to view the log of any Jabber
059     * user you have contacted.  You can view the log by date and time
060     *
061     * @author Adam Olsen
062     * @version 1.0
063    */
064    public class LogViewerDialog extends JFrame
065    {
066            private ResourceBundle resources = ResourceBundle.getBundle( "JBotherBundle", Locale.getDefault() );
067            private String logDirectory;
068            private JList logList;
069            private JPanel container = new JPanel();
070            private JPanel rightPanel = new JPanel();
071            private ConversationArea logView;
072            private File logDirectoryFile;
073            private JButton  closeButton = new JButton( resources.getString( "closeButton" ) ),
074                                             clearButton = new JButton( resources.getString( "clearButton" ) );
075    
076            private JSplitPane splitPane;
077            private File fileList[];
078            private LogViewerCaller caller;
079            private LogViewerDialog thisPointer = this;
080    
081            /**
082             * Default constructor
083             * Can be passed a ChatRoomPanel, HeadlineWindow, and a ChatPanel as the caller
084             * @param caller the object that called this dialog
085             * @param entryName the user who's log is to be viewed
086            */
087            public LogViewerDialog( LogViewerCaller caller, String entryName )
088            {
089                    super( "Log Viewer (" + entryName + ")" );
090                    setTitle( resources.getString( "logViewer" ) + " (" + entryName + ")" );
091    
092                    ImageIcon icon = StatusIconCache.getStatusIcon(org.jivesoftware.smack.packet.Presence.Mode.AVAILABLE);
093                    if ( icon != null ) setIconImage( icon.getImage() );
094    
095                    if( caller != null ) this.caller = caller;
096    
097                    logDirectory = JBother.profileDir + File.separatorChar + "logs" + File.separatorChar +
098                            entryName.replaceAll( "@", "_at_" ).replaceAll( "\\/", "-" );
099    
100                    logDirectoryFile = new File( logDirectory );
101    
102                    container.setLayout( new BoxLayout( container, BoxLayout.X_AXIS ) );
103                    setContentPane( container );
104    
105                    logView = new ConversationArea();
106    
107                    logView.setPreferredSize( new Dimension( 500, 350 ) );
108    
109                    rightPanel.setLayout( new BoxLayout( rightPanel, BoxLayout.Y_AXIS ) );
110                    rightPanel.add( new JScrollPane( logView ) );
111    
112                    JPanel buttonPanel = new JPanel();
113                    buttonPanel.setLayout( new BoxLayout( buttonPanel, BoxLayout.X_AXIS ) );
114                    buttonPanel.setBorder( BorderFactory.createEmptyBorder( 5, 5, 0, 0 ) );
115                    buttonPanel.add( Box.createHorizontalGlue() );
116                    buttonPanel.add( clearButton );
117                    buttonPanel.add( closeButton );
118                    rightPanel.add( buttonPanel );
119    
120                    splitPane = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT, new JScrollPane( loadLogFiles() ), rightPanel );
121                    splitPane.setDividerLocation( 150 );
122                    splitPane.setOneTouchExpandable( true );
123    
124                    container.add( splitPane );
125                    container.setBorder( BorderFactory.createEmptyBorder( 5, 5, 5, 5 ) );
126    
127                    setUpListeners();
128    
129                    pack();
130                    Standard.cascadePlacement( this );
131                    DialogTracker.addDialog( this, false, true );
132    
133                    if( logList.getModel().getSize() >= 1 ) setVisible( true );
134                    else {
135                            Standard.warningMessage( null, resources.getString( "logViewer" ),
136                                    resources.getString( "noLogData" ) );
137                            DialogTracker.removeDialog( this );
138                    }
139            }
140    
141            /**
142             * Returns a formatted date string that is used in many places in JBother
143             * @return the formatted date and time
144            */
145            public static String getDateName()
146            {
147                    SimpleDateFormat formatter = new SimpleDateFormat( "yyyy-MM-dd-HH-mm-ss" );
148                    String date = formatter.format( new Date() );
149                    return date;
150            }
151    
152            /**
153             * Sets up the listeners for the various events
154            */
155            private void setUpListeners()
156            {
157                    setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
158    
159                    closeButton.addActionListener( new ActionListener()
160                    {
161                            public void actionPerformed( ActionEvent e )
162                            {
163                                    DialogTracker.removeDialog( thisPointer );
164                            }
165                    } );
166    
167                    clearButton.addActionListener( new ActionListener()
168                    {
169                            public void actionPerformed( ActionEvent e )
170                            {
171                                    clearHandler();
172                            }
173                    } );
174    
175                    logList.addMouseListener( new LogListMouseListener() );
176            }
177    
178            /**
179             * Listens for someone to click on an entry date
180             * and populates the textArea with the log data
181             * @author Adam Olsen
182             * @version 1.0
183            */
184            private class LogListMouseListener extends MouseAdapter
185            {
186                    public void mouseClicked( MouseEvent e )
187                    {
188                            File file = (File)logList.getSelectedValue();
189                            String fileText = "";
190    
191                            try {
192                                    // open the selected log
193                                    FileReader fr = new FileReader( file );
194                                    BufferedReader in = new BufferedReader( fr );
195                                    String line;
196                                    while( ( line = in.readLine() ) != null ) fileText += line;
197                                    fr.close();
198                            }
199                            catch( FileNotFoundException fnfe ) {  }
200                            catch( IOException ioe ) {  }
201    
202                            logView.setText( fileText );
203                    }
204            }
205    
206            /**
207             * Clears all log data (deletes all log entries)
208            */
209            private void clearHandler()
210            {
211                    int result = JOptionPane.showConfirmDialog( null,
212                            resources.getString( "sureClearLog" ), resources.getString( "clearLogs" ), JOptionPane.YES_NO_OPTION );
213    
214                    if( result == 0 )
215                    {
216                            if( caller != null )
217                            {
218                                    caller.closeLog();
219                                    caller.startLog();
220                            }
221    
222                            for( int i = 0; i < fileList.length; i++ ) fileList[i].delete();
223                            DialogTracker.removeDialog( this );
224                    }
225            }
226    
227            /**
228             * Returns a list of all available log entries
229             * @return the list of log entries
230            */
231            private JList loadLogFiles()
232            {
233                    logList = new JList();
234                    logList.setSelectionMode( ListSelectionModel.SINGLE_SELECTION );
235                    logList.setCellRenderer( new LogListRenderer() );
236    
237                    if( !logDirectoryFile.isDirectory() ) return logList;
238    
239                    // opens the directory and lists the files
240                    fileList = logDirectoryFile.listFiles( new LogFileFilter() );
241                    if( fileList.length == 0 ) return logList;
242    
243                    String fileText = "";
244    
245                    Arrays.sort( fileList, Collections.reverseOrder() );
246    
247                    // displays the most recent entry
248                    try {
249                            FileReader fr = new FileReader( fileList[0] );
250                            BufferedReader in = new BufferedReader( fr );
251                            String line;
252                            while( ( line = in.readLine() ) != null ) fileText += line;
253                            fr.close();
254                    }
255                    catch( FileNotFoundException fnfe ) { return new JList(); }
256                    catch( IOException ioe ) { return new JList(); }
257    
258                    logView.setText( fileText );
259    
260                    logList.setListData( fileList );
261                    logList.setSelectedIndex( 0 );
262                    return logList;
263            }
264    }
265    
266    /**
267     * Displays each log entry as a date and time
268     * @author Adam Olsen
269     * @version 1.0
270    */
271    class LogListRenderer extends JLabel implements ListCellRenderer
272    {
273            /**
274             * Sets the background to opaque
275            */
276            public LogListRenderer()
277            {
278                    setOpaque( true );
279            }
280    
281            /**
282             * Renders each entry
283            */
284            public Component getListCellRendererComponent( JList list, Object value, int index, boolean isSelected, boolean cellHasFocus )
285            {
286                    File file = (File)value;
287    
288                    String dateString[] = file.toString().replaceAll( ".*\\" + File.separatorChar ,
289                            "" ).replaceAll( "\\.log\\.html", "" ).split( "\\-" );
290    
291                    try {
292                            setText( dateString[1] + "-" + dateString[2] + "-" + dateString[0] + " " + dateString[3] + ":" + dateString[4] + ":" + dateString[5] );
293                    }
294                    catch( Exception e )
295                    {
296                            setText( "Invalid Date" );
297                    }
298    
299                    setBackground( isSelected ? list.getSelectionBackground() : list.getBackground() );
300                    setForeground( isSelected ? list.getSelectionForeground() : list.getForeground() );
301                    list.validate();
302    
303                    return this;
304            }
305    }
306    
307    /**
308     * A filter to only accept html files
309     * @author Adam Olsen
310     * @version 1.0
311    */
312    class LogFileFilter implements FileFilter
313    {
314            // accept html files
315            public boolean accept( File f )
316            {
317                    if( f.isDirectory() ) return false;
318    
319                    if( f.length() <= 0.0 ) return false;
320    
321                    String extension = Utils.getExtension( f );
322    
323                    if( extension != null )
324                    {
325                            if( extension.equals( Utils.html ) )
326                            {
327                                            return true;
328                            }
329                            else {
330                                    return false;
331                            }
332                    }
333    
334                    return false;
335            }
336    }