001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 020 package org.apache.geronimo.javamail.store.nntp; 021 022 import javax.mail.Flags; 023 import javax.mail.Folder; 024 import javax.mail.IllegalWriteException; 025 import javax.mail.Message; 026 import javax.mail.MessagingException; 027 import javax.mail.MethodNotSupportedException; 028 import javax.mail.Session; 029 import javax.mail.event.ConnectionEvent; 030 031 import org.apache.geronimo.javamail.transport.nntp.NNTPConnection; 032 033 /** 034 * The base NNTP implementation of the javax.mail.Folder This is a base class 035 * for both the Root NNTP server and each NNTP group folder. 036 * 037 * @see javax.mail.Folder 038 * 039 * @version $Rev: 437941 $ 040 */ 041 public class NNTPFolder extends Folder { 042 043 // our active connection. 044 protected NNTPConnection connection; 045 046 // our attached session 047 protected Session session; 048 049 // the name of this folder (either the name of the server for the root or 050 // the news group name). 051 protected String name; 052 053 // the "full" name of the folder. For the root folder, this is the name 054 // returned by the connection 055 // welcome string. Otherwise, this is the same as the name. 056 protected String fullName; 057 058 // the parent folder. For the root folder, this is null. For a group folder, 059 // this is the root. 060 protected Folder parent; 061 062 // the folder open state 063 protected boolean folderOpen = false; 064 065 // the folder message count. For the root folder, this is always 0. 066 protected int messageCount = 0; 067 068 // the persistent flags we save in the store (basically just the SEEN flag). 069 protected Flags permanentFlags; 070 071 /** 072 * Super class constructor the base NNTPFolder class. 073 * 074 * @param store 075 * The javamail store this folder is attached to. 076 */ 077 protected NNTPFolder(NNTPStore store) { 078 super(store); 079 // get the active connection from the store...all commands are sent 080 // there 081 this.connection = store.getConnection(); 082 this.session = store.getSession(); 083 084 // set up our permanent flags bit. 085 permanentFlags = new Flags(); 086 permanentFlags.add(Flags.Flag.SEEN); 087 } 088 089 /** 090 * Retrieve the folder name. 091 * 092 * @return The folder's name. 093 */ 094 public String getName() { 095 return name; 096 } 097 098 /** 099 * 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 }