1 17 package org.alfresco.filesys.smb.server.repo; 18 19 import java.io.File ; 20 import java.io.FileNotFoundException ; 21 import java.io.IOException ; 22 import java.net.URL ; 23 import java.util.List ; 24 25 import javax.transaction.UserTransaction ; 26 27 import org.alfresco.config.ConfigElement; 28 import org.alfresco.error.AlfrescoRuntimeException; 29 import org.alfresco.filesys.server.SrvSession; 30 import org.alfresco.filesys.server.core.DeviceContext; 31 import org.alfresco.filesys.server.core.DeviceContextException; 32 import org.alfresco.filesys.server.filesys.AccessDeniedException; 33 import org.alfresco.filesys.server.filesys.AccessMode; 34 import org.alfresco.filesys.server.filesys.DiskInterface; 35 import org.alfresco.filesys.server.filesys.FileInfo; 36 import org.alfresco.filesys.server.filesys.FileName; 37 import org.alfresco.filesys.server.filesys.FileOpenParams; 38 import org.alfresco.filesys.server.filesys.FileSharingException; 39 import org.alfresco.filesys.server.filesys.FileStatus; 40 import org.alfresco.filesys.server.filesys.FileSystem; 41 import org.alfresco.filesys.server.filesys.IOControlNotImplementedException; 42 import org.alfresco.filesys.server.filesys.IOCtlInterface; 43 import org.alfresco.filesys.server.filesys.NetworkFile; 44 import org.alfresco.filesys.server.filesys.SearchContext; 45 import org.alfresco.filesys.server.filesys.SrvDiskInfo; 46 import org.alfresco.filesys.server.filesys.TreeConnection; 47 import org.alfresco.filesys.smb.SMBException; 48 import org.alfresco.filesys.smb.SMBStatus; 49 import org.alfresco.filesys.smb.SharingMode; 50 import org.alfresco.filesys.smb.server.SMBSrvSession; 51 import org.alfresco.filesys.smb.server.repo.FileState.FileStateStatus; 52 import org.alfresco.filesys.smb.server.repo.pseudo.ContentPseudoFileImpl; 53 import org.alfresco.filesys.smb.server.repo.pseudo.LocalPseudoFile; 54 import org.alfresco.filesys.smb.server.repo.pseudo.MemoryNetworkFile; 55 import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFile; 56 import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFileInterface; 57 import org.alfresco.filesys.smb.server.repo.pseudo.PseudoFileList; 58 import org.alfresco.filesys.smb.server.repo.pseudo.PseudoNetworkFile; 59 import org.alfresco.filesys.util.DataBuffer; 60 import org.alfresco.filesys.util.WildCard; 61 import org.alfresco.model.ContentModel; 62 import org.alfresco.repo.security.authentication.AuthenticationComponent; 63 import org.alfresco.service.cmr.coci.CheckOutCheckInService; 64 import org.alfresco.service.cmr.lock.NodeLockedException; 65 import org.alfresco.service.cmr.repository.ContentService; 66 import org.alfresco.service.cmr.repository.NodeRef; 67 import org.alfresco.service.cmr.repository.NodeService; 68 import org.alfresco.service.cmr.repository.StoreRef; 69 import org.alfresco.service.cmr.search.SearchService; 70 import org.alfresco.service.cmr.security.AccessStatus; 71 import org.alfresco.service.cmr.security.PermissionService; 72 import org.alfresco.service.namespace.NamespaceService; 73 import org.alfresco.service.transaction.TransactionService; 74 import org.apache.commons.logging.Log; 75 import org.apache.commons.logging.LogFactory; 76 77 84 public class ContentDiskDriver implements DiskInterface, IOCtlInterface 85 { 86 88 private static final Log logger = LogFactory.getLog(ContentDiskDriver.class); 89 90 92 private static final String KEY_STORE = "store"; 93 private static final String KEY_ROOT_PATH = "rootPath"; 94 private static final String KEY_RELATIVE_PATH = "relativePath"; 95 96 98 private CifsHelper cifsHelper; 99 private TransactionService transactionService; 100 private NamespaceService namespaceService; 101 private NodeService nodeService; 102 private SearchService searchService; 103 private ContentService contentService; 104 private PermissionService permissionService; 105 private CheckOutCheckInService checkInOutService; 106 107 private AuthenticationComponent authComponent; 108 109 111 private IOControlHandler m_ioHandler; 112 113 115 private PseudoFileInterface m_pseudoFiles; 116 117 122 public ContentDiskDriver(CifsHelper cifsHelper) 123 { 124 this.cifsHelper = cifsHelper; 125 } 126 127 130 public void setContentService(ContentService contentService) 131 { 132 this.contentService = contentService; 133 } 134 135 138 public void setNamespaceService(NamespaceService namespaceService) 139 { 140 this.namespaceService = namespaceService; 141 } 142 143 146 public void setNodeService(NodeService nodeService) 147 { 148 this.nodeService = nodeService; 149 } 150 151 154 public void setSearchService(SearchService searchService) 155 { 156 this.searchService = searchService; 157 } 158 159 160 163 public void setTransactionService(TransactionService transactionService) 164 { 165 this.transactionService = transactionService; 166 } 167 168 173 public void setPermissionService(PermissionService permissionService) 174 { 175 this.permissionService = permissionService; 176 } 177 178 183 public void setCheckInOutService(CheckOutCheckInService checkInOutService) 184 { 185 this.checkInOutService = checkInOutService; 186 } 187 188 193 public void setAuthenticationComponent(AuthenticationComponent authComponent) 194 { 195 this.authComponent = authComponent; 196 } 197 198 207 public DeviceContext createContext(ConfigElement cfg) throws DeviceContextException 208 { 209 211 authComponent.setCurrentUser( authComponent.getSystemUserName()); 212 213 215 UserTransaction tx = transactionService.getUserTransaction(true); 216 217 ContentContext context = null; 218 219 try 220 { 221 223 if ( tx != null) 224 tx.begin(); 225 226 228 ConfigElement storeElement = cfg.getChild(KEY_STORE); 229 if (storeElement == null || storeElement.getValue() == null || storeElement.getValue().length() == 0) 230 { 231 throw new DeviceContextException("Device missing init value: " + KEY_STORE); 232 } 233 String storeValue = storeElement.getValue(); 234 StoreRef storeRef = new StoreRef(storeValue); 235 236 238 if (! nodeService.exists(storeRef)) 239 { 240 throw new DeviceContextException("Store not created prior to application startup: " + storeRef); 241 } 242 NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef); 243 244 246 ConfigElement rootPathElement = cfg.getChild(KEY_ROOT_PATH); 247 if (rootPathElement == null || rootPathElement.getValue() == null || rootPathElement.getValue().length() == 0) 248 { 249 throw new DeviceContextException("Device missing init value: " + KEY_ROOT_PATH); 250 } 251 String rootPath = rootPathElement.getValue(); 252 253 255 List <NodeRef> nodeRefs = searchService.selectNodes(storeRootNodeRef, rootPath, null, namespaceService, false); 256 257 NodeRef rootNodeRef = null; 258 259 if (nodeRefs.size() > 1) 260 { 261 throw new DeviceContextException("Multiple possible roots for device: \n" + 262 " root path: " + rootPath + "\n" + 263 " results: " + nodeRefs); 264 } 265 else if (nodeRefs.size() == 0) 266 { 267 throw new DeviceContextException("No root found for device: \n" + 269 " root path: " + rootPath); 270 } 271 else 272 { 273 rootNodeRef = nodeRefs.get(0); 275 } 276 277 279 ConfigElement relativePathElement = cfg.getChild(KEY_RELATIVE_PATH); 280 281 if ( relativePathElement != null) 282 { 283 285 String relPath = relativePathElement.getValue().replace( '/', FileName.DOS_SEPERATOR); 286 287 289 NodeRef relPathNode = cifsHelper.getNodeRef( rootNodeRef, relPath); 290 if ( cifsHelper.isDirectory( relPathNode) == false) 291 throw new DeviceContextException("Relative path is not a folder, " + relativePathElement.getValue()); 292 293 295 rootNodeRef = relPathNode; 296 } 297 298 300 tx.commit(); 301 tx = null; 302 303 305 context = new ContentContext(storeValue, rootPath, rootNodeRef); 306 307 309 context.setDiskInformation(new SrvDiskInfo(2560, 64, 512, 2304)); 310 311 313 context.setFilesystemAttributes(FileSystem.CasePreservedNames); 314 } 315 catch (Exception ex) 316 { 317 logger.error("Error during create context", ex); 318 } 319 finally 320 { 321 323 if ( tx != null) 324 { 325 try 326 { 327 tx.rollback(); 328 } 329 catch (Exception ex) 330 { 331 logger.warn("Failed to rollback transaction", ex); 332 } 333 } 334 } 335 336 338 try 339 { 340 342 Object ioctlObj = Class.forName("org.alfresco.filesys.server.smb.repo.ContentIOControlHandler").newInstance(); 343 344 346 if ( ioctlObj instanceof IOControlHandler) 347 { 348 350 m_ioHandler = (IOControlHandler) ioctlObj; 351 m_ioHandler.initialize( this, cifsHelper, transactionService, nodeService, checkInOutService); 352 } 353 354 356 if ( m_ioHandler != null) 357 { 358 ConfigElement dragDropElem = cfg.getChild( "dragAndDrop"); 359 if ( dragDropElem != null) 360 { 361 363 ConfigElement pseudoName = dragDropElem.getChild( "filename"); 364 ConfigElement appPath = dragDropElem.getChild( "path"); 365 366 if ( pseudoName != null && appPath != null) 367 { 368 370 URL appURL = this.getClass().getClassLoader().getResource(appPath.getValue()); 371 if ( appURL == null) 372 throw new DeviceContextException("Failed to find drag and drop application, " + appPath.getValue()); 373 File appFile = new File (appURL.getFile()); 374 if ( appFile.exists() == false) 375 throw new DeviceContextException("Drag and drop application not found, " + appPath.getValue()); 376 377 379 PseudoFile dragDropPseudo = new LocalPseudoFile( pseudoName.getValue(), appFile.getAbsolutePath()); 380 context.setDragAndDropApp( dragDropPseudo); 381 } 382 } 383 } 384 } 385 catch (Exception ex) 386 { 387 if ( logger.isDebugEnabled()) 388 logger.debug("No I/O control handler available"); 389 } 390 391 393 ConfigElement urlFileElem = cfg.getChild( "urlFile"); 394 if ( urlFileElem != null) 395 { 396 398 ConfigElement pseudoName = urlFileElem.getChild( "filename"); 399 ConfigElement webPath = urlFileElem.getChild( "webpath"); 400 401 if ( pseudoName != null && webPath != null) 402 { 403 405 String path = webPath.getValue(); 406 if ( path.endsWith("/") == false) 407 path = path + "/"; 408 409 411 if ( pseudoName.getValue().endsWith(".url") == false) 412 throw new DeviceContextException("URL link file must end with .url, " + pseudoName.getValue()); 413 414 416 context.setURLFileName( pseudoName.getValue()); 417 context.setURLPrefix( path); 418 } 419 } 420 421 423 if ( context.hasDragAndDropApp() || context.hasURLFile()) 424 { 425 427 m_pseudoFiles = new ContentPseudoFileImpl(); 428 } 429 430 432 ConfigElement offlineFiles = cfg.getChild( "offlineFiles"); 433 if ( offlineFiles != null) 434 { 435 437 cifsHelper.setMarkLockedFilesAsOffline( true); 438 439 441 logger.info("Locked files will be marked as offline"); 442 } 443 444 446 return context; 447 } 448 449 454 public final boolean hasPseudoFileInterface() 455 { 456 return m_pseudoFiles != null ? true : false; 457 } 458 459 464 public final PseudoFileInterface getPseudoFileInterface() 465 { 466 return m_pseudoFiles; 467 } 468 469 477 public boolean isReadOnly(SrvSession sess, DeviceContext ctx) throws IOException 478 { 479 return false; 480 } 481 482 491 public FileInfo getFileInformation(SrvSession session, TreeConnection tree, String path) throws IOException 492 { 493 495 ContentContext ctx = (ContentContext) tree.getContext(); 496 NodeRef infoParentNodeRef = ctx.getRootNode(); 497 498 if ( path == null) 499 path = ""; 500 501 String infoPath = path; 502 503 try 504 { 505 507 FileInfo finfo = null; 508 509 if ( hasPseudoFileInterface()) 510 { 511 513 PseudoFile pfile = getPseudoFileInterface().getPseudoFile( session, tree, path); 514 if ( pfile != null) 515 { 516 518 if ( logger.isDebugEnabled()) 519 logger.debug("getInfo using pseudo file info for " + path); 520 return pfile.getFileInfo(); 521 } 522 } 523 524 526 NodeRef nodeRef = getNodeForPath(tree, infoPath); 527 if ( nodeRef != null) 528 { 529 531 finfo = cifsHelper.getFileInformation(nodeRef); 532 533 535 if ( logger.isDebugEnabled()) 536 logger.debug("getInfo using cached noderef for path " + path); 537 } 538 539 541 session.beginTransaction(transactionService, true); 542 543 if ( finfo == null) 544 { 545 String [] paths = FileName.splitPath( path); 546 547 if ( paths[0] != null && paths[0].length() > 1) 548 { 549 551 nodeRef = getNodeForPath(tree, paths[0]); 552 553 if ( nodeRef != null) 554 { 555 infoParentNodeRef = nodeRef; 556 infoPath = paths[1]; 557 558 560 if ( logger.isDebugEnabled()) 561 logger.debug("getInfo using cached noderef for parent " + path); 562 } 563 } 564 565 567 finfo = cifsHelper.getFileInformation(infoParentNodeRef, infoPath); 568 569 571 if (logger.isDebugEnabled()) 572 { 573 logger.debug("Getting file information: \n" + 574 " path: " + path + "\n" + 575 " file info: " + finfo); 576 } 577 } 578 579 581 return finfo; 582 } 583 catch (FileNotFoundException e) 584 { 585 if (logger.isDebugEnabled()) 587 { 588 logger.debug("Getting file information - File not found: \n" + 589 " path: " + path); 590 } 591 throw e; 592 } 593 catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) 594 { 595 597 if ( logger.isDebugEnabled()) 598 logger.debug("Get file info - access denied, " + path); 599 600 602 throw new AccessDeniedException("Get file information " + path); 603 } 604 catch (AlfrescoRuntimeException ex) 605 { 606 608 if ( logger.isDebugEnabled()) 609 logger.debug("Get file info error", ex); 610 611 613 throw new IOException ("Get file information " + path); 614 } 615 } 616 617 628 public SearchContext startSearch(SrvSession sess, TreeConnection tree, String searchPath, int attributes) throws FileNotFoundException 629 { 630 try 631 { 632 634 ContentContext ctx = (ContentContext) tree.getContext(); 635 636 String searchFileSpec = searchPath; 637 NodeRef searchRootNodeRef = ctx.getRootNode(); 638 FileState searchFolderState = null; 639 640 642 sess.beginTransaction(transactionService, true); 643 644 647 String [] paths = null; 648 649 if ( ctx.hasStateTable()) 650 { 651 653 paths = FileName.splitPath(searchPath); 654 if ( paths[0] != null && paths[0].length() > 1) 655 { 656 658 NodeRef nodeRef = getNodeForPath(tree, paths[0]); 659 660 662 searchFolderState = getStateForPath(tree, paths[0]); 663 if ( searchFolderState == null) 664 { 665 667 searchFolderState = ctx.getStateTable().findFileState( paths[0], true, true); 668 } 669 670 672 if ( searchFolderState.hasNodeRef() == false) 673 { 674 676 searchFolderState.setNodeRef( nodeRef); 677 } 678 679 681 if ( hasPseudoFileInterface()) 682 getPseudoFileInterface().addPseudoFilesToFolder( sess, tree, paths[0]); 683 684 686 if ( nodeRef != null) 687 { 688 searchRootNodeRef = nodeRef; 689 searchFileSpec = paths[1]; 690 691 693 if ( logger.isDebugEnabled()) 694 logger.debug("Search using cached noderef for path " + searchPath); 695 } 696 } 697 } 698 699 701 List <NodeRef> results = cifsHelper.getNodeRefs(searchRootNodeRef, searchFileSpec); 702 703 705 PseudoFileList pseudoList = null; 706 707 if ( sess instanceof SMBSrvSession && searchFolderState != null && searchFolderState.hasPseudoFiles()) 708 { 709 711 if ( WildCard.containsWildcards(searchFileSpec)) 712 { 713 715 pseudoList = searchFolderState.getPseudoFileList(); 716 } 717 else if ( results == null || results.size() == 0) 718 { 719 721 String fname = paths[1]; 722 723 if ( fname != null) 724 { 725 727 PseudoFile pfile = searchFolderState.getPseudoFileList().findFile( fname, true); 728 if ( pfile != null) 729 { 730 732 pseudoList = new PseudoFileList(); 733 pseudoList.addFile( pfile); 734 } 735 } 736 } 737 } 738 739 741 SearchContext searchCtx = new ContentSearchContext(cifsHelper, results, searchFileSpec, pseudoList); 742 743 745 if (logger.isDebugEnabled()) 746 { 747 logger.debug("Started search: \n" + 748 " search path: " + searchPath + "\n" + 749 " attributes: " + attributes); 750 } 751 return searchCtx; 752 } 753 catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) 754 { 755 757 if ( logger.isDebugEnabled()) 758 logger.debug("Start search - access denied, " + searchPath); 759 760 762 throw new FileNotFoundException ("Start search " + searchPath); 763 } 764 catch (AlfrescoRuntimeException ex) 765 { 766 768 if ( logger.isDebugEnabled()) 769 logger.debug("Start search", ex); 770 771 773 throw new FileNotFoundException ("Start search " + searchPath); 774 } 775 } 776 777 786 public int fileExists(SrvSession sess, TreeConnection tree, String name) 787 { 788 789 int status = FileStatus.Unknown; 790 791 try 792 { 793 795 ContentContext ctx = (ContentContext) tree.getContext(); 796 FileState fstate = null; 797 798 if ( ctx.hasStateTable()) 799 ctx.getStateTable().findFileState(name); 800 801 if ( fstate != null) 802 { 803 FileStateStatus fsts = fstate.getFileStatus(); 804 805 if ( fsts == FileStateStatus.FileExists) 806 status = FileStatus.FileExists; 807 else if ( fsts == FileStateStatus.FolderExists) 808 status = FileStatus.DirectoryExists; 809 else if ( fsts == FileStateStatus.NotExist || fsts == FileStateStatus.Renamed) 810 status = FileStatus.NotExist; 811 812 814 if ( logger.isDebugEnabled()) 815 logger.debug("Cache hit - fileExists() " + name + ", sts=" + status); 816 } 817 else 818 { 819 821 sess.beginTransaction(transactionService, true); 822 823 825 FileInfo info = getFileInformation(sess, tree, name); 826 if (info.isDirectory()) 827 { 828 status = FileStatus.DirectoryExists; 829 } 830 else 831 { 832 status = FileStatus.FileExists; 833 } 834 } 835 } 836 catch (FileNotFoundException e) 837 { 838 status = FileStatus.NotExist; 839 } 840 catch (IOException e) 841 { 842 844 logger.debug("File exists error, " + name, e); 845 846 status = FileStatus.NotExist; 847 } 848 849 if (logger.isDebugEnabled()) 851 { 852 logger.debug("File status determined: \n" + 853 " name: " + name + "\n" + 854 " status: " + status); 855 } 856 return status; 857 } 858 859 868 public NetworkFile openFile(SrvSession sess, TreeConnection tree, FileOpenParams params) throws IOException 869 { 870 872 sess.beginTransaction(transactionService, false); 873 874 try 875 { 876 878 ContentContext ctx = (ContentContext) tree.getContext(); 879 880 882 if ( hasPseudoFileInterface()) 883 { 884 886 PseudoFile pfile = getPseudoFileInterface().getPseudoFile( sess, tree, params.getPath()); 887 if ( pfile != null) 888 { 889 891 return pfile.getFile( params.getPath()); 892 } 893 } 894 895 897 NodeRef nodeRef = getNodeForPath(tree, params.getPath()); 898 899 903 if ( params.hasAccessMode(AccessMode.NTRead) && 904 permissionService.hasPermission(nodeRef, PermissionService.READ) == AccessStatus.DENIED) 905 throw new AccessDeniedException("No read access to " + params.getFullPath()); 906 907 909 if ( params.hasAccessMode(AccessMode.NTWrite) && 910 permissionService.hasPermission(nodeRef, PermissionService.WRITE) == AccessStatus.DENIED) 911 throw new AccessDeniedException("No write access to " + params.getFullPath()); 912 913 915 if ( params.hasAccessMode(AccessMode.NTDelete) && 916 permissionService.hasPermission(nodeRef, PermissionService.DELETE) == AccessStatus.DENIED) 917 throw new AccessDeniedException("No delete access to " + params.getFullPath()); 918 919 921 FileState fstate = null; 922 923 if ( ctx.hasStateTable()) 924 { 925 927 fstate = ctx.getStateTable().findFileState( params.getPath()); 928 929 if ( fstate != null) 930 { 931 933 if ( fstate.exists() == false) 934 throw new FileNotFoundException (); 935 936 938 if ( fstate != null && params.getSharedAccess() == SharingMode.NOSHARING && 939 fstate.getOpenCount() > 0) 940 throw new FileSharingException("File already open, " + params.getPath()); 941 } 942 } 943 944 946 NetworkFile netFile = ContentNetworkFile.createFile(transactionService, nodeService, contentService, cifsHelper, nodeRef, params); 947 948 950 if ( ctx.hasStateTable()) 951 { 952 if ( fstate == null) 953 fstate = ctx.getStateTable().findFileState(params.getPath(), params.isDirectory(), true); 954 955 957 fstate.incrementOpenCount(); 958 fstate.setNodeRef(nodeRef); 959 } 960 961 964 if ( params.isOverwrite() && netFile != null) 965 { 966 968 netFile.truncateFile( 0L); 969 } 970 971 973 if (logger.isDebugEnabled()) 974 { 975 logger.debug("Opened network file: \n" + 976 " path: " + params.getPath() + "\n" + 977 " file open parameters: " + params + "\n" + 978 " network file: " + netFile); 979 } 980 981 983 return netFile; 984 } 985 catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) 986 { 987 989 if ( logger.isDebugEnabled()) 990 logger.debug("Open file - access denied, " + params.getFullPath()); 991 992 994 throw new AccessDeniedException("Open file " + params.getFullPath()); 995 } 996 catch (AlfrescoRuntimeException ex) 997 { 998 1000 if ( logger.isDebugEnabled()) 1001 logger.debug("Open file error", ex); 1002 1003 1005 throw new IOException ("Open file " + params.getFullPath()); 1006 } 1007 } 1008 1009 1018 public NetworkFile createFile(SrvSession sess, TreeConnection tree, FileOpenParams params) throws IOException 1019 { 1020 1022 sess.beginTransaction(transactionService, false); 1023 1024 try 1025 { 1026 1028 ContentContext ctx = (ContentContext) tree.getContext(); 1029 NodeRef deviceRootNodeRef = ctx.getRootNode(); 1030 1031 String path = params.getPath(); 1032 1033 1036 if ( ctx.hasStateTable()) 1037 { 1038 1040 String [] paths = FileName.splitPath(path); 1041 if ( paths[0] != null && paths[0].length() > 1) 1042 { 1043 1045 NodeRef nodeRef = getNodeForPath(tree, paths[0]); 1046 1047 if ( nodeRef != null) 1048 { 1049 deviceRootNodeRef = nodeRef; 1050 path = paths[1]; 1051 1052 1054 if ( logger.isDebugEnabled()) 1055 logger.debug("Create file using cached noderef for path " + paths[0]); 1056 } 1057 } 1058 } 1059 1060 1062 NodeRef nodeRef = cifsHelper.createNode(deviceRootNodeRef, path, true); 1063 1064 NetworkFile netFile = ContentNetworkFile.createFile(transactionService, nodeService, contentService, cifsHelper, nodeRef, params); 1066 1067 1069 if ( ctx.hasStateTable()) 1070 { 1071 FileState fstate = ctx.getStateTable().findFileState(path, false, true); 1072 if ( fstate != null) 1073 { 1074 1076 fstate.setFileStatus(FileStateStatus.FileExists); 1077 fstate.incrementOpenCount(); 1078 fstate.setNodeRef(nodeRef); 1079 1080 1082 if ( logger.isDebugEnabled()) 1083 logger.debug("Creaste file, state=" + fstate); 1084 } 1085 } 1086 1087 if (logger.isDebugEnabled()) 1089 { 1090 logger.debug("Created file: \n" + 1091 " path: " + path + "\n" + 1092 " file open parameters: " + params + "\n" + 1093 " node: " + nodeRef + "\n" + 1094 " network file: " + netFile); 1095 } 1096 return netFile; 1097 } 1098 catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) 1099 { 1100 1102 if ( logger.isDebugEnabled()) 1103 logger.debug("Create file - access denied, " + params.getFullPath()); 1104 1105 1107 throw new AccessDeniedException("Create file " + params.getFullPath()); 1108 } 1109 catch (AlfrescoRuntimeException ex) 1110 { 1111 1113 if ( logger.isDebugEnabled()) 1114 logger.debug("Create file error", ex); 1115 1116 1118 throw new IOException ("Create file " + params.getFullPath()); 1119 } 1120 1121 } 1122 1123 1131 public void createDirectory(SrvSession sess, TreeConnection tree, FileOpenParams params) throws IOException 1132 { 1133 1135 sess.beginTransaction(transactionService, false); 1136 1137 try 1138 { 1139 1141 ContentContext ctx = (ContentContext) tree.getContext(); 1142 NodeRef deviceRootNodeRef = ctx.getRootNode(); 1143 1144 String path = params.getPath(); 1145 1146 1149 if ( ctx.hasStateTable()) 1150 { 1151 1153 String [] paths = FileName.splitPath(path); 1154 if ( paths[0] != null && paths[0].length() > 1) 1155 { 1156 1158 NodeRef nodeRef = getNodeForPath(tree, paths[0]); 1159 1160 if ( nodeRef != null) 1161 { 1162 deviceRootNodeRef = nodeRef; 1163 path = paths[1]; 1164 1165 1167 if ( logger.isDebugEnabled()) 1168 logger.debug("Create file using cached noderef for path " + paths[0]); 1169 } 1170 } 1171 } 1172 1173 1175 NodeRef nodeRef = cifsHelper.createNode(deviceRootNodeRef, path, false); 1176 1177 1179 if ( ctx.hasStateTable()) 1180 { 1181 FileState fstate = ctx.getStateTable().findFileState(path, true, true); 1182 if ( fstate != null) 1183 { 1184 1186 fstate.setFileStatus(FileStateStatus.FolderExists); 1187 fstate.incrementOpenCount(); 1188 fstate.setNodeRef(nodeRef); 1189 1190 1192 if ( logger.isDebugEnabled()) 1193 logger.debug("Creaste folder, state=" + fstate); 1194 } 1195 } 1196 1197 if (logger.isDebugEnabled()) 1199 { 1200 logger.debug("Created directory: \n" + 1201 " path: " + path + "\n" + 1202 " file open params: " + params + "\n" + 1203 " node: " + nodeRef); 1204 } 1205 } 1206 catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) 1207 { 1208 1210 if ( logger.isDebugEnabled()) 1211 logger.debug("Create directory - access denied, " + params.getFullPath()); 1212 1213 1215 throw new AccessDeniedException("Create directory " + params.getFullPath()); 1216 } 1217 catch (AlfrescoRuntimeException ex) 1218 { 1219 1221 if ( logger.isDebugEnabled()) 1222 logger.debug("Create directory error", ex); 1223 1224 1226 throw new IOException ("Create directory " + params.getFullPath()); 1227 } 1228 } 1229 1230 1238 public void deleteDirectory(SrvSession sess, TreeConnection tree, String dir) throws IOException 1239 { 1240 1242 sess.beginTransaction(transactionService, false); 1243 1244 1246 ContentContext ctx = (ContentContext) tree.getContext(); 1247 NodeRef deviceRootNodeRef = ctx.getRootNode(); 1248 1249 try 1250 { 1251 NodeRef nodeRef = cifsHelper.getNodeRef(deviceRootNodeRef, dir); 1253 if (nodeService.exists(nodeRef)) 1254 { 1255 nodeService.deleteNode(nodeRef); 1256 1257 1259 if ( ctx.hasStateTable()) 1260 ctx.getStateTable().removeFileState(dir); 1261 } 1262 if (logger.isDebugEnabled()) 1264 { 1265 logger.debug("Deleted directory: \n" + 1266 " directory: " + dir + "\n" + 1267 " node: " + nodeRef); 1268 } 1269 } 1270 catch (FileNotFoundException e) 1271 { 1272 if (logger.isDebugEnabled()) 1274 { 1275 logger.debug("Deleted directory <alfready gone>: \n" + 1276 " directory: " + dir); 1277 } 1278 } 1279 catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) 1280 { 1281 1283 if ( logger.isDebugEnabled()) 1284 logger.debug("Delete directory - access denied, " + dir); 1285 1286 1288 throw new AccessDeniedException("Delete directory " + dir); 1289 } 1290 catch (AlfrescoRuntimeException ex) 1291 { 1292 1294 if ( logger.isDebugEnabled()) 1295 logger.debug("Delete directory", ex); 1296 1297 1299 throw new IOException ("Delete directory " + dir); 1300 } 1301 } 1302 1303 1311 public void flushFile(SrvSession sess, TreeConnection tree, NetworkFile file) throws IOException 1312 { 1313 1315 file.flushFile(); 1316 } 1317 1318 1326 public void closeFile(SrvSession sess, TreeConnection tree, NetworkFile file) throws IOException 1327 { 1328 1330 sess.beginTransaction(transactionService, false); 1331 1332 1334 ContentContext ctx = (ContentContext) tree.getContext(); 1335 1336 if ( ctx.hasStateTable()) 1337 { 1338 FileState fstate = ctx.getStateTable().findFileState(file.getFullName()); 1339 if ( fstate != null) 1340 fstate.decrementOpenCount(); 1341 } 1342 1343 1345 file.closeFile(); 1346 1347 1349 if (file.hasDeleteOnClose()) 1350 { 1351 1353 if ( file instanceof ContentNetworkFile) 1354 { 1355 ContentNetworkFile contentNetFile = (ContentNetworkFile) file; 1356 NodeRef nodeRef = contentNetFile.getNodeRef(); 1357 1358 1360 if (nodeService.exists(nodeRef)) 1361 { 1362 try 1363 { 1364 1366 nodeService.deleteNode(nodeRef); 1367 1368 1370 if ( ctx.hasStateTable()) 1371 ctx.getStateTable().removeFileState(file.getFullName()); 1372 } 1373 catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) 1374 { 1375 1377 if ( logger.isDebugEnabled()) 1378 logger.debug("Delete on close - access denied, " + file.getFullName()); 1379 1380 1382 throw new AccessDeniedException("Delete on close " + file.getFullName()); 1383 } 1384 } 1385 } 1386 else if ( file instanceof PseudoNetworkFile || 1387 file instanceof MemoryNetworkFile) 1388 { 1389 1391 if ( hasPseudoFileInterface()) 1392 { 1393 1395 getPseudoFileInterface().deletePseudoFile( sess, tree, file.getFullName()); 1396 } 1397 } 1398 } 1399 1400 1402 if (logger.isDebugEnabled()) 1403 { 1404 logger.debug("Closed file: \n" + 1405 " network file: " + file + "\n" + 1406 " deleted on close: " + file.hasDeleteOnClose()); 1407 } 1408 } 1409 1410 1418 public void deleteFile(SrvSession sess, TreeConnection tree, String name) throws IOException 1419 { 1420 1422 sess.beginTransaction(transactionService, false); 1423 1424 1426 ContentContext ctx = (ContentContext) tree.getContext(); 1427 1428 try 1429 { 1430 NodeRef nodeRef = getNodeForPath(tree, name); 1432 if (nodeService.exists(nodeRef)) 1433 { 1434 nodeService.deleteNode(nodeRef); 1435 1436 1438 if ( ctx.hasStateTable()) 1439 ctx.getStateTable().removeFileState(name); 1440 } 1441 1442 if (logger.isDebugEnabled()) 1444 { 1445 logger.debug("Deleted file: \n" + 1446 " file: " + name + "\n" + 1447 " node: " + nodeRef); 1448 } 1449 } 1450 catch (FileNotFoundException e) 1451 { 1452 if (logger.isDebugEnabled()) 1454 { 1455 logger.debug("Deleted file <alfready gone>: \n" + 1456 " file: " + name); 1457 } 1458 } 1459 catch (NodeLockedException ex) 1460 { 1461 1463 if ( logger.isDebugEnabled()) 1464 logger.debug("Delete file - access denied (locked)"); 1465 1466 1468 throw new AccessDeniedException("Delete " + name); 1469 } 1470 catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) 1471 { 1472 1474 if ( logger.isDebugEnabled()) 1475 logger.debug("Delete file - access denied"); 1476 1477 1479 throw new AccessDeniedException("Delete " + name); 1480 } 1481 catch (AlfrescoRuntimeException ex) 1482 { 1483 1485 if ( logger.isDebugEnabled()) 1486 logger.debug("Delete file error", ex); 1487 1488 1490 throw new IOException ("Delete file " + name); 1491 } 1492 } 1493 1494 1503 public void renameFile(SrvSession sess, TreeConnection tree, String oldName, String newName) throws IOException 1504 { 1505 sess.beginTransaction(transactionService, false); 1507 1508 try 1509 { 1510 1512 ContentContext ctx = (ContentContext) tree.getContext(); 1513 1514 NodeRef nodeToMoveRef = getNodeForPath(tree, oldName); 1516 1517 String [] splitPaths = FileName.splitPath(newName); 1519 NodeRef targetFolderRef = getNodeForPath(tree, splitPaths[0]); 1520 String name = splitPaths[1]; 1522 boolean relinked = false; 1524 if ( ctx.hasStateTable()) 1525 { 1526 1528 if ( !cifsHelper.isDirectory(nodeToMoveRef) ) 1529 { 1530 1532 FileState renState = ctx.getStateTable().removeFileState(newName); 1533 1534 if ( renState != null && renState.getFileStatus() == FileStateStatus.Renamed) 1535 { 1536 1538 if ( logger.isDebugEnabled()) 1539 logger.debug(" Found rename state, relinking, " + renState); 1540 1541 1544 cifsHelper.relinkNode( renState.getNodeRef(), nodeToMoveRef, targetFolderRef, name); 1545 relinked = true; 1546 1547 1549 if ( renState.hasRenameState()) 1550 renState.getRenameState().setNodeRef(nodeToMoveRef); 1551 1552 1554 ctx.getStateTable().removeFileState(oldName); 1555 1556 1558 FileState fstate = ctx.getStateTable().findFileState(newName, false, true); 1559 1560 fstate.setNodeRef(renState.getNodeRef()); 1561 fstate.setFileStatus(FileStateStatus.FileExists); 1562 } 1563 else 1564 { 1565 1567 FileState fstate = ctx.getStateTable().findFileState(oldName, false, true); 1568 1569 1572 fstate.setExpiryTime(System.currentTimeMillis() + FileState.RenameTimeout); 1573 1574 1576 fstate.setFileStatus(FileStateStatus.Renamed); 1577 fstate.setNodeRef(nodeToMoveRef); 1578 1579 1581 FileState newState = ctx.getStateTable().findFileState(newName, false, true); 1582 1583 newState.setNodeRef(nodeToMoveRef); 1584 newState.setFileStatus(FileStateStatus.FileExists); 1585 1586 1588 fstate.setRenameState(newState); 1589 1590 1592 if ( logger.isDebugEnabled()) 1593 logger.debug("Cached rename state for " + oldName + ", state=" + fstate); 1594 } 1595 } 1596 else 1597 { 1598 1600 FileState fstate = ctx.getStateTable().findFileState(oldName); 1601 1602 if ( fstate != null) 1603 { 1604 1606 ctx.getStateTable().renameFileState(newName, fstate); 1607 } 1608 } 1609 } 1610 1611 if (!relinked) 1612 { 1613 cifsHelper.move(nodeToMoveRef, targetFolderRef, name); 1614 } 1615 1616 1618 if (logger.isDebugEnabled()) 1619 logger.debug("Moved node: " + " from: " + oldName + " to: " + newName); 1620 } 1621 catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) 1622 { 1623 1625 if ( logger.isDebugEnabled()) 1626 logger.debug("Rename file - access denied, " + oldName); 1627 1628 1630 throw new AccessDeniedException("Rename file " + oldName); 1631 } 1632 catch (NodeLockedException ex) 1633 { 1634 1636 if ( logger.isDebugEnabled()) 1637 logger.debug("Rename file", ex); 1638 1639 1641 throw new AccessDeniedException("Node locked " + oldName); 1642 } 1643 catch (AlfrescoRuntimeException ex) 1644 { 1645 1647 if ( logger.isDebugEnabled()) 1648 logger.debug("Rename file", ex); 1649 1650 1652 throw new IOException ("Rename file " + oldName); 1653 } 1654 } 1655 1656 1665 public void setFileInformation(SrvSession sess, TreeConnection tree, String name, FileInfo info) throws IOException 1666 { 1667 try 1668 { 1669 1671 if ( hasPseudoFileInterface() && 1672 getPseudoFileInterface().isPseudoFile( sess, tree, name)) 1673 { 1674 1676 return; 1677 } 1678 1679 1681 NodeRef nodeRef = getNodeForPath(tree, name); 1682 1683 1685 if ( permissionService.hasPermission(nodeRef, PermissionService.WRITE) == AccessStatus.DENIED) 1686 throw new AccessDeniedException("No write access to " + name); 1687 1688 1690 if ( info.hasSetFlag(FileInfo.SetDeleteOnClose) && info.hasDeleteOnClose()) 1691 { 1692 1694 if ( nodeService.hasAspect( nodeRef, ContentModel.ASPECT_LOCKABLE)) 1695 { 1696 1698 String lockTypeStr = (String ) nodeService.getProperty( nodeRef, ContentModel.PROP_LOCK_TYPE); 1699 1700 if ( lockTypeStr != null) 1701 throw new AccessDeniedException("Node locked, cannot mark for delete"); 1702 } 1703 } 1704 } 1705 catch (org.alfresco.repo.security.permissions.AccessDeniedException ex) 1706 { 1707 1709 if ( logger.isDebugEnabled()) 1710 logger.debug("Set file information - access denied, " + name); 1711 1712 1714 throw new AccessDeniedException("Set file information " + name); 1715 } 1716 catch (AlfrescoRuntimeException ex) 1717 { 1718 1720 if ( logger.isDebugEnabled()) 1721 logger.debug("Open file error", ex); 1722 1723 1725 throw new IOException ("Set file information " + name); 1726 } 1727 } 1728 1729 1738 public void truncateFile(SrvSession sess, TreeConnection tree, NetworkFile file, long size) throws IOException 1739 { 1740 1742 file.truncateFile(size); 1743 1744 if (logger.isDebugEnabled()) 1746 { 1747 logger.debug("Truncated file: \n" + 1748 " network file: " + file + "\n" + 1749 " size: " + size); 1750 } 1751 } 1752 1753 1766 public int readFile( 1767 SrvSession sess, TreeConnection tree, NetworkFile file, 1768 byte[] buffer, int bufferPosition, int size, long fileOffset) throws IOException 1769 { 1770 1772 if(file.isDirectory()) 1773 throw new AccessDeniedException(); 1774 1775 1777 int count = file.readFile(buffer, size, bufferPosition, fileOffset); 1778 1779 if ( count == -1) 1780 { 1781 1783 count = 0; 1784 } 1785 1786 if (logger.isDebugEnabled()) 1788 { 1789 logger.debug("Read bytes from file: \n" + 1790 " network file: " + file + "\n" + 1791 " buffer size: " + buffer.length + "\n" + 1792 " buffer pos: " + bufferPosition + "\n" + 1793 " size: " + size + "\n" + 1794 " file offset: " + fileOffset + "\n" + 1795 " bytes read: " + count); 1796 } 1797 return count; 1798 } 1799 1800 1810 public long seekFile(SrvSession sess, TreeConnection tree, NetworkFile file, long pos, int typ) throws IOException 1811 { 1812 throw new UnsupportedOperationException ("Unsupported: " + file + " (seek)"); 1813 } 1814 1815 1828 public int writeFile(SrvSession sess, TreeConnection tree, NetworkFile file, 1829 byte[] buffer, int bufferOffset, int size, long fileOffset) throws IOException 1830 { 1831 1833 file.writeFile(buffer, size, bufferOffset, fileOffset); 1834 1835 if (logger.isDebugEnabled()) 1837 { 1838 logger.debug("Wrote bytes to file: \n" + 1839 " network file: " + file + "\n" + 1840 " buffer size: " + buffer.length + "\n" + 1841 " size: " + size + "\n" + 1842 " file offset: " + fileOffset); 1843 } 1844 return size; 1845 } 1846 1847 1855 public NodeRef getNodeForPath(TreeConnection tree, String path) 1856 throws FileNotFoundException 1857 { 1858 1860 ContentContext ctx = (ContentContext) tree.getContext(); 1861 1862 if ( ctx.hasStateTable()) 1863 { 1864 1866 FileState fstate = ctx.getStateTable().findFileState(path); 1867 if ( fstate != null && fstate.hasNodeRef() && fstate.exists() ) 1868 { 1869 if (nodeService.exists(fstate.getNodeRef())) 1871 { 1872 return fstate.getNodeRef(); 1873 } 1874 else 1875 { 1876 ctx.getStateTable().removeFileState(path); 1877 } 1878 } 1879 } 1880 1881 1883 return cifsHelper.getNodeRef(ctx.getRootNode(), path); 1884 } 1885 1886 1894 public FileState getStateForPath(TreeConnection tree, String path) 1895 throws FileNotFoundException 1896 { 1897 1899 ContentContext ctx = (ContentContext) tree.getContext(); 1900 FileState fstate = null; 1901 1902 if ( ctx.hasStateTable()) 1903 { 1904 1906 fstate = ctx.getStateTable().findFileState(path); 1907 } 1908 1909 1911 return fstate; 1912 } 1913 1914 1920 public void treeClosed(SrvSession sess, TreeConnection tree) 1921 { 1922 } 1924 1925 1931 public void treeOpened(SrvSession sess, TreeConnection tree) 1932 { 1933 } 1935 1936 1950 public DataBuffer processIOControl(SrvSession sess, TreeConnection tree, int ctrlCode, int fid, DataBuffer dataBuf, 1951 boolean isFSCtrl, int filter) 1952 throws IOControlNotImplementedException, SMBException 1953 { 1954 1956 NetworkFile netFile = tree.findFile(fid); 1957 if ( netFile == null || netFile.isDirectory() == false) 1958 throw new SMBException(SMBStatus.NTErr, SMBStatus.NTInvalidParameter); 1959 1960 1962 if ( m_ioHandler != null) 1963 return m_ioHandler.processIOControl( sess, tree, ctrlCode, fid, dataBuf, isFSCtrl, filter); 1964 else 1965 throw new IOControlNotImplementedException(); 1966 } 1967} 1968 | Popular Tags |