1 17 18 package org.apache.james.mailrepository; 19 20 import org.apache.avalon.cornerstone.services.store.ObjectRepository; 21 import org.apache.avalon.cornerstone.services.store.Store; 22 import org.apache.avalon.cornerstone.services.store.StreamRepository; 23 import org.apache.avalon.framework.activity.Initializable; 24 import org.apache.avalon.framework.component.Component; 25 import org.apache.avalon.framework.component.ComponentException; 26 import org.apache.avalon.framework.component.ComponentManager; 27 import org.apache.avalon.framework.component.Composable; 28 import org.apache.avalon.framework.configuration.Configurable; 29 import org.apache.avalon.framework.configuration.Configuration; 30 import org.apache.avalon.framework.configuration.ConfigurationException; 31 import org.apache.avalon.framework.configuration.DefaultConfiguration; 32 import org.apache.avalon.framework.logger.AbstractLogEnabled; 33 import org.apache.james.core.MailImpl; 34 import org.apache.james.core.MimeMessageWrapper; 35 import org.apache.james.services.MailRepository; 36 import org.apache.james.util.Lock; 37 38 import java.io.OutputStream ; 39 import java.util.*; 40 import javax.mail.MessagingException ; 41 42 53 public class AvalonMailRepository 54 extends AbstractLogEnabled 55 implements MailRepository, Component, Configurable, Composable, Initializable { 56 57 60 protected final static boolean DEEP_DEBUG = false; 61 62 private static final String TYPE = "MAIL"; 63 64 private Lock lock; 65 private Store store; 66 private StreamRepository sr; 67 private ObjectRepository or; 68 private String destination; 69 private Set keys; 70 private boolean fifo; 71 72 75 public void compose( final ComponentManager componentManager ) 76 throws ComponentException { 77 store = (Store)componentManager. 78 lookup( "org.apache.avalon.cornerstone.services.store.Store" ); 79 } 80 81 84 public void configure(Configuration conf) throws ConfigurationException { 85 destination = conf.getAttribute("destinationURL"); 86 if (getLogger().isDebugEnabled()) { 87 getLogger().debug("AvalonMailRepository.destinationURL: " + destination); 88 } 89 String checkType = conf.getAttribute("type"); 90 if (! (checkType.equals("MAIL") || checkType.equals("SPOOL")) ) { 91 String exceptionString = "Attempt to configure AvalonMailRepository as " + 92 checkType; 93 if (getLogger().isWarnEnabled()) { 94 getLogger().warn(exceptionString); 95 } 96 throw new ConfigurationException(exceptionString); 97 } 98 fifo = conf.getAttributeAsBoolean("FIFO", false); 99 } 101 102 105 public void initialize() 106 throws Exception { 107 try { 108 DefaultConfiguration objectConfiguration 110 = new DefaultConfiguration( "repository", 111 "generated:AvalonFileRepository.compose()" ); 112 113 objectConfiguration.setAttribute("destinationURL", destination); 114 objectConfiguration.setAttribute("type", "OBJECT"); 115 objectConfiguration.setAttribute("model", "SYNCHRONOUS"); 116 117 DefaultConfiguration streamConfiguration 118 = new DefaultConfiguration( "repository", 119 "generated:AvalonFileRepository.compose()" ); 120 121 streamConfiguration.setAttribute( "destinationURL", destination ); 122 streamConfiguration.setAttribute( "type", "STREAM" ); 123 streamConfiguration.setAttribute( "model", "SYNCHRONOUS" ); 124 125 sr = (StreamRepository) store.select(streamConfiguration); 126 or = (ObjectRepository) store.select(objectConfiguration); 127 lock = new Lock(); 128 keys = Collections.synchronizedSet(new HashSet()); 129 130 131 HashSet streamKeys = new HashSet(); 133 for (Iterator i = sr.list(); i.hasNext(); ) { 134 streamKeys.add(i.next()); 135 } 136 HashSet objectKeys = new HashSet(); 137 for (Iterator i = or.list(); i.hasNext(); ) { 138 objectKeys.add(i.next()); 139 } 140 141 Collection strandedStreams = (Collection)streamKeys.clone(); 142 strandedStreams.removeAll(objectKeys); 143 for (Iterator i = strandedStreams.iterator(); i.hasNext(); ) { 144 String key = (String )i.next(); 145 remove(key); 146 } 147 148 Collection strandedObjects = (Collection)objectKeys.clone(); 149 strandedObjects.removeAll(streamKeys); 150 for (Iterator i = strandedObjects.iterator(); i.hasNext(); ) { 151 String key = (String )i.next(); 152 remove(key); 153 } 154 155 keys.clear(); 158 for (Iterator i = or.list(); i.hasNext(); ) { 159 keys.add(i.next()); 160 } 161 if (getLogger().isDebugEnabled()) { 162 StringBuffer logBuffer = 163 new StringBuffer (128) 164 .append(this.getClass().getName()) 165 .append(" created in ") 166 .append(destination); 167 getLogger().debug(logBuffer.toString()); 168 } 169 } catch (Exception e) { 170 final String message = "Failed to retrieve Store component:" + e.getMessage(); 171 getLogger().error( message, e ); 172 throw e; 173 } 174 } 175 176 183 public boolean unlock(String key) { 184 if (lock.unlock(key)) { 185 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) { 186 StringBuffer debugBuffer = 187 new StringBuffer (256) 188 .append("Unlocked ") 189 .append(key) 190 .append(" for ") 191 .append(Thread.currentThread().getName()) 192 .append(" @ ") 193 .append(new java.util.Date (System.currentTimeMillis())); 194 getLogger().debug(debugBuffer.toString()); 195 } 196 return true; 200 } else { 201 return false; 202 } 203 } 204 205 212 public boolean lock(String key) { 213 if (lock.lock(key)) { 214 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) { 215 StringBuffer debugBuffer = 216 new StringBuffer (256) 217 .append("Locked ") 218 .append(key) 219 .append(" for ") 220 .append(Thread.currentThread().getName()) 221 .append(" @ ") 222 .append(new java.util.Date (System.currentTimeMillis())); 223 getLogger().debug(debugBuffer.toString()); 224 } 225 return true; 229 } else { 230 return false; 231 } 232 } 233 234 240 public void store(MailImpl mc) throws MessagingException { 241 try { 242 String key = mc.getName(); 243 boolean wasLocked = lock.isLocked(key); 245 246 if (!wasLocked) { 247 lock.lock(key); 249 } 250 try { 251 if (!keys.contains(key)) { 252 keys.add(key); 253 } 254 boolean saveStream = true; 255 256 if (mc.getMessage() instanceof MimeMessageWrapper) { 257 MimeMessageWrapper wrapper = (MimeMessageWrapper) mc.getMessage(); 258 if (DEEP_DEBUG) { 259 System.out.println("Retrieving from: " + wrapper.getSourceId()); 260 StringBuffer debugBuffer = 261 new StringBuffer (64) 262 .append("Saving to: ") 263 .append(destination) 264 .append("/") 265 .append(mc.getName()); 266 System.out.println(debugBuffer.toString()); 267 System.out.println("Modified: " + wrapper.isModified()); 268 } 269 StringBuffer destinationBuffer = 270 new StringBuffer (128) 271 .append(destination) 272 .append("/") 273 .append(mc.getName()); 274 if (wrapper.getSourceId().equals(destinationBuffer.toString()) && !wrapper.isModified()) { 275 saveStream = false; 279 } 280 } 281 if (saveStream) { 282 OutputStream out = null; 283 try { 284 out = sr.put(key); 285 mc.writeMessageTo(out); 286 } finally { 287 if (out != null) out.close(); 288 } 289 } 290 or.put(key, mc); 292 } finally { 293 if (!wasLocked) { 294 lock.unlock(key); 296 } 297 } 298 299 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) { 300 StringBuffer logBuffer = 301 new StringBuffer (64) 302 .append("Mail ") 303 .append(key) 304 .append(" stored."); 305 getLogger().debug(logBuffer.toString()); 306 } 307 308 synchronized (this) { 309 notify(); 311 } 312 } catch (Exception e) { 313 getLogger().error("Exception storing mail: " + e); 314 throw new MessagingException ("Exception caught while storing Message Container: " + e); 315 } 316 } 317 318 325 public MailImpl retrieve(String key) throws MessagingException { 326 if ((DEEP_DEBUG) && (getLogger().isDebugEnabled())) { 327 getLogger().debug("Retrieving mail: " + key); 328 } 329 try { 330 MailImpl mc = null; 331 try { 332 mc = (MailImpl) or.get(key); 333 } catch (RuntimeException re) { 334 StringBuffer exceptionBuffer = 335 new StringBuffer (128) 336 .append("Exception retrieving mail: ") 337 .append(re.toString()) 338 .append(", so we're deleting it... good riddance!"); 339 getLogger().debug(exceptionBuffer.toString()); 340 remove(key); 341 return null; 342 } 343 MimeMessageAvalonSource source = new MimeMessageAvalonSource(sr, destination, key); 344 mc.setMessage(new MimeMessageWrapper(source)); 345 346 return mc; 347 } catch (Exception me) { 348 getLogger().error("Exception retrieving mail: " + me); 349 throw new MessagingException ("Exception while retrieving mail: " + me.getMessage()); 350 } 351 } 352 353 358 public void remove(MailImpl mail) throws MessagingException { 359 remove(mail.getName()); 360 } 361 362 363 369 public void remove(Collection mails) throws MessagingException { 370 Iterator delList = mails.iterator(); 371 while (delList.hasNext()) { 372 remove((MailImpl)delList.next()); 373 } 374 } 375 376 381 public void remove(String key) throws MessagingException { 382 if (lock(key)) { 383 try { 384 keys.remove(key); 385 sr.remove(key); 386 or.remove(key); 387 } finally { 388 unlock(key); 389 } 390 } else { 391 StringBuffer exceptionBuffer = 392 new StringBuffer (64) 393 .append("Cannot lock ") 394 .append(key) 395 .append(" to remove it"); 396 throw new MessagingException (exceptionBuffer.toString()); 397 } 398 } 399 400 406 public Iterator list() { 407 final ArrayList clone; 410 synchronized(keys) { 411 clone = new ArrayList(keys); 412 } 413 if (fifo) Collections.sort(clone); return clone.iterator(); 415 } 416 } 417 | Popular Tags |