1 17 package org.alfresco.filesys.smb.server.repo; 18 19 import java.io.FileNotFoundException ; 20 import java.io.IOException ; 21 import java.nio.ByteBuffer ; 22 import java.nio.channels.FileChannel ; 23 24 import org.alfresco.error.AlfrescoRuntimeException; 25 import org.alfresco.filesys.server.filesys.AccessDeniedException; 26 import org.alfresco.filesys.server.filesys.FileAttribute; 27 import org.alfresco.filesys.server.filesys.FileInfo; 28 import org.alfresco.filesys.server.filesys.FileOpenParams; 29 import org.alfresco.filesys.server.filesys.NetworkFile; 30 import org.alfresco.i18n.I18NUtil; 31 import org.alfresco.model.ContentModel; 32 import org.alfresco.repo.content.filestore.FileContentReader; 33 import org.alfresco.repo.transaction.TransactionUtil; 34 import org.alfresco.repo.transaction.TransactionUtil.TransactionWork; 35 import org.alfresco.service.cmr.repository.ContentAccessor; 36 import org.alfresco.service.cmr.repository.ContentData; 37 import org.alfresco.service.cmr.repository.ContentReader; 38 import org.alfresco.service.cmr.repository.ContentService; 39 import org.alfresco.service.cmr.repository.ContentWriter; 40 import org.alfresco.service.cmr.repository.NodeRef; 41 import org.alfresco.service.cmr.repository.NodeService; 42 import org.alfresco.service.transaction.TransactionService; 43 import org.apache.commons.logging.Log; 44 import org.apache.commons.logging.LogFactory; 45 46 54 public class ContentNetworkFile extends NetworkFile 55 { 56 private static final Log logger = LogFactory.getLog(ContentNetworkFile.class); 57 58 private TransactionService transactionService; 59 private NodeService nodeService; 60 private ContentService contentService; 61 private NodeRef nodeRef; 62 63 private FileChannel channel; 64 65 private ContentAccessor content; 66 67 private boolean modified; 68 69 71 private boolean writableChannel; 72 73 76 public static ContentNetworkFile createFile( 77 TransactionService transactionService, 78 NodeService nodeService, 79 ContentService contentService, 80 CifsHelper cifsHelper, 81 NodeRef nodeRef, 82 FileOpenParams params) 83 { 84 String path = params.getPath(); 85 86 89 ContentNetworkFile netFile = new ContentNetworkFile(transactionService, nodeService, contentService, nodeRef, path); 91 if (params.isReadOnlyAccess()) 93 { 94 netFile.setGrantedAccess(NetworkFile.READONLY); 95 } 96 else 97 { 98 netFile.setGrantedAccess(NetworkFile.READWRITE); 99 } 100 101 FileInfo fileInfo; 103 try 104 { 105 fileInfo = cifsHelper.getFileInformation(nodeRef, ""); 106 } 107 catch (FileNotFoundException e) 108 { 109 throw new AlfrescoRuntimeException("File not found when creating network file: " + nodeRef, e); 110 } 111 if (fileInfo.isDirectory()) 112 { 113 netFile.setAttributes(FileAttribute.Directory); 114 } 115 else 116 { 117 119 netFile.setFileSize(fileInfo.getSize()); 120 } 121 122 124 if ( fileInfo.hasCreationDateTime()) 125 netFile.setCreationDate( fileInfo.getCreationDateTime()); 126 127 if ( fileInfo.hasModifyDateTime()) 128 netFile.setModifyDate(fileInfo.getModifyDateTime()); 129 130 if ( fileInfo.hasAccessDateTime()) 131 netFile.setAccessDate(fileInfo.getAccessDateTime()); 132 133 135 netFile.setAttributes(fileInfo.getFileAttributes()); 136 137 139 if ( netFile.isReadOnly()) 140 netFile.setGrantedAccess(NetworkFile.READONLY); 141 142 if (logger.isDebugEnabled()) 144 { 145 logger.debug("Created network file: \n" + 146 " node: " + nodeRef + "\n" + 147 " param: " + params + "\n" + 148 " netfile: " + netFile); 149 } 150 return netFile; 151 } 152 153 162 private ContentNetworkFile( 163 TransactionService transactionService, 164 NodeService nodeService, 165 ContentService contentService, 166 NodeRef nodeRef, 167 String name) 168 { 169 super(name); 170 setFullName(name); 171 this.transactionService = transactionService; 172 this.nodeService = nodeService; 173 this.contentService = contentService; 174 this.nodeRef = nodeRef; 175 } 176 177 182 public String toString() 183 { 184 StringBuilder sb = new StringBuilder (50); 185 sb.append("ContentNetworkFile:") 186 .append("[ node=").append(nodeRef) 187 .append(", channel=").append(channel) 188 .append(writableChannel ? "(Write)" : "(Read)") 189 .append(", writable=").append(isWritable()) 190 .append(", content=").append(content) 191 .append(", modified=").append(modified) 192 .append("]"); 193 return sb.toString(); 194 } 195 196 199 public NodeRef getNodeRef() 200 { 201 return nodeRef; 202 } 203 204 212 private boolean isWritable() 213 { 214 int access = getGrantedAccess(); 216 return (access == NetworkFile.READWRITE || access == NetworkFile.WRITEONLY); 217 } 218 219 224 public final boolean hasContent() 225 { 226 return content != null ? true : false; 227 } 228 229 244 private synchronized void openContent(boolean write, boolean trunc) throws AccessDeniedException, AlfrescoRuntimeException 245 { 246 if (isDirectory()) 247 { 248 throw new AlfrescoRuntimeException("Unable to open channel for a directory network file: " + this); 249 } 250 251 253 else if ( write && writableChannel == false && channel != null) 254 { 255 257 try 258 { 259 channel.close(); 260 channel = null; 261 } 262 catch (IOException ex) 263 { 264 logger.error("Error closing read-only channel", ex); 265 } 266 267 269 if ( logger.isDebugEnabled()) 270 logger.debug("Switching to writable channel for " + getName()); 271 } 272 else if (channel != null) 273 { 274 return; 276 } 277 278 if (write && !isWritable()) 280 { 281 throw new AccessDeniedException("The network file was created for read-only: " + this); 282 } 283 284 content = null; 285 if (write) 286 { 287 content = contentService.getWriter(nodeRef, ContentModel.PROP_CONTENT, false); 288 289 291 writableChannel = true; 292 293 295 channel = ((ContentWriter) content).getFileChannel( trunc); 296 } 297 else 298 { 299 content = contentService.getReader(nodeRef, ContentModel.PROP_CONTENT); 300 content = FileContentReader.getSafeContentReader( 302 (ContentReader) content, 303 I18NUtil.getMessage(FileContentReader.MSG_MISSING_CONTENT), 304 nodeRef, content); 305 306 308 writableChannel = false; 309 310 channel = ((ContentReader) content).getFileChannel(); 312 } 313 } 314 315 320 public synchronized void closeFile() throws IOException 321 { 322 if (isDirectory()) { 324 return; 325 } 326 else if (channel == null) { 328 return; 329 } 330 331 332 if (modified) { 334 TransactionWork<Object > closeWork = new TransactionWork<Object >() 339 { 340 public Object doWork() throws Exception 341 { 342 channel.close(); 345 channel = null; 346 ContentData contentData = content.getContentData(); 348 nodeService.setProperty(nodeRef, ContentModel.PROP_CONTENT, contentData); 349 return null; 351 } 352 }; 353 TransactionUtil.executeInUserTransaction(transactionService, closeWork); 354 } 355 else 356 { 357 channel.close(); 359 channel = null; 360 } 363 } 364 365 371 public synchronized void truncateFile(long size) throws IOException 372 { 373 376 if ( hasContent() == false && size == 0L) 377 { 378 380 openContent(true, true); 381 } 382 else 383 { 384 386 openContent(true, false); 387 388 390 channel.truncate(size); 391 } 392 393 395 modified = true; 396 397 399 if (logger.isDebugEnabled()) 400 { 401 logger.debug("Truncated channel: " + 402 " net file: " + this + "\n" + 403 " size: " + size); 404 } 405 } 406 407 416 public synchronized void writeFile(byte[] buffer, int length, int position, long fileOffset) throws IOException 417 { 418 420 openContent(true, false); 421 422 424 ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, position, length); 425 int count = channel.write(byteBuffer, fileOffset); 426 427 429 modified = true; 430 431 433 setFileSize(channel.size()); 434 435 437 if (logger.isDebugEnabled()) 438 { 439 logger.debug("Wrote to channel: " + 440 " net file: " + this + "\n" + 441 " written: " + count); 442 } 443 } 444 445 455 public synchronized int readFile(byte[] buffer, int length, int position, long fileOffset) throws IOException 456 { 457 459 openContent(false, false); 460 461 ByteBuffer byteBuffer = ByteBuffer.wrap(buffer, position, length); 463 int count = channel.read(byteBuffer, fileOffset); 464 if (count < 0) 465 { 466 count = 0; } 468 if (logger.isDebugEnabled()) 470 { 471 logger.debug("Read from channel: " + 472 " net file: " + this + "\n" + 473 " read: " + count); 474 } 475 return count; 476 } 477 478 @Override 479 public synchronized void openFile(boolean createFlag) throws IOException 480 { 481 throw new UnsupportedOperationException (); 482 } 483 484 @Override 485 public synchronized long seekFile(long pos, int typ) throws IOException 486 { 487 throw new UnsupportedOperationException (); 488 } 489 490 @Override 491 public synchronized void flushFile() throws IOException 492 { 493 openContent(true, false); 495 channel.force(false); 497 if (logger.isDebugEnabled()) 499 { 500 logger.debug("Flushed channel: " + 501 " net file: " + this); 502 } 503 } 504 } 505 | Popular Tags |