View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *  http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.geronimo.javamail.store.nntp;
21  
22  import javax.mail.Flags;
23  import javax.mail.Folder;
24  import javax.mail.IllegalWriteException;
25  import javax.mail.Message;
26  import javax.mail.MessagingException;
27  import javax.mail.MethodNotSupportedException;
28  import javax.mail.Session;
29  import javax.mail.event.ConnectionEvent;
30  
31  import org.apache.geronimo.javamail.transport.nntp.NNTPConnection;
32  
33  /**
34   * The base NNTP implementation of the javax.mail.Folder This is a base class
35   * for both the Root NNTP server and each NNTP group folder.
36   * 
37   * @see javax.mail.Folder
38   * 
39   * @version $Rev: 437941 $
40   */
41  public class NNTPFolder extends Folder {
42  
43      // our active connection.
44      protected NNTPConnection connection;
45  
46      // our attached session
47      protected Session session;
48  
49      // the name of this folder (either the name of the server for the root or
50      // the news group name).
51      protected String name;
52  
53      // the "full" name of the folder. For the root folder, this is the name
54      // returned by the connection
55      // welcome string. Otherwise, this is the same as the name.
56      protected String fullName;
57  
58      // the parent folder. For the root folder, this is null. For a group folder,
59      // this is the root.
60      protected Folder parent;
61  
62      // the folder open state
63      protected boolean folderOpen = false;
64  
65      // the folder message count. For the root folder, this is always 0.
66      protected int messageCount = 0;
67  
68      // the persistent flags we save in the store (basically just the SEEN flag).
69      protected Flags permanentFlags;
70  
71      /**
72       * Super class constructor the base NNTPFolder class.
73       * 
74       * @param store
75       *            The javamail store this folder is attached to.
76       */
77      protected NNTPFolder(NNTPStore store) {
78          super(store);
79          // get the active connection from the store...all commands are sent
80          // there
81          this.connection = store.getConnection();
82          this.session = store.getSession();
83  
84          // set up our permanent flags bit.
85          permanentFlags = new Flags();
86          permanentFlags.add(Flags.Flag.SEEN);
87      }
88  
89      /**
90       * Retrieve the folder name.
91       * 
92       * @return The folder's name.
93       */
94      public String getName() {
95          return name;
96      }
97  
98      /**
99       * Retrieve the folder's full name (including hierarchy information). NNTP
100      * folders are flat, so the full name is generally the same as the name.
101      * 
102      * @return The full name value.
103      */
104     public String getFullName() {
105         return fullName;
106     }
107 
108     /**
109      * Returns the parent folder for this folder. Returns null if this is the
110      * root folder.
111      */
112     public Folder getParent() throws MessagingException {
113         return parent;
114     }
115 
116     /**
117      * Indicated whether the folder "exists" or not. Existance in this context
118      * indicates that the group still exists on the server.
119      * 
120      * @return
121      * @exception MessagingException
122      */
123     public boolean exists() throws MessagingException {
124         // by default, return true. This is really only the case for the root.
125         // The group folder will
126         // need to override this.
127         return true;
128     }
129 
130     /**
131      * List the subfolders. For group folders, this is a meaningless so we throw
132      * a MethodNotSupportedException.
133      * 
134      * @param pattern
135      *            The folder pattern string.
136      * 
137      * @return Never returns.
138      * @exception MessagingException
139      */
140     public Folder[] list(String pattern) throws MessagingException {
141         throw new MethodNotSupportedException("NNTP group folders cannot contain sub folders");
142     }
143 
144     /**
145      * Retrieve the list of subscribed folders that match the given pattern
146      * string.
147      * 
148      * @param pattern
149      *            The pattern string used for the matching
150      * 
151      * @return An array of matching folders from the subscribed list.
152      */
153     public Folder[] listSubscribed(String pattern) throws MessagingException {
154         throw new MethodNotSupportedException("NNTP group folders cannot contain sub folders");
155     }
156 
157     /**
158      * No sub folders, hence there is no notion of a seperator. We return a null
159      * character (consistent with what Sun returns for POP3 folders).
160      */
161     public char getSeparator() throws MessagingException {
162         return '\0';
163     }
164 
165     /**
166      * Return whether this folder can hold just messages or also subfolders.
167      * Only the root folder can hold other folders, so it will need to override.
168      * 
169      * @return Either Folder.HOLDS_MESSAGES or Folder.HOLDS_FOLDERS.
170      * @exception MessagingException
171      */
172     public int getType() throws MessagingException {
173         return HOLDS_MESSAGES;
174     }
175 
176     /**
177      * Create a new folder. NNTP folders are read only, so this is a nop.
178      * 
179      * @param type
180      *            The type of folder.
181      * 
182      * @return Not support, throws an exception.
183      * @exception MessagingException
184      */
185     public boolean create(int type) throws MessagingException {
186         throw new MethodNotSupportedException("Sub folders cannot be created in NNTP");
187     }
188 
189     /**
190      * Check for new messages. We always return false for the root folder. The
191      * group folders will need to override.
192      * 
193      * @return Always returns false.
194      * @exception MessagingException
195      */
196     public boolean hasNewMessages() throws MessagingException {
197         return false;
198     }
199 
200     /**
201      * Get a named subfolder from this folder. This only has meaning from the
202      * root NNTP folder.
203      * 
204      * @param name
205      *            The requested name.
206      * 
207      * @return If the folder exists, returns a Folder object representing the
208      *         named folder.
209      * @exception MessagingException
210      */
211     public Folder getFolder(String name) throws MessagingException {
212         throw new MethodNotSupportedException("NNTP Group folders do not support sub folders");
213     }
214 
215     /**
216      * Delete a folder. This is not supported for NNTP.
217      * 
218      * @param recurse
219      *            The recusion flag.
220      * 
221      * @return Never returns.
222      * @exception MessagingException
223      */
224     public boolean delete(boolean recurse) throws MessagingException {
225         throw new MethodNotSupportedException("Deleting of NNTP folders is not supported");
226     }
227 
228     /**
229      * Rename a folder. Not supported for NNTP folders.
230      * 
231      * @param f
232      *            The new folder specifying the rename location.
233      * 
234      * @return
235      * @exception MessagingException
236      */
237     public boolean renameTo(Folder f) throws MessagingException {
238         throw new MethodNotSupportedException("Renaming of NNTP folders is not supported.");
239     }
240 
241     /**
242      * @see javax.mail.Folder#open(int)
243      */
244     public void open(int mode) throws MessagingException {
245 
246         // we don't support READ_WRITE mode, so don't allow opening in that
247         // mode.
248         if (mode == READ_WRITE) {
249             throw new IllegalWriteException("Newsgroup folders cannot be opened read/write");
250         }
251 
252         // an only be performed on a closed folder
253         checkClosed();
254 
255         this.mode = mode;
256 
257         // perform folder type-specific open actions.
258         openFolder();
259 
260         folderOpen = true;
261 
262         notifyConnectionListeners(ConnectionEvent.OPENED);
263     }
264 
265     /**
266      * Perform folder type-specific open actions. The default action is to do
267      * nothing.
268      * 
269      * @exception MessagingException
270      */
271     protected void openFolder() throws MessagingException {
272     }
273 
274     /**
275      * Peform folder type-specific close actions. The default action is to do
276      * nothing.
277      * 
278      * @exception MessagingException
279      */
280     protected void closeFolder() throws MessagingException {
281     }
282 
283     /**
284      * Close the folder. Cleans up resources, potentially expunges messages
285      * marked for deletion, and sends an event notification.
286      * 
287      * @param expunge
288      *            The expunge flag, which is ignored for NNTP folders.
289      * 
290      * @exception MessagingException
291      */
292     public void close(boolean expunge) throws MessagingException {
293         // Can only be performed on an open folder
294         checkOpen();
295 
296         // give the subclasses an opportunity to do some cleanup
297         closeFolder();
298 
299         folderOpen = false;
300         notifyConnectionListeners(ConnectionEvent.CLOSED);
301     }
302 
303     /**
304      * Tests the open status of the folder.
305      * 
306      * @return true if the folder is open, false otherwise.
307      */
308     public boolean isOpen() {
309         return folderOpen;
310     }
311 
312     /**
313      * Get the permanentFlags
314      * 
315      * @return The set of permanent flags we support (only SEEN).
316      */
317     public Flags getPermanentFlags() {
318         // we need a copy of our master set.
319         return new Flags(permanentFlags);
320     }
321 
322     /**
323      * Get the count of messages in this folder.
324      * 
325      * @return The message count.
326      * @exception MessagingException
327      */
328     public int getMessageCount() throws MessagingException {
329         return messageCount;
330     }
331 
332     /**
333      * Checks wether the message is in cache, if not will create a new message
334      * object and return it.
335      * 
336      * @see javax.mail.Folder#getMessage(int)
337      */
338     public Message getMessage(int msgNum) throws MessagingException {
339         // for the base, we just throw an exception.
340         throw new MethodNotSupportedException("Root NNTP folder does not contain messages");
341     }
342 
343     /**
344      * Append messages to a folder. NNTP folders are read only, so this is not
345      * supported.
346      * 
347      * @param msgs
348      *            The list of messages to append.
349      * 
350      * @exception MessagingException
351      */
352     public void appendMessages(Message[] msgs) throws MessagingException {
353         throw new MethodNotSupportedException("Root NNTP folder does not contain messages");
354 
355     }
356 
357     /**
358      * Expunge messages marked for deletion and return a list of the Messages.
359      * Not supported for NNTP.
360      * 
361      * @return Never returns.
362      * @exception MessagingException
363      */
364     public Message[] expunge() throws MessagingException {
365         throw new MethodNotSupportedException("Root NNTP folder does not contain messages");
366     }
367 
368     /**
369      * Below is a list of convenience methods that avoid repeated checking for a
370      * value and throwing an exception
371      */
372 
373     /** Ensure the folder is open */
374     protected void checkOpen() throws IllegalStateException {
375         if (!folderOpen) {
376             throw new IllegalStateException("Folder is not Open");
377         }
378     }
379 
380     /** Ensure the folder is not open */
381     protected void checkClosed() throws IllegalStateException {
382         if (folderOpen) {
383             throw new IllegalStateException("Folder is Open");
384         }
385     }
386 
387     /**
388      * @see javax.mail.Folder#notifyMessageChangedListeners(int,
389      *      javax.mail.Message)
390      * 
391      * this method is protected and cannot be used outside of Folder, therefore
392      * had to explicitly expose it via a method in NNTPFolder, so that
393      * NNTPMessage has access to it
394      * 
395      * Bad design on the part of the Java Mail API.
396      */
397     public void notifyMessageChangedListeners(int type, Message m) {
398         super.notifyMessageChangedListeners(type, m);
399     }
400 
401     /**
402      * Retrieve the subscribed status for a folder. This default implementation
403      * just returns false (which is true for the root folder).
404      * 
405      * @return Always returns true.
406      */
407     public boolean isSubscribed() {
408         return false;
409     }
410 
411     /**
412      * Set the subscribed status for a folder.
413      * 
414      * @param flag
415      *            The new subscribed status.
416      * 
417      * @exception MessagingException
418      */
419     public void setSubscribed(boolean flag) throws MessagingException {
420         throw new MessagingException("Root NNTP folder cannot be subscribed to");
421     }
422 
423     /**
424      * Test if a given article number is marked as SEEN.
425      * 
426      * @param article
427      *            The target article number.
428      * 
429      * @return The articles current seen status.
430      */
431     public boolean isSeen(int article) {
432         return false;
433     }
434 
435     /**
436      * Set the SEEN status for an article.
437      * 
438      * @param article
439      *            The target article.
440      * @param flag
441      *            The new seen setting.
442      * 
443      * @exception MessagingException
444      */
445     public void setSeen(int article, boolean flag) throws MessagingException {
446         throw new MessagingException("Root NNTP folder does not contain articles");
447     }
448 
449 }