1 17 package org.alfresco.repo.content; 18 19 import java.io.IOException ; 20 import java.lang.reflect.Method ; 21 import java.nio.ByteBuffer ; 22 import java.nio.MappedByteBuffer ; 23 import java.nio.channels.FileChannel ; 24 import java.nio.channels.FileLock ; 25 import java.nio.channels.ReadableByteChannel ; 26 import java.nio.channels.WritableByteChannel ; 27 import java.util.List ; 28 29 import org.alfresco.error.AlfrescoRuntimeException; 30 import org.alfresco.repo.transaction.TransactionUtil; 31 import org.alfresco.service.cmr.repository.Content; 32 import org.alfresco.service.cmr.repository.ContentStreamListener; 33 import org.alfresco.service.transaction.TransactionService; 34 import org.apache.commons.logging.Log; 35 import org.apache.commons.logging.LogFactory; 36 import org.springframework.aop.AfterReturningAdvice; 37 38 43 public abstract class AbstractContent implements Content 44 { 45 private static Log logger = LogFactory.getLog(AbstractContent.class); 46 47 48 private TransactionService transactionService; 49 50 private String contentUrl; 51 private String mimetype; 52 private String encoding; 53 54 57 protected AbstractContent(String contentUrl) 58 { 59 if (contentUrl == null || contentUrl.length() == 0) 60 { 61 throw new IllegalArgumentException ("contentUrl must be a valid String"); 62 } 63 this.contentUrl = contentUrl; 64 } 65 66 71 protected TransactionService getTransactionService() 72 { 73 return transactionService; 74 } 75 76 public void setTransactionService(TransactionService transactionService) 77 { 78 this.transactionService = transactionService; 79 } 80 81 public String toString() 82 { 83 StringBuilder sb = new StringBuilder (100); 84 sb.append("Content") 85 .append("[ url=").append(contentUrl) 86 .append(", mimetype=").append(mimetype) 87 .append(", encoding=").append(encoding) 88 .append("]"); 89 return sb.toString(); 90 } 91 92 public String getContentUrl() 93 { 94 return contentUrl; 95 } 96 97 public String getMimetype() 98 { 99 return mimetype; 100 } 101 102 105 public void setMimetype(String mimetype) 106 { 107 this.mimetype = mimetype; 108 } 109 110 public String getEncoding() 111 { 112 return encoding; 113 } 114 115 118 public void setEncoding(String encoding) 119 { 120 this.encoding = encoding; 121 } 122 123 129 protected class ByteChannelCallbackAdvise implements AfterReturningAdvice 130 { 131 private List <ContentStreamListener> listeners; 132 133 public ByteChannelCallbackAdvise(List <ContentStreamListener> listeners) 134 { 135 this.listeners = listeners; 136 } 137 138 141 public void afterReturning(Object returnValue, Method method, Object [] args, Object target) throws Throwable 142 { 143 if (method.getName().equals("close")) 145 { 146 fireChannelClosed(); 147 } 148 } 149 150 private void fireChannelClosed() 151 { 152 if (listeners.size() == 0) 153 { 154 return; 156 } 157 if (transactionService == null) 159 { 160 throw new AlfrescoRuntimeException("A transaction service is required when there are listeners present"); 161 } 162 TransactionUtil.TransactionWork work = new TransactionUtil.TransactionWork() 163 { 164 public Object doWork() 165 { 166 for (ContentStreamListener listener : listeners) 168 { 169 listener.contentStreamClosed(); 170 } 171 return null; 172 } 173 }; 174 TransactionUtil.executeInUserTransaction(transactionService, work); 175 if (logger.isDebugEnabled()) 177 { 178 logger.debug("Content listeners called: close"); 179 } 180 } 181 } 182 183 189 protected class CallbackFileChannel extends FileChannel 190 { 191 192 private FileChannel delegate; 193 194 private List <ContentStreamListener> listeners; 195 196 200 public CallbackFileChannel( 201 FileChannel delegate, 202 List <ContentStreamListener> listeners) 203 { 204 if (delegate == null) 205 { 206 throw new IllegalArgumentException ("FileChannel delegate is required"); 207 } 208 if (delegate instanceof CallbackFileChannel) 209 { 210 throw new IllegalArgumentException ("FileChannel delegate may not be a CallbackFileChannel"); 211 } 212 213 this.delegate = delegate; 214 this.listeners = listeners; 215 } 216 217 220 @Override 221 protected void implCloseChannel() throws IOException 222 { 223 delegate.close(); 224 fireChannelClosed(); 225 } 226 227 230 private void fireChannelClosed() 231 { 232 if (listeners.size() == 0) 233 { 234 return; 236 } 237 if (transactionService == null) 239 { 240 throw new AlfrescoRuntimeException("A transaction service is required when there are listeners present"); 241 } 242 TransactionUtil.TransactionWork work = new TransactionUtil.TransactionWork() 243 { 244 public Object doWork() 245 { 246 for (ContentStreamListener listener : listeners) 248 { 249 listener.contentStreamClosed(); 250 } 251 return null; 252 } 253 }; 254 TransactionUtil.executeInUserTransaction(transactionService, work); 255 if (logger.isDebugEnabled()) 257 { 258 logger.debug("Content listeners called: close"); 259 } 260 } 261 262 @Override 263 public void force(boolean metaData) throws IOException 264 { 265 delegate.force(metaData); 266 } 267 268 @Override 269 public FileLock lock(long position, long size, boolean shared) throws IOException 270 { 271 return delegate.lock(position, size, shared); 272 } 273 274 @Override 275 public MappedByteBuffer map(MapMode mode, long position, long size) throws IOException 276 { 277 return delegate.map(mode, position, size); 278 } 279 280 @Override 281 public long position() throws IOException 282 { 283 return delegate.position(); 284 } 285 286 @Override 287 public FileChannel position(long newPosition) throws IOException 288 { 289 return delegate.position(newPosition); 290 } 291 292 @Override 293 public int read(ByteBuffer dst) throws IOException 294 { 295 return delegate.read(dst); 296 } 297 298 @Override 299 public int read(ByteBuffer dst, long position) throws IOException 300 { 301 return delegate.read(dst, position); 302 } 303 304 @Override 305 public long read(ByteBuffer [] dsts, int offset, int length) throws IOException 306 { 307 return delegate.read(dsts, offset, length); 308 } 309 310 @Override 311 public long size() throws IOException 312 { 313 return delegate.size(); 314 } 315 316 @Override 317 public long transferFrom(ReadableByteChannel src, long position, long count) throws IOException 318 { 319 return delegate.transferFrom(src, position, count); 320 } 321 322 @Override 323 public long transferTo(long position, long count, WritableByteChannel target) throws IOException 324 { 325 return delegate.transferTo(position, count, target); 326 } 327 328 @Override 329 public FileChannel truncate(long size) throws IOException 330 { 331 return delegate.truncate(size); 332 } 333 334 @Override 335 public FileLock tryLock(long position, long size, boolean shared) throws IOException 336 { 337 return delegate.tryLock(position, size, shared); 338 } 339 340 @Override 341 public int write(ByteBuffer src) throws IOException 342 { 343 return delegate.write(src); 344 } 345 346 @Override 347 public int write(ByteBuffer src, long position) throws IOException 348 { 349 return delegate.write(src, position); 350 } 351 352 @Override 353 public long write(ByteBuffer [] srcs, int offset, int length) throws IOException 354 { 355 return delegate.write(srcs, offset, length); 356 } 357 } 358 } 359 | Popular Tags |