View Javadoc

1   /**
2    *
3    * Copyright 2006 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  
18  package org.apache.geronimo.javamail.store.nntp;
19  
20  import java.io.File;
21  import java.io.PrintStream;
22  import java.util.Iterator;
23  
24  import javax.mail.Folder;
25  import javax.mail.MessagingException;
26  import javax.mail.Session;
27  import javax.mail.Store;
28  import javax.mail.URLName;
29  
30  import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrc;
31  import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrcFile;
32  import org.apache.geronimo.javamail.store.nntp.newsrc.NNTPNewsrcGroup;
33  import org.apache.geronimo.javamail.transport.nntp.NNTPConnection;
34  import org.apache.geronimo.mail.util.SessionUtil;
35  
36  /**
37   * NNTP implementation of javax.mail.Store POP protocol spec is implemented in
38   * org.apache.geronimo.javamail.store.pop3.NNTPConnection
39   * 
40   * @version $Rev: 432884 $ $Date: 2006-08-19 14:53:20 -0700 (Sat, 19 Aug 2006) $
41   */
42  public class NNTPStore extends Store {
43  
44      protected static final String NNTP_AUTH = "auth";
45  
46      protected static final String NNTP_PORT = "port";
47  
48      protected static final String NNTP_NEWSRC = "newsrc";
49  
50      protected static final String protocol = "nntp";
51  
52      protected static final int DEFAULT_NNTP_PORT = 119;
53  
54      // the active connection object.
55      protected NNTPConnection connection;
56  
57      // the newsrc file where we store subscriptions and seen message markers.
58      protected NNTPNewsrc newsrc;
59  
60      // the root folder
61      protected NNTPRootFolder root;
62  
63      // our session provided debug output stream.
64      protected PrintStream debugStream;
65  
66      /**
67       * Construct an NNTPStore item. This will load the .newsrc file associated
68       * with the server.
69       * 
70       * @param session
71       *            The owning javamail Session.
72       * @param urlName
73       *            The Store urlName, which can contain server target
74       *            information.
75       */
76      public NNTPStore(Session session, URLName urlName) {
77          super(session, urlName);
78  
79          // get our debug output.
80          debugStream = session.getDebugOut();
81  
82      }
83  
84      /**
85       * @see javax.mail.Store#getDefaultFolder()
86       * 
87       * This returns a root folder object for all of the news groups.
88       */
89      public Folder getDefaultFolder() throws MessagingException {
90          checkConnectionStatus();
91          if (root == null) {
92              return new NNTPRootFolder(this, connection.getHost(), connection.getWelcomeString());
93          }
94          return root;
95      }
96  
97      /**
98       * @see javax.mail.Store#getFolder(java.lang.String)
99       */
100     public Folder getFolder(String name) throws MessagingException {
101         return getDefaultFolder().getFolder(name);
102     }
103 
104     /**
105      * 
106      * @see javax.mail.Store#getFolder(javax.mail.URLName)
107      */
108     public Folder getFolder(URLName url) throws MessagingException {
109         return getDefaultFolder().getFolder(url.getFile());
110     }
111 
112     /**
113      * @see javax.mail.Service#protocolConnect(java.lang.String, int,
114      *      java.lang.String, java.lang.String)
115      */
116     protected synchronized boolean protocolConnect(String host, int port, String username, String password)
117             throws MessagingException {
118         if (debug) {
119             debugOut("Connecting to server " + host + ":" + port + " for user " + username);
120         }
121 
122         // first check to see if we need to authenticate. If we need this, then
123         // we must have a username and
124         // password specified. Failing this may result in a user prompt to
125         // collect the information.
126         boolean mustAuthenticate = getBooleanProperty(NNTP_AUTH, false);
127 
128         // if we need to authenticate, and we don't have both a userid and
129         // password, then we fail this
130         // immediately. The Service.connect() method will try to obtain the user
131         // information and retry the
132         // connection one time.
133         if (mustAuthenticate && (username == null || password == null)) {
134             return false;
135         }
136 
137         // if the port is defaulted, then see if we have something configured in
138         // the session.
139         // if not configured, we just use the default default.
140         if (port == -1) {
141             // check for a property and fall back on the default if it's not
142             // set.
143             port = getIntProperty(NNTP_PORT, DEFAULT_NNTP_PORT);
144         }
145 
146         // create socket and connect to server.
147         connection = new NNTPConnection(protocol, session, host, port, username, password, debug);
148         connection.connect();
149 
150         // see if we have a newsrc file location specified
151         String newsrcFile = getProperty(NNTP_NEWSRC);
152 
153         File source = null;
154 
155         // not given as a property? Then look for a file in user.home
156         if (newsrcFile != null) {
157             source = new File(newsrcFile);
158         } else {
159             // ok, look for a file in the user.home directory. If possible,
160             // we'll try for a file
161             // with the hostname appended.
162             String home = SessionUtil.getProperty("user.home");
163 
164             // try for a host-specific file first. If not found, use (and
165             // potentially create) a generic
166             // .newsrc file.
167             newsrcFile = ".newsrc-" + host;
168             source = new File(home, newsrcFile);
169             if (!source.exists()) {
170                 source = new File(home, ".newsrc");
171             }
172         }
173 
174         // now create a newsrc read and load the file.
175         newsrc = new NNTPNewsrcFile(source);
176         newsrc.load();
177 
178         // we're going to return success here, but in truth, the server may end
179         // up asking for our
180         // bonafides at any time, and we'll be expected to authenticate then.
181         return true;
182     }
183 
184     /**
185      * @see javax.mail.Service#close()
186      */
187     public void close() throws MessagingException {
188         // This is done to ensure proper event notification.
189         super.close();
190         // persist the newsrc file, if possible
191         newsrc.close();
192         connection.close();
193         connection = null;
194     }
195 
196     private void checkConnectionStatus() throws MessagingException {
197         if (!this.isConnected()) {
198             throw new MessagingException("Not connected ");
199         }
200     }
201 
202     /**
203      * Internal debug output routine.
204      * 
205      * @param value
206      *            The string value to output.
207      */
208     void debugOut(String message) {
209         debugStream.println("NNTPTransport DEBUG: " + message);
210     }
211 
212     /**
213      * Internal debugging routine for reporting exceptions.
214      * 
215      * @param message
216      *            A message associated with the exception context.
217      * @param e
218      *            The received exception.
219      */
220     void debugOut(String message, Throwable e) {
221         debugOut("Received exception -> " + message);
222         debugOut("Exception message -> " + e.getMessage());
223         e.printStackTrace(debugStream);
224     }
225 
226     /**
227      * Retrieve the server connection created by this store.
228      * 
229      * @return The active connection object.
230      */
231     NNTPConnection getConnection() {
232         return connection;
233     }
234 
235     /**
236      * Retrieve the Session object this Store is operating under.
237      * 
238      * @return The attached Session instance.
239      */
240     Session getSession() {
241         return session;
242     }
243 
244     /**
245      * Retrieve all of the groups we nave persistent store information about.
246      * 
247      * @return The set of groups contained in the newsrc file.
248      */
249     Iterator getNewsrcGroups() {
250         return newsrc.getGroups();
251     }
252 
253     /**
254      * Retrieve the newsrc group information for a named group. If the file does
255      * not currently include this group, an unsubscribed group will be added to
256      * the file.
257      * 
258      * @param name
259      *            The name of the target group.
260      * 
261      * @return The NNTPNewsrcGroup item corresponding to this name.
262      */
263     NNTPNewsrcGroup getNewsrcGroup(String name) {
264         return newsrc.getGroup(name);
265     }
266 
267     /**
268      * Get a property associated with this mail protocol.
269      * 
270      * @param name
271      *            The name of the property.
272      * 
273      * @return The property value (returns null if the property has not been
274      *         set).
275      */
276     String getProperty(String name) {
277         // the name we're given is the least qualified part of the name. We
278         // construct the full property name
279         // using the protocol (either "nntp" or "nntp-post").
280         String fullName = "mail." + protocol + "." + name;
281         return session.getProperty(fullName);
282     }
283 
284     /**
285      * Get a property associated with this mail session. Returns the provided
286      * default if it doesn't exist.
287      * 
288      * @param name
289      *            The name of the property.
290      * @param defaultValue
291      *            The default value to return if the property doesn't exist.
292      * 
293      * @return The property value (returns defaultValue if the property has not
294      *         been set).
295      */
296     String getProperty(String name, String defaultValue) {
297         // the name we're given is the least qualified part of the name. We
298         // construct the full property name
299         // using the protocol (either "nntp" or "nntp-post").
300         String fullName = "mail." + protocol + "." + name;
301         return SessionUtil.getProperty(session, fullName, defaultValue);
302     }
303 
304     /**
305      * Get a property associated with this mail session as an integer value.
306      * Returns the default value if the property doesn't exist or it doesn't
307      * have a valid int value.
308      * 
309      * @param name
310      *            The name of the property.
311      * @param defaultValue
312      *            The default value to return if the property doesn't exist.
313      * 
314      * @return The property value converted to an int.
315      */
316     int getIntProperty(String name, int defaultValue) {
317         // the name we're given is the least qualified part of the name. We
318         // construct the full property name
319         // using the protocol (either "nntp" or "nntp-post").
320         String fullName = "mail." + protocol + "." + name;
321         return SessionUtil.getIntProperty(session, fullName, defaultValue);
322     }
323 
324     /**
325      * Get a property associated with this mail session as an boolean value.
326      * Returns the default value if the property doesn't exist or it doesn't
327      * have a valid int value.
328      * 
329      * @param name
330      *            The name of the property.
331      * @param defaultValue
332      *            The default value to return if the property doesn't exist.
333      * 
334      * @return The property value converted to a boolean
335      */
336     boolean getBooleanProperty(String name, boolean defaultValue) {
337         // the name we're given is the least qualified part of the name. We
338         // construct the full property name
339         // using the protocol (either "nntp" or "nntp-post").
340         String fullName = "mail." + protocol + "." + name;
341         return SessionUtil.getBooleanProperty(session, fullName, defaultValue);
342     }
343 }