001         package com.croftsoft.apps.agoracast.c2p;
002    
003         import java.awt.*;
004         import java.awt.event.*;
005         import java.io.*;
006         import java.util.*;
007         import javax.swing.*;
008         import javax.swing.table.*;
009    
010         import com.croftsoft.core.gui.ButtonPanel2;
011         import com.croftsoft.core.gui.LabeledFieldsPanel2;
012         import com.croftsoft.core.lang.NullArgumentException;
013         import com.croftsoft.core.lang.Pair;
014         import com.croftsoft.core.lang.StringLib;
015         import com.croftsoft.core.net.news.Newsgroup;
016         import com.croftsoft.core.net.news.NntpConstants;
017         import com.croftsoft.core.net.news.NntpSocket;
018         import com.croftsoft.core.net.news.UsenetMessage;
019         import com.croftsoft.core.text.DateFormatLib;
020         import com.croftsoft.core.util.log.Log;
021    
022         /*********************************************************************
023         *
024         * <p />
025         *
026         * @version
027         *   2001-08-13
028         * @since
029         *   2001-07-31
030         * @author
031         *   <a href="https://www.croftsoft.com/">David Wallace Croft</a>
032         *********************************************************************/
033    
034         public final class  AgoracastSourcePanel
035           extends JPanel
036           implements ActionListener, Log, Runnable
037         //////////////////////////////////////////////////////////////////////
038         //////////////////////////////////////////////////////////////////////
039         {
040    
041         private final AgoracastMediator     agoracastMediator;
042    
043         private final AgoracastBrowsePanel  agoracastBrowsePanel;
044    
045         private final JTextArea             jTextArea;
046    
047         private final JButton               cancelButton;
048    
049         //
050    
051         private AgoracastData  agoracastData;
052    
053         private NntpSocket     nntpSocket;
054    
055         //////////////////////////////////////////////////////////////////////
056         //////////////////////////////////////////////////////////////////////
057    
058         public  AgoracastSourcePanel (
059           AgoracastMediator     agoracastMediator,
060           AgoracastBrowsePanel  agoracastBrowsePanel )
061         //////////////////////////////////////////////////////////////////////
062         {
063           super ( new BorderLayout ( ), true ); // isDoubleBuffered
064    
065           NullArgumentException.check (
066             this.agoracastMediator = agoracastMediator );
067    
068           NullArgumentException.check (
069             this.agoracastBrowsePanel = agoracastBrowsePanel );
070    
071           AgoracastLib.setColor ( this, agoracastMediator );
072    
073           add ( new JScrollPane (
074             jTextArea = new JTextArea ( ) ), BorderLayout.CENTER );
075    
076           jTextArea.setFont ( AgoracastConstants.LOG_FONT );
077    
078           cancelButton = new JButton ( "Cancel" );
079    
080           cancelButton.addActionListener ( this );
081    
082           add ( cancelButton, BorderLayout.SOUTH );
083         }
084    
085         //////////////////////////////////////////////////////////////////////
086         //////////////////////////////////////////////////////////////////////
087    
088         public synchronized void  viewSource ( AgoracastData  agoracastData )
089         //////////////////////////////////////////////////////////////////////
090         {
091           this.agoracastData = agoracastData;
092    
093           new Thread ( this ).start ( );
094         }
095    
096         public synchronized void  run ( )
097         //////////////////////////////////////////////////////////////////////
098         {
099           try
100           {
101             String  articleId = agoracastData.getArticleId ( );
102    
103             jTextArea.setText (
104               DateFormatLib.toIsoDateFormat ( new Date ( ) )
105               + " Downloading article " + articleId + "..." );
106    
107             cancelButton.setText ( "Cancel" );
108    
109    // should we get this from the agoracastData instead?
110    
111             String  server = agoracastMediator.getServer ( );
112    
113             String  newsgroupName = agoracastData.getNewsgroup ( );
114    
115             nntpSocket = new NntpSocket ( server, this );
116    
117             // 200 server ready - posting allowed
118             // 201 server ready - no posting allowed
119    
120             if ( nntpSocket.getResponseCode ( ).startsWith ( "20" ) )
121             {
122               String  responseCode = nntpSocket.command (
123                 NntpConstants.COMMAND_GROUP + " " + newsgroupName );
124    
125               if ( responseCode.startsWith ( "480" ) )
126               {
127                 // 480 Authentication Required
128    
129                 AgoracastLib.authenticate ( nntpSocket, agoracastMediator );
130    
131                 // throws SecurityException if it fails
132    
133                 responseCode = nntpSocket.command (
134                   NntpConstants.COMMAND_GROUP + " " + newsgroupName );
135               }
136    
137               // 211 n f l s group selected
138               //   (n = estimated number of articles in group,
139               //   f = first article number in the group,
140               //   l = last article number in the group,
141               //   s = name of the group.)
142               // 411 no such news group
143    
144               if ( responseCode.startsWith ( "211" ) )
145               {
146                 responseCode = nntpSocket.command (
147                   NntpConstants.COMMAND_ARTICLE + " " + articleId );
148    
149                 // 220 n <a> article retrieved - head and body follow
150                 //    (n = article number, <a> = message-id)
151                 // 221 n <a> article retrieved - head follows
152                 // 222 n <a> article retrieved - body follows
153                 // 223 n <a> article retrieved - request text separately
154                 // 412 no newsgroup has been selected
155                 // 420 no current article has been selected
156                 // 423 no such article number in this group
157                 // 430 no such article found
158    
159                 if ( responseCode.startsWith ( "220" ) )
160                 {
161                   BufferedReader  bufferedReader
162                     = nntpSocket.getBufferedReader ( );
163    
164                   String  line;
165    
166                   while ( true )
167                   {
168                     line = bufferedReader.readLine ( );
169    
170                     if ( ".".equals ( line )
171                       || ( line == null ) )
172                     {
173                       break;
174                     }
175    
176                     record ( line );
177                   }
178                 }
179               }
180             }
181    
182             nntpSocket.command ( NntpConstants.COMMAND_QUIT );
183           }
184           catch ( Exception  ex )
185           {
186             record ( ex );
187           }
188           finally
189           {
190             if ( nntpSocket != null )
191             {
192               try
193               {
194                 nntpSocket.close ( );
195    
196               }
197               catch ( Exception  ex )
198               {
199                 record ( ex );
200               }
201             }
202    
203             cancelButton.setText ( "Done" );  
204           }
205         }
206    
207         public void  actionPerformed ( ActionEvent  actionEvent )
208         //////////////////////////////////////////////////////////////////////
209         {
210           try
211           {
212             Object  source = actionEvent.getSource ( );
213    
214             if ( source == cancelButton )
215             {
216               if ( nntpSocket != null )
217               {
218    // Is this hanging?
219    
220                 nntpSocket.close ( );
221               }
222    
223               agoracastBrowsePanel.showTable ( );
224             }
225           }
226           catch ( Exception  ex )
227           {
228             record ( ex );
229           }
230         }
231    
232         //////////////////////////////////////////////////////////////////////
233         //////////////////////////////////////////////////////////////////////
234    
235    // cut-and-paste from AgoracastSendPanel and AgoracastDownloadPanel,
236    // make reusable, see LogPanel
237    
238         public synchronized void  record ( String  message )
239         //////////////////////////////////////////////////////////////////////
240         {
241           jTextArea.append ( '\n' + message );
242    
243           String  text = jTextArea.getText ( );
244    
245           int  textLength = text.length ( );
246    
247           if ( textLength > AgoracastConstants.LOG_TEXT_LENGTH_MAX )
248           {
249             jTextArea.setText ( text.substring (
250               textLength - AgoracastConstants.LOG_TEXT_LENGTH_MAX ) );
251           }
252         }
253    
254         public synchronized void  record ( Throwable  throwable )
255         //////////////////////////////////////////////////////////////////////
256         {
257           record ( '\n' + throwable.toString ( ) );
258         }
259    
260    
261         public synchronized void  record (
262           String  message, Throwable  throwable )
263         //////////////////////////////////////////////////////////////////////
264         {
265           record ( '\n' + message + '\n' + throwable.toString ( ) );
266         }
267    
268         //////////////////////////////////////////////////////////////////////
269         //////////////////////////////////////////////////////////////////////
270         }